Y-combinator adalah konsep ilmu komputer dari sisi "fungsional". Kebanyakan programmer tidak tahu sama sekali tentang kombinator, jika mereka pernah mendengarnya.
- Apa itu Y-combinator?
- Bagaimana cara kerja kombinator?
- Apa yang baik untuk mereka?
- Apakah mereka berguna dalam bahasa prosedural?
functional-programming
computer-science
theory
definition
combinators
Chris Ammerman
sumber
sumber
Jawaban:
Jika Anda siap membaca lama, Mike Vanier memiliki penjelasan yang bagus . Singkatnya, ini memungkinkan Anda untuk menerapkan rekursi dalam bahasa yang belum tentu mendukungnya secara asli.
sumber
Y-combinator adalah "fungsional" (fungsi yang beroperasi pada fungsi lain) yang memungkinkan rekursi, ketika Anda tidak dapat merujuk ke fungsi dari dalam dirinya sendiri. Dalam teori ilmu komputer, ia menggeneralisasikan rekursi , mengabstraksikan implementasinya, dan dengan demikian memisahkannya dari kerja aktual dari fungsi yang dimaksud. Manfaat tidak memerlukan nama waktu kompilasi untuk fungsi rekursif adalah semacam bonus. =)
Ini berlaku dalam bahasa yang mendukung fungsi lambda . The ekspresi alam berbasis lambdas biasanya berarti bahwa mereka tidak bisa menyebut diri mereka dengan nama. Dan mengatasinya dengan mendeklarasikan variabel, merujuknya, lalu menugaskan lambda padanya, untuk menyelesaikan loop referensi-diri, rapuh. Variabel lambda dapat disalin, dan variabel asli ditugaskan kembali, yang mematahkan referensi-diri.
Y-combinator sulit untuk diimplementasikan, dan sering digunakan, dalam bahasa yang diketik statis (yang sering menggunakan bahasa prosedural ), karena biasanya pembatasan pengetikan membutuhkan jumlah argumen agar fungsi yang bersangkutan diketahui pada waktu kompilasi. Ini berarti bahwa kombinator-y harus ditulis untuk setiap argumen yang perlu digunakan.
Di bawah ini adalah contoh bagaimana penggunaan dan kerja Y-Combinator, dalam C #.
Menggunakan Y-combinator melibatkan cara "tidak biasa" untuk membangun fungsi rekursif. Pertama, Anda harus menulis fungsi Anda sebagai bagian dari kode yang memanggil fungsi yang sudah ada sebelumnya, daripada fungsi itu sendiri:
Kemudian Anda mengubahnya menjadi fungsi yang membutuhkan fungsi untuk memanggil, dan mengembalikan fungsi yang melakukannya. Ini disebut fungsional, karena dibutuhkan satu fungsi, dan melakukan operasi dengannya yang menghasilkan fungsi lain.
Sekarang Anda memiliki fungsi yang mengambil fungsi, dan mengembalikan fungsi lain yang terlihat seperti faktorial, tetapi alih-alih menyebut dirinya sendiri, ia memanggil argumen yang dilewatkan ke fungsi luar. Bagaimana Anda menjadikan ini faktorial? Lewati fungsi batin itu sendiri. Y-Combinator melakukan itu, dengan menjadi fungsi dengan nama permanen, yang dapat memperkenalkan rekursi.
Daripada memanggil faktorial itu sendiri, yang terjadi adalah bahwa faktorial memanggil generator faktorial (dikembalikan oleh panggilan rekursif ke Y-Combinator). Dan tergantung pada nilai t saat ini, fungsi yang dikembalikan dari generator akan memanggil generator lagi, dengan t - 1, atau hanya mengembalikan 1, mengakhiri rekursi.
Ini rumit dan samar, tetapi semuanya bergetar pada saat run-time, dan kunci untuk kerjanya adalah "eksekusi yang ditunda", dan pemecahan rekursi untuk menjangkau dua fungsi. Batin F dilewatkan sebagai argumen , untuk dipanggil dalam iterasi berikutnya, hanya jika perlu .
sumber
fix :: (a -> a) -> a
dana
pada gilirannya bisa menjadi fungsi dari banyak argumen yang Anda inginkan. Ini berarti bahwa pengetikan statis tidak benar-benar membuat ini rumit.Saya telah mengangkat ini dari http://www.mail-archive.com/[email protected]/msg02716.html yang merupakan penjelasan yang saya tulis beberapa tahun yang lalu.
Saya akan menggunakan JavaScript dalam contoh ini, tetapi banyak bahasa lain juga akan berfungsi.
Tujuan kami adalah untuk dapat menulis fungsi rekursif dari 1 variabel menggunakan hanya fungsi 1 variabel dan tidak ada tugas, mendefinisikan sesuatu berdasarkan nama, dll. (Mengapa ini adalah tujuan kami adalah pertanyaan lain, mari kita anggap ini sebagai tantangan yang kami diberikan.) Sepertinya tidak mungkin, ya? Sebagai contoh, mari kita terapkan faktorial.
Nah langkah 1 adalah mengatakan bahwa kita bisa melakukan ini dengan mudah jika kita sedikit curang. Menggunakan fungsi 2 variabel dan tugas, kita setidaknya bisa menghindari harus menggunakan tugas untuk mengatur rekursi.
Sekarang mari kita lihat apakah kita bisa menipu lebih sedikit. Yah pertama-tama kita menggunakan tugas, tetapi kita tidak perlu. Kita cukup menulis X dan Y sebaris.
Tapi kami menggunakan fungsi 2 variabel untuk mendapatkan fungsi 1 variabel. Bisakah kita memperbaikinya? Nah pria yang cerdas dengan nama Haskell Curry memiliki trik yang rapi, jika Anda memiliki fungsi urutan yang lebih tinggi maka Anda hanya perlu fungsi 1 variabel. Buktinya adalah bahwa Anda dapat memperoleh dari fungsi 2 (atau lebih dalam kasus umum) variabel menjadi 1 variabel dengan transformasi teks murni mekanis seperti ini:
di mana ... tetap persis sama. (Trik ini disebut "currying" setelah penemunya. Bahasa Haskell juga bernama untuk Haskell Curry. File yang di bawah trivia tidak berguna.) Sekarang hanya menerapkan transformasi ini di mana-mana dan kami mendapatkan versi final kami.
Jangan ragu untuk mencobanya. waspada () yang kembali, ikat ke tombol, apa pun. Kode itu menghitung faktorial, secara rekursif, tanpa menggunakan penugasan, deklarasi, atau fungsi 2 variabel. (Tetapi mencoba melacak cara kerjanya kemungkinan membuat kepala Anda berputar. Dan menyerahkannya, tanpa derivasi, hanya sedikit diformat ulang akan menghasilkan kode yang pasti membingungkan dan membingungkan.)
Anda dapat mengganti 4 baris yang secara rekursif mendefinisikan faktorial dengan fungsi rekursif lain yang Anda inginkan.
sumber
function (n) { return builder(builder)(n);}
bukanbuilder(builder)
?Saya ingin tahu apakah ada gunanya mencoba membangun ini dari bawah ke atas. Ayo lihat. Berikut ini adalah fungsi faktorial rekursif dasar:
Mari kita refactor dan membuat fungsi baru
fact
yang mengembalikan fungsi komputasi faktorial anonim alih-alih melakukan perhitungan itu sendiri:Itu agak aneh, tetapi tidak ada yang salah dengan itu. Kami hanya membuat fungsi faktorial baru di setiap langkah.
Rekursi pada tahap ini masih cukup eksplisit. The
fact
Fungsi perlu menyadari dari nama sendiri. Mari kita parameterkan panggilan rekursif:Itu hebat, tetapi
recurser
masih perlu tahu namanya sendiri. Mari kita parameterkan juga:Sekarang, alih-alih menelepon
recurser(recurser)
secara langsung, mari kita buat fungsi pembungkus yang mengembalikan hasilnya:Kita sekarang bisa menyingkirkan
recurser
nama itu sama sekali; itu hanya argumen untuk fungsi dalam Y, yang dapat diganti dengan fungsi itu sendiri:Satu-satunya nama eksternal masih dirujuk adalah
fact
, tetapi harus jelas sekarang bahwa itu dengan mudah parameter, juga menciptakan solusi lengkap, generik,:sumber
recurser
. Tidak tahu apa yang dilakukannya, atau mengapa.recurser
Fungsi adalah langkah pertama menuju tujuan ini, karena memberikan kita versi rekursif darifact
yang tidak pernah merujuk dirinya dengan nama.function Y(recurse) { return recurse(recurse); } let factorial = Y(creator => value => { return value == 0 ? 1 : value * creator(creator)(value - 1); });
. Dan ini adalah bagaimana saya mencernanya (tidak yakin apakah itu benar): Dengan tidak secara eksplisit merujuk fungsi (tidak diizinkan sebagai kombinator ), kita dapat menggunakan dua fungsi yang diterapkan sebagian / kari (fungsi pembuat dan fungsi menghitung), dengan yang mana kita dapat membuat fungsi lambda / anonim yang mencapai rekursif tanpa perlu nama untuk fungsi penghitungan?Sebagian besar jawaban atas menggambarkan apa yang Y-Combinator adalah tetapi tidak apa itu untuk .
Combinator titik tetap digunakan untuk menunjukkan bahwa kalkulus lambda sudah selesai . Ini adalah hasil yang sangat penting dalam teori komputasi dan memberikan landasan teoritis untuk pemrograman fungsional .
Mempelajari kombinator titik tetap juga membantu saya benar-benar memahami pemrograman fungsional. Saya tidak pernah menemukan gunanya bagi mereka dalam pemrograman yang sebenarnya.
sumber
y-combinator dalam JavaScript :
Sunting : Saya belajar banyak dari melihat kode, tetapi yang ini agak sulit untuk ditelan tanpa latar belakang - maaf tentang itu. Dengan pengetahuan umum yang disajikan oleh jawaban lain, Anda dapat mulai memilah apa yang terjadi.
Fungsi Y adalah "y-combinator". Sekarang lihat
var factorial
garis di mana Y digunakan. Perhatikan bahwa Anda meneruskan fungsi ke sana yang memiliki parameter (dalam contoh ini,recurse
) yang juga digunakan nanti di fungsi dalam. Nama parameter pada dasarnya menjadi nama fungsi dalam yang memungkinkannya untuk melakukan panggilan rekursif (karena digunakanrecurse()
dalam definisi itu.) Y-kombinator melakukan keajaiban dalam mengaitkan fungsi dalam yang anonim dengan nama parameter fungsi yang diteruskan ke Y.Untuk penjelasan lengkap tentang bagaimana Y melakukan sihir, lihat artikel yang terhubung (bukan oleh saya btw.)
sumber
arguments.callee
tidak diperbolehkan dalam Mode Ketat: developer.mozilla.org/en/JavaScript/…(function fact(n){ return n <= 1? 1 : n * fact(n-1); })(5)
Untuk programmer yang belum menemukan pemrograman fungsional secara mendalam, dan tidak peduli untuk memulainya sekarang, tetapi sedikit ingin tahu:
Kombinator Y adalah rumus yang memungkinkan Anda menerapkan rekursi dalam situasi di mana fungsi tidak dapat memiliki nama tetapi dapat diedarkan sebagai argumen, digunakan sebagai nilai pengembalian, dan didefinisikan dalam fungsi lainnya.
Ia bekerja dengan melewatkan fungsi itu sendiri sebagai argumen, sehingga bisa memanggil dirinya sendiri.
Ini adalah bagian dari kalkulus lambda, yang benar-benar matematika tetapi secara efektif merupakan bahasa pemrograman, dan sangat mendasar bagi ilmu komputer dan terutama untuk pemrograman fungsional.
Nilai praktis sehari-hari dari penggabung Y terbatas, karena bahasa pemrograman cenderung memberi Anda fungsi.
Jika Anda perlu mengidentifikasinya di barisan polisi, sepertinya ini:
Anda biasanya dapat menemukannya karena diulang
(λx.f (x x))
.The
λ
simbol huruf Yunani lambda, yang memberikan lambda kalkulus namanya, dan ada banyak(λx.t)
hal gaya karena itulah yang lambda kalkulus terlihat seperti.sumber
U x = x x
,Y = U . (. U)
(menyalahgunakan notasi mirip Haskell). TKI, dengan kombinator yang tepatY = BU(CBU)
,. JadiYf = U (f . U) = (f . U) (f . U) = f (U (f . U)) = f ((f . U) (f . U))
,.Rekursi anonim
Combinator titik tetap adalah fungsi tingkat tinggi
fix
yang menurut definisi memenuhi kesetaraanfix f
merupakan solusix
untuk persamaan titik tetapFaktorial dari bilangan alami dapat dibuktikan dengan
Menggunakan
fix
, bukti konstruktif sewenang-wenang atas fungsi-fungsi umum / μ-rekursif dapat diturunkan tanpa referensialitas diri yang tidak simultan.dimana
seperti yang
Ini bukti resmi itu
secara metodis menggunakan kesetaraan combinator titik tetap untuk penulisan ulang
Kalkulus Lambda
The untyped lambda kalkulus formalisme terdiri dalam tata bahasa bebas konteks
di mana
v
rentang variabel, bersama dengan aturan pengurangan beta dan etaPengurangan beta menggantikan semua kemunculan variabel bebas
x
dalam tubuh abstraksi ("fungsi")B
dengan ekspresi ("argumen")E
. Reduksi Eta menghilangkan abstraksi yang berlebihan. Kadang-kadang dihilangkan dari formalisme. Sebuah tereduksi ekspresi, yang tidak ada aturan pengurangan berlaku, dalam yang normal atau bentuk kanonik .adalah singkatan
(aneka ragam abstraksi),
adalah singkatan
(aplikasi-asosiasi kiri),
dan
adalah alpha-setara .
Abstraksi dan aplikasi adalah dua-satunya "bahasa primitif" dari kalkulus lambda, tetapi mereka memungkinkan pengkodean data kompleks kompleks dan operasi.
Angka-angka Gereja adalah pengkodean bilangan alami yang mirip dengan alami-aksiomatik Peano.
Bukti formal itu
menggunakan aturan penulisan ulang reduksi beta:
Combinators
Dalam kalkulus lambda, kombinator adalah abstraksi yang tidak mengandung variabel bebas. Paling sederhana
I
:, penggabung identitasisomorfik dengan fungsi identitas
Combinator seperti itu adalah operator primitif dari calculin combinator seperti sistem SKI.
Pengurangan beta tidak sangat normal ; tidak semua ekspresi yang dapat direduksi, “redexes”, konvergen ke bentuk normal di bawah reduksi beta. Contoh sederhana adalah aplikasi divergen
ω
kombinator omegauntuk dirinya sendiri:
Pengurangan subekspresi paling kiri ("kepala") diprioritaskan. Pesanan aplikatif menormalkan argumen sebelum substitusi, pesanan normal tidak. Kedua strategi ini analog dengan evaluasi yang bersemangat, misalnya C, dan evaluasi malas, misalnya Haskell.
menyimpang di bawah pengurangan beta aplikasi-order bersemangat
karena dalam semantik yang ketat
tetapi konvergen di bawah reduksi beta normal-order malas
Jika ekspresi memiliki bentuk normal, reduksi orde normal beta akan menemukannya.
Y
Properti penting dari
Y
combinator titik tetapdiberikan oleh
Kesetaraan
isomorfik untuk
Kalkulus lambda yang tidak diketik dapat menyandikan bukti konstruktif sewenang-wenang atas fungsi umum / μ-rekursif.
(Multiplikasi tertunda, pertemuan)
Untuk kalkulus lambda Gereja yang tidak diketik, telah terbukti ada tak terhingga jumlah tak terhitung dari kombinator titik tetap
Y
.Pengurangan beta orde normal membuat kalkulus lambda tanpa tulisan yang tidak dibatasi menjadi sistem penulisan ulang Turing-complete.
Di Haskell, kombinator titik tetap dapat diterapkan secara elegan
Kemalasan Haskell menjadi normal sebelum semua subekspresi dievaluasi.
sumber
λ x . x
, apa kabar Anda hari ini?Jawaban lain memberikan jawaban yang cukup ringkas untuk ini, tanpa satu fakta penting: Anda tidak perlu menerapkan kombinator titik tetap dalam bahasa praktis apa pun dengan cara berbelit-belit ini dan melakukan hal itu tidak memiliki tujuan praktis (kecuali "lihat, saya tahu apa kombinator Y adalah"). Ini adalah konsep teoretis yang penting, tetapi memiliki sedikit nilai praktis.
sumber
Berikut ini adalah implementasi JavaScript dari Y-Combinator dan fungsi faktorial (dari artikel Douglas Crockford, tersedia di: http://javascript.crockford.com/little.html ).
sumber
Y-Combinator adalah nama lain untuk kapasitor fluks.
sumber
Saya telah menulis semacam "panduan idiot" kepada Y-Combinator di Clojure dan Skema untuk membantu saya memahami hal itu. Mereka dipengaruhi oleh materi dalam "The Little Schemer"
Dalam Skema: https://gist.github.com/z5h/238891
atau Clojure: https://gist.github.com/z5h/5102747
Kedua tutorial adalah kode yang diselingi dengan komentar dan harus dipotong & dapat ditempel ke editor favorit Anda.
sumber
Sebagai pemula untuk kombinator, saya menemukan artikel Mike Vanier (terima kasih Nicholas Mancuso) sangat membantu. Saya ingin menulis ringkasan, selain mendokumentasikan pemahaman saya, jika bisa membantu beberapa orang lain saya akan sangat senang.
Dari Crappy ke Less Crappy
Menggunakan faktorial sebagai contoh, kami menggunakan
almost-factorial
fungsi berikut untuk menghitung faktorial angkax
:Dalam pseudo-code di atas,
almost-factorial
take in functionf
and numberx
(almost-factorial
is curried, sehingga dapat dilihat sebagai fungsi takef
dan mengembalikan fungsi 1-arity).Ketika
almost-factorial
menghitung faktorialx
, ia mendelegasikan perhitungan faktorial untukx - 1
berfungsif
dan mengakumulasikan hasil itu denganx
(dalam hal ini, mengalikan hasil dari (x - 1) dengan x).Hal ini dapat dilihat sebagai
almost-factorial
mengambil dalam versi jelek dari fungsi faktorial (yang hanya dapat menghitung sampai angkax - 1
) dan mengembalikan versi faktorial yang kurang jelek (yang menghitung sampai angkax
). Seperti dalam formulir ini:Jika kita berulang kali melewatkan versi faktorial yang kurang jelek
almost-factorial
, kita akhirnya akan mendapatkan fungsi faktorial yang kita inginkanf
. Di mana itu dapat dianggap sebagai:Titik perbaikan
Fakta yang
almost-factorial f = f
berartif
adalah titik perbaikan fungsialmost-factorial
.Ini adalah cara yang sangat menarik untuk melihat hubungan fungsi-fungsi di atas dan itu adalah momen aha bagi saya. (harap baca posting Mike tentang titik perbaikan jika Anda belum)
Tiga fungsi
Untuk menggeneralisasi, kami memiliki non-rekursif fungsi
fn
(seperti kami hampir-faktorial), kita memiliki nya fix-titik fungsifr
(seperti f kami), lalu apaY
yang dilakukannya adalah ketika Anda memberikanY
fn
,Y
mengembalikan fungsi fix-titikfn
.Jadi dalam ringkasan (disederhanakan dengan asumsi
fr
hanya membutuhkan satu parameter;x
berdegenerasi kex - 1
,x - 2
... dalam rekursi):fn
:def fn fr x = ...accumulate x with result from (fr (- x 1))
, ini adalah hampir-berguna fungsi - meskipun kita tidak dapat menggunakanfn
secara langsung dix
, itu akan berguna segera. Non-rekursif inifn
menggunakan fungsifr
untuk menghitung hasilnyafn fr = fr
,fr
adalah titik perbaikan darifn
,fr
adalah berguna funciton, kita dapat menggunakanfr
padax
untuk mendapatkan hasil kamiY fn = fr
,Y
mengembalikan titik perbaikan suatu fungsi, mengubah fungsiY
kami yang hampir berguna fungsifn
menjadi bergunafr
Berasal
Y
(tidak termasuk)Saya akan melewatkan derivasi
Y
dan pergi ke pemahamanY
. Posting Mike Vainer memiliki banyak detail.Bentuk dari
Y
Y
didefinisikan sebagai (dalam kalkulus lambda format ):Jika kita mengganti variabel
s
di sebelah kiri fungsi, kita dapatkanJadi memang, hasil dari
(Y f)
adalah titik perbaikan darif
.Kenapa
(Y f)
berhasil?Bergantung pada tanda tangan
f
,(Y f)
dapat menjadi fungsi dari arity apa pun, untuk menyederhanakan, mari kita asumsikan(Y f)
hanya mengambil satu parameter, seperti fungsi faktorial kami.sejak itu
fn fr = fr
, kami melanjutkanperhitungan rekursif berakhir ketika yang paling dalam
(fn fr 1)
adalah kasus dasar danfn
tidak digunakanfr
dalam perhitungan.Melihat
Y
lagi:Begitu
Bagi saya, bagian magis dari pengaturan ini adalah:
fn
danfr
saling tergantung satu sama lain:fr
'membungkus'fn
di dalam, setiap kalifr
digunakan untuk menghitungx
, itu 'memunculkan' ('mengangkat'?)fn
dan mendelegasikan perhitungan itufn
(lewat sendirifr
danx
); di sisi lain,fn
tergantungfr
dan digunakanfr
untuk menghitung hasil dari masalah yang lebih kecilx-1
.fr
digunakan untuk mendefinisikanfn
(saatfn
digunakanfr
dalam operasinya), yang sebenarnyafr
belum didefinisikan.fn
yang mendefinisikan logika bisnis nyata. Berdasarkanfn
,Y
menciptakanfr
- fungsi pembantu dalam bentuk tertentu - untuk memfasilitasi perhitunganfn
secara rekursif .Itu membantu saya memahami
Y
cara ini saat ini, semoga membantu.BTW, saya juga menemukan buku Pengantar Pemrograman Fungsional Melalui Lambda Calculus sangat baik, saya hanya bagian dari itu dan fakta bahwa saya tidak bisa mendapatkan kepala saya di
Y
dalam buku membawa saya ke posting ini.sumber
Berikut adalah jawaban untuk pertanyaan asli , yang disusun dari artikel (yang bernilai layak dibaca) yang disebutkan dalam jawaban oleh Nicholas Mancuso , serta jawaban lain:
Y-combinator adalah "fungsional" (atau fungsi tingkat tinggi - fungsi yang beroperasi pada fungsi lain) yang mengambil argumen tunggal, yang merupakan fungsi yang tidak rekursif, dan mengembalikan versi fungsi yang rekursif.
Agak rekursif =), tetapi definisi yang lebih mendalam:
Combinator - hanyalah ekspresi lambda tanpa variabel bebas.
Variabel bebas - adalah variabel yang bukan variabel terikat.
Bound variable - variabel yang terkandung di dalam tubuh ekspresi lambda yang memiliki nama variabel sebagai salah satu argumennya.
Cara lain untuk berpikir tentang ini adalah bahwa kombinator adalah ekspresi lambda, di mana Anda dapat mengganti nama kombinator dengan definisi di mana-mana ia ditemukan dan memiliki semuanya masih berfungsi (Anda akan masuk ke loop tak terbatas jika kombinator akan mengandung referensi untuk dirinya sendiri, di dalam tubuh lambda).
Y-combinator adalah combinator titik tetap.
Titik tetap dari suatu fungsi adalah elemen dari domain fungsi yang dipetakan ke dirinya sendiri oleh fungsi.
Artinya,
c
adalah titik tetap dari fungsif(x)
jikaf(c) = c
Ini berarti
f(f(...f(c)...)) = fn(c) = c
Contoh di bawah ini menganggap pengetikan kuat + dinamis :
La-combinator Y (normal-order):
Definisi ini berlaku untuk bahasa dengan evaluasi lazy (juga: ditunda, sesuai kebutuhan) - strategi evaluasi yang menunda evaluasi ekspresi hingga nilainya diperlukan.
Ini artinya, untuk fungsi yang diberikan
f
(yang merupakan fungsi non-rekursif), fungsi rekursif yang sesuai dapat diperoleh terlebih dahulu dengan menghitungλx.f(x x)
, dan kemudian menerapkan ekspresi lambda ini ke dirinya sendiri.Ketat (aplikatif-order) Y-combinator:
Definisi ini berlaku untuk bahasa dengan evaluasi ketat (juga: bersemangat, serakah) - strategi evaluasi di mana ekspresi dievaluasi segera setelah terikat pada variabel.
Sama seperti malas di alamnya, ia hanya memiliki
λ
pembungkus tambahan untuk menunda evaluasi tubuh lambda. Saya telah mengajukan pertanyaan lain , yang agak terkait dengan topik ini.Dicuridipinjam dari jawaban oleh Chris Ammerman : Y-combinator menggeneralisasi rekursi, mengabstraksikan implementasinya, dan dengan demikian memisahkannya dari kerja sebenarnya dari fungsi yang dimaksud.Meskipun, Y-combinator memiliki beberapa aplikasi praktis, itu terutama konsep teoretis, pemahaman yang akan memperluas visi Anda secara keseluruhan dan, kemungkinan, akan meningkatkan keterampilan analitis dan pengembang Anda.
Seperti yang dikatakan oleh Mike Vanier : dimungkinkan untuk mendefinisikan kombinator Y dalam banyak bahasa yang diketik secara statis, tetapi (setidaknya dalam contoh yang saya lihat) definisi seperti itu biasanya memerlukan beberapa jenis peretasan yang tidak jelas, karena kombinator Y sendiri tidak t memiliki tipe statis langsung. Itu di luar cakupan artikel ini, jadi saya tidak akan menyebutkannya lebih lanjut
Dan seperti yang disebutkan oleh Chris Ammerman : sebagian besar bahasa prosedural memiliki pengetikan statis.
Jadi jawab yang ini - tidak juga.
sumber
Y-combinator mengimplementasikan rekursi anonim. Jadi, bukannya
Anda dapat melakukan
tentu saja, y-combinator hanya berfungsi dalam bahasa panggilan-dengan-nama. Jika Anda ingin menggunakan ini dalam bahasa panggilan-menurut-nilai normal apa pun, maka Anda akan memerlukan z-combinator terkait (y-combinator akan berbeda / infinite-loop).
sumber
Combinator titik tetap (atau operator titik tetap) adalah fungsi tingkat tinggi yang menghitung titik tetap fungsi lainnya. Operasi ini relevan dalam teori bahasa pemrograman karena memungkinkan implementasi rekursi dalam bentuk aturan penulisan ulang, tanpa dukungan eksplisit dari mesin runtime bahasa. (src Wikipedia)
sumber
Operator ini dapat menyederhanakan hidup Anda:
Maka Anda menghindari fungsi ekstra:
Akhirnya, Anda menelepon
fac(5)
.sumber
Saya pikir cara terbaik untuk menjawab ini adalah dengan memilih bahasa, seperti JavaScript:
Sekarang tulis ulang sehingga tidak menggunakan nama fungsi di dalam fungsi, tetapi masih menyebutnya secara rekursif.
Satu-satunya tempat nama fungsi
factorial
harus dilihat adalah di situs panggilan.Petunjuk: Anda tidak bisa menggunakan nama fungsi, tetapi Anda bisa menggunakan nama parameter.
Kerjakan masalahnya. Jangan mencarinya. Setelah Anda menyelesaikannya, Anda akan memahami masalah apa yang dipecahkan oleh kombinator-y.
sumber