• Tidak ada hasil yang ditemukan

Abstraksi Lamda (Lambda Abstractions)

Dalam dokumen Buku bhs pemrograman Q Equational 2018 (Halaman 115-119)

10 fungsi Built-In

10.6 Abstraksi Lamda (Lambda Abstractions)

Mulai dari Q 7.1, format khusus lamda kini merupakan suatu fungsi built-in yang

mengembalikan suatu obyek fungsi “yang di-compile” yang diwakili oleh type fungsi built-in yang baru. Penawaran ini mencapai lebih baik dibanding implementasi yang sebelumnya di dalam standard library yang didasarkan pada combinatorial kalkulus. Lebih dari itu, sintaks \X.Y sekarang dapat digunakan sebagai suatu stenografi(shorthand) menyenangkan untuk suatu aplikasi lamda X Y, lihat Bagian 6.4.8 [Lamda dan Ungkapan Bersyarat (Conditional Expressions)], halaman 47.

Kedua argument lamda adalah special/khusus. Argument yang pertama X menandakan suatu ungkapan untuk diadu dengan parameter nyata dari fungsi manakala diterapkan. Argument yang kedua Y adalah badan dari abstraksi lamda. Manakala suatu fungsi lamda diberlakukan bagi suatu argument Z, Z yang pertama diadu dengan pola X dan variabel (bebas) dalam X harus bersesuaian dengan nilai-nilai di dalam Z. Pola mempertemukan (matching) dilakukan di dalam cara yang sama perihal sisi left-hand dari suatu penyamaan; khususnya, pola non-linier (yang berisi suatu variabel lebih dari sekali) dan variabel tanpa nama bekerja seperti yang diharapkan. Jika pertandingan (match) gagal maka aplikasi dari fungsi lamda juga gagal. Jika tidak badan dari lamda dievaluasi, dengan variabel dari pola digantikan dengan nilai-nilai bersesuaian mereka, dan menghasilkan format normal yang dikembalikan sebagai nilai dari aplikasi lamda. Seperti di pelepasan/release sebelumnya, fungsi lamda harus mengetahui format khusus lain yang melaksanakan variabel bindings (mengikat) sedemikian sehingga constructs ini dapat diperluas secara berulang. Untuk yang akhir ini, seperti fungsi “lamda-like” harus

dideklarasikan dari sebagai anggota dari suatu type yang diperoleh dari type lamda yang sudah dikenal, dan format khusus lambdax yang sudah dikenal harus dimuati berlebihan (overloaded) seperti, ketika berlaku untuk suatu ungkapan yang menyertakan fungsi lamda-like, [itu] mengembalikan suatu perluasan yang dikutip menyangkut constructs dalam kaitan dengan lamda. Contoh untuk ini dapat ditemukan di dalam modul standard library cond.q.

Contoh

Abstraksi lamda sederhana berikut dapat digunakan untuk menandakan suatu fungsi yang mana membentuk bujur sangkar (squares) argument nya dengan mengalikannya dengan dirinya sendiri. (dalam berikut ini kita menggunakan notasi \X.Y yang biasa dalam keseluruhannya, maka contoh ini ditulis sebagai \X.X*X. Tetapi catat bahwa ini hanya “syntactic sugar” untuk

suatu aplikasi fungsi lamda, lamda X (X*X) dalam hal ini.)

==> \X.X*X \X1 . X1*X1

==> _ 5 25

Dalam contoh ini pola lamda hanya suatu variabel tunggal, yang selalu mempertemukan (matches).

Fungsi lamda Multi-Argument dapat diciptakan menggunakan lamda bersarang (nested lambdas):

==> \X.\Y.(1-X)*Y \X1 . \X2 . (1-X1)*X2 ==> _ 0.9 0.5

0.05

Untuk kenyamanan, notasi \X1 X2... . Y disajikan sebagai stenografi (shorthand) untuk \X1 . \X2... . Y:

==> \X Y.(1-X)*Y \X1 . \X2 . (1-X1)*X2 ==> _ 0.9 0.5

0.05

Juga catat bahwa di dalam suatu ungkapan lamda tersarang masing-masing variabel terikat oleh lamda yang paling dalam di mana itu terjadi:

==> \X.(\X.X*X) (X+1) \X1 . (\X2 . X2*X2) (X1+1) ==> _ 2

9

Lebih dari itu, variabel lamda selalu terikat secara statis, seperti ditentukan oleh konteks lexical. Sebagai contoh, pertimbangkan:

==> def F = \X.\Y.(1-X)*Y, G = \Y.(1-X)*Y, H = \X.~G ==> F; H \X1 . \X2 . (1-X1)*X2 \X1 . \X2 . (1-X)*X2 ==> F 0.9 0.5; H 0.9 0.5 0.05 (1-X)*0.5

Catat bahwa di dalam fungsi G variabel X memjadi bebas, dan karenanya pegangan yang sama untuk H.

Pada sisi lain, di dalam fungsi F variabel X terikat oleh lamda yang paling jauh.

Argument lamda dapat juga merupakan suatu pola untuk diadu dengan parameter yang nyata ketika fungsi diterapkan:

==> \(X,Y).(1-X)*Y \(X1,X2) . (1-X1)*X2 ==> _ (0.9,0.5)

0.05

==> \[X|Xs].Xs \[X1|X2] . X2 ==> _ [1,2,3] [2,3]

Jika suatu pertandingan gagal maka aplikasi dari fungsi lamda juga gagal:

==> (\[X|Xs].Xs) [] (\[X1|X2] . X2) []

variabel tanpa nama dan pola nonlinear juga bekerja seperti yang diharapkan:

==> \[_|Xs].Xs \[X1|X2] . X2 ==> _ [1,2,3] [2,3] ==> \[X,X|Xs].Xs \[X1,X1|X2] . X2 ==> _ [1,1,2] [2] ==> (\[X,X|Xs].Xs) [1,2,3] (\[X1,X1|X2] . X2) [1,2,3] ==> (\[_,_|Xs].Xs) [1,2,3] [3]

Tetapi catat bahwa di dalam suatu lamda multi-argument, pola argument yang berbeda akan ditarungkan dengan bebas dari satu sama lain. Ini karena suatu abstraksi lamda seperti \X X.X*X adalah setara dengan \X.\X.X*X, sehingga variabel X di dalam badan benar-benar harus argument lamda yang kedua (yang mana kepunyaan lamda yang paling dalam) dan argument yang pertama tidak pernah digunakan:

==> \X X.X*X \X1 . \X2 . X2*X2 ==> _ 1 2

4

Hal ini terlihat berlawanan dengan suatu definisi equational seperti foo X X = X*X di mana keseluruhan sisi left-hand mengambil bagian di dalam proses mempertemukan.

Lamda dapat juga digunakan untuk menggantikan variabel di dalam format khusus seperti operator tanda kutip:

==> (\X.’(X+1)) (2*3) ’(6+1)

Tetapi catat bahwa selama pola dan badan lamda adalah argument khusus, parameter yang nyata diharapkan oleh fungsi lamda tidak khusus. Dengan begitu nilai 2*3 di dalam contoh di atas dievaluasi sebelum digantikan untuk variabel X. Jika kamu ingin mencegah argument lamda dari yang sedang dievaluasi, kamu harus melindunginya dengan suatu format khusus (e.g., suatu

tanda kutip), dan mengekstrak nilai untuk digunakan di badan lamda dengan menggunakan suatu pola yang sesuai:

==> (\’X.’(X+1)) ’(2*3) ’(2*3+1)

Lamda lawan Persamaan

Haskell dan ML para programmer perlu juga sadar bahwa lamda hanya suatu fungsi biasa di dalam Q (sekalipun hanya suatu format khusus yang terjadi untuk beroperasi pada ungkapan simbolis), maka tidak ada koneksi/hubungan antara variabel bindings (ikatan) dilakukan manakala mempertemukan sisi lefthand penyamaan, dan macam variabel binding dilakukan oleh fungsi lamda. Sesungguhnya, untuk interpreter Q variabel di dalam suatu pola lamda adalah tidak ada yang khusus sama sekali; pada level definisi equational mereka hanya variable bebas!

Ini memimpin ke arah suatu perangkap umum, yakni bahwa kamu mungkin secara kebetulan mencoba untuk menggunakan kembali suatu simbol variabel yang terikat oleh sisi left-hand (atau di dalam suatu ketentuan berada) dari suatu penyamaan sebagai variabel lamda, yang akan memiliki efek mengejutkan. Sebagai contoh, pertimbangkan definisi berikut:

foo X = (\X.2*X+1) (X+1);

Di dalam Haskell, suatu definisi equational seperti satu di atas (yaitu., sesuatu seperti foo x = (\x->2*x+1) (x+1)) yang sangat utama dipertimbangkan setara dengan suatu abstraksi lamda yang bersesuaian (\x-> (\x->2*x+1) (x+1) dalam hal ini), dan karenanya foo 99 akan mengevaluasi ke 2*(99+1)+1= 201. Bukan juga di dalam Q. Apa yang benar-benar terjadi di sini adalah bahwa foo 99 mengurangi (\99.2*99+1) (99+1) karena sisi left-hand variabel X digantikan oleh nilai 99 di mana terjadi pada sisi right-hand dari penyamaan. Untuk mendapatkan perilaku yang benar di dalam contoh ini kamu dapat menggantikan yang manapun variabel lamda dengan suatu simbol yang tidak terikat oleh penyamaan, atau menggunakan suatu deklarasi variabel inline untuk melepaskan variabel lamda, maka seperti:

foo X = (\var X.2*var X+1) (X+1);

Tentu saja kamu dapat juga hanya menggambarkan foo nya sendiri sebagai suatu fungsi lamda:

foo = \X . (\X.2*X+1) (X+1);

Selama ini adalah canggung sempit dan mungkin memerlukan banyak waktu untuk dapat digunakan, cara Q dalam menerapkan lamda mempunyai keuntungan utama bahwa abstraksi lamda adalah first-class citizens di dalam bahasa (sesungguhnya mereka hanya ungkapan biasa) dan karenanya kamu dapat dengan mudah memanipulasi/menggerakkannya pada suatu tingkatan/level simbolis. Ini membuat [itu] mungkin untuk menerapkan constructs seperti pengertian list(cf. Bagian 11.8 [Kondisi Bersyarat dan Pengertian (Conditionals and Comprehensions)], halaman 127), yang bersandar pada lamda untuk kepentingan melakukan variabel bindings, tanpa keharusan untuk memohon pertolongan builtins tambahan atau suatu tingkat/level penafsiran/interpretation ekstra.

Seperti yang telah disebutkan, nilai yang dikembalikan oleh lamda benar-benar suatu format

“yang di-compile” dari abstraksi lamda yang diberikan, yang diwakili sebagai suatu obyek “yang buram (opaque)” dari type fungsi built-in. Meskipun demikian interpreter dapat mencetak object ini di dalam suatu format yang dapat selalu diuraikan kembali untuk merekonstruksi fungsi yang sama. (nama variabel yang asli berada di pola lamda yang hilang di dalam proses ini, bagaimanapun. Inilah alasan kenapa kamu akan lihat nama-nama variabel umum seperti X1, X2, dll. di dalam penyajian yang dicetak.)

Kita juga panggil fungsi object lamda seperti itu, untuk mencirikannya dari abstraksi lamda, yaitu, ungkapan lamda dari yang mana mereka dihitung.

Karena fungsi lamda mempunyai suatu penyajian tercetak di dalam Q, mereka dapat juga ditulis ke dan membaca kembali dari penyimpanan (storage) eksternal. Lebih dari itu, selama Object fungsi tidak bisa diperiksa dalam suatu pertunjukan langsung, kamu dapat dengan mudah mencapai efek yang sama menggunakan str dan valq (cf. Bagian 10.4 [Fungsi Konversi], halaman 95), yang mengijinkan kamu untuk mendapatkan kembali pola dan badan lamda dari suatu fungsi lamda:

==> def fac = \N.if N>0 then N*fac (N-1) else 1 ==> def ’(\X.Y) = valq (str fac); X; Y

X1

if X1>0 then X1*fac (X1-1) else 1

Dua fungsi lamda dapat dipertimbangkan “sama” jika mereka mencetak (print out) yang sama

di dalam interpreter.

Sesungguhnya, pembuka standard overloads‘=’ dan ‘<>’ pada Object fungsi maka, lihat Bab 11

[Standard Library], halaman 113. Dalam kontras, dua Object fungsi secara sintaks sama hanya jika mereka benar-benar object yang sama:

==> def fac = \N.if N>0 then N*fac (N-1) else 1 ==> eq fac fac

true

==> eq fac (\N.if N>0 then N*fac (N-1) else 1) false

==> fac = (\N.if N>0 then N*fac (N-1) else 1) True

Dalam dokumen Buku bhs pemrograman Q Equational 2018 (Halaman 115-119)