TL; DR Seperti yang ditunjukkan orang lain: notasi lambda hanyalah cara untuk mendefinisikan fungsi tanpa dipaksa untuk memberi mereka nama.
Versi panjang
Saya ingin menguraikan sedikit tentang topik ini karena saya merasa sangat menarik. Penafian: Saya sudah lama mengikuti kalkulus lambda. Jika seseorang dengan pengetahuan yang lebih baik menemukan kesalahan dalam jawaban saya, jangan ragu untuk membantu saya meningkatkannya.
Mari kita mulai dengan ekspresi, misalnya 1 + 2dan x + 2. Literal seperti 1dan 2disebut konstanta karena terikat dengan nilai tetap tertentu.
Identifier seperti xdisebut variabel dan untuk mengevaluasinya Anda harus mengikatnya ke beberapa nilai terlebih dahulu. Jadi, pada dasarnya Anda tidak dapat mengevaluasi x + 1selama Anda tidak tahu apa xitu.
Notasi lambda menyediakan skema untuk mengikat nilai input spesifik ke variabel. Sebuah ekspresi lambda dapat dibentuk dengan menambahkan λx .di depan sebuah ekspresi yang ada, misalnya λx . x + 1. Variabel xdikatakan bebas di x + 1dan terikat diλx . x + 1
Bagaimana ini membantu dalam mengevaluasi ekspresi? Jika Anda memberi nilai pada ekspresi lambda, seperti itu
(λx . x + 1) 2
maka Anda dapat mengevaluasi seluruh ekspresi dengan mengganti (mengikat) semua kemunculan variabel xdengan nilai 2:
(λx . x + 1) 2
2 + 1
3
Jadi, notasi lambda menyediakan mekanisme umum untuk mengikat hal-hal ke variabel yang muncul dalam blok ekspresi / program. Bergantung pada konteksnya, ini menciptakan konsep yang sangat berbeda dalam bahasa pemrograman:
- Dalam bahasa murni fungsional seperti Haskell, ekspresi lambda mewakili fungsi dalam arti matematika: nilai input disuntikkan ke dalam tubuh lambda dan nilai output dihasilkan.
- Dalam banyak bahasa (misalnya JavaScript, Python, Skema) mengevaluasi tubuh ekspresi lambda dapat memiliki efek samping. Dalam hal ini orang dapat menggunakan istilah prosedur untuk menandai perbedaan fungsi murni.
Terlepas dari perbedaan, notasi lambda adalah tentang mendefinisikan parameter formal dan mengikatnya ke parameter aktual.
Langkah selanjutnya, adalah memberi fungsi / prosedur nama. Dalam beberapa bahasa, fungsi adalah nilai seperti yang lain, sehingga Anda dapat memberi nama fungsi sebagai berikut:
(define f (lambda (x) (+ x 1))) ;; Scheme
f = \x -> x + 1 -- Haskell
val f: (Int => Int) = x => x + 1 // Scala
var f = function(x) { return x + 1 } // JavaScript
f = lambda x: x + 1 # Python
Seperti yang ditunjukkan Eli Barzilay, definisi ini hanya mengikat nama fpada suatu nilai, yang kebetulan merupakan suatu fungsi. Jadi dalam hal ini, fungsi, angka, string, karakter adalah semua nilai yang dapat diikat ke nama dengan cara yang sama:
(define n 42) ;; Scheme
n = 42 -- Haskell
val n: Int = 42 // Scala
var n = 42 // JavaScript
n = 42 # Python
Dalam bahasa ini Anda juga dapat mengikat fungsi ke nama menggunakan notasi yang lebih akrab (tapi setara):
(define (f x) (+ x 1)) ;; Scheme
f x = x + 1 -- Haskell
def f(x: Int): Int = x + 1 // Scala
function f(x) { return x + 1 } // JavaScript
def f(x): return x + 1 # Python
Beberapa bahasa, misalnya C, hanya mendukung notasi terakhir untuk mendefinisikan (bernama) fungsi.
Penutupan
Beberapa pengamatan terakhir tentang penutupan . Pertimbangkan ungkapannya x + y. Ini mengandung dua variabel gratis. Jika Anda mengikat xmenggunakan notasi lambda Anda mendapatkan:
\x -> x + y
Ini bukan (belum) fungsi karena masih berisi variabel gratis y. Anda bisa membuat fungsi dengan mengikat yjuga:
\x -> \y -> x + y
atau
\x y -> x + y
yang sama dengan +fungsinya.
Tetapi Anda dapat mengikat, katakanlah, ydengan cara lain (*):
incrementBy y = \x -> x + y
Hasil penerapan kenaikan fungsi Dengan angka adalah penutupan, yaitu fungsi / prosedur yang badannya berisi variabel bebas (misalnya y) yang telah terikat pada nilai dari lingkungan di mana penutupan didefinisikan.
Begitu incrementBy 5juga fungsi (penutupan) yang menambah angka dengan 5.
CATATAN (*)
Saya sedikit curang di sini:
incrementBy y = \x -> x + y
setara dengan
incrementBy = \y -> \x -> x + y
jadi mekanisme pengikatannya sama. Secara intuitif, saya berpikir tentang penutupan sebagai mewakili sebagian dari ekspresi lambda yang lebih kompleks. Ketika representasi ini dibuat, beberapa binding dari ekspresi ibu telah ditetapkan dan penutupan menggunakannya nanti ketika akan dievaluasi / dipanggil.