Currying mengkonversi fungsi tunggal n argumen ke n fungsi dengan satu argumen masing-masing. Diberikan fungsi berikut:
function f(x,y,z) { z(x(y));}
Saat kari, menjadi:
function f(x) { lambda(y) { lambda(z) { z(x(y)); } } }
Untuk mendapatkan aplikasi lengkap dari f (x, y, z), Anda perlu melakukan ini:
f(x)(y)(z);
Banyak bahasa fungsional memungkinkan Anda menulis f x y z
. Jika Anda hanya memanggil f x y
atau f (x) (y) maka Anda mendapatkan fungsi yang diterapkan sebagian — nilai kembali adalah penutupan lambda(z){z(x(y))}
dengan nilai x dan y yang diteruskan f(x,y)
.
Salah satu cara untuk menggunakan aplikasi parsial adalah dengan mendefinisikan fungsi sebagai aplikasi parsial dari fungsi umum, seperti lipatan :
function fold(combineFunction, accumulator, list) {/* ... */}
function sum = curry(fold)(lambda(accum,e){e+accum}))(0);
function length = curry(fold)(lambda(accum,_){1+accum})(empty-list);
function reverse = curry(fold)(lambda(accum,e){concat(e,accum)})(empty-list);
/* ... */
@list = [1, 2, 3, 4]
sum(list) //returns 10
@f = fold(lambda(accum,e){e+accum}) //f = lambda(accumulator,list) {/*...*/}
f(0,list) //returns 10
@g = f(0) //same as sum
g(list) //returns 10
Cara termudah untuk melihat perbedaannya adalah dengan mempertimbangkan contoh nyata . Mari kita asumsikan bahwa kita memiliki fungsi
Add
yang mengambil 2 angka sebagai input dan mengembalikan angka sebagai output, misalnyaAdd(7, 5)
mengembalikan12
. Pada kasus ini:Menerapkan sebagian fungsi
Add
dengan suatu nilai7
akan memberi kita fungsi baru sebagai output. Fungsi itu sendiri membutuhkan 1 angka sebagai input dan menghasilkan angka. Dengan demikian:Jadi kita bisa melakukan ini:
Currying fungsi
Add
akan memberi kita fungsi baru sebagai output. Fungsi itu sendiri memakan waktu 1 angka sebagai input dan output belum fungsi baru yang lain. Fungsi ketiga itu kemudian mengambil 1 angka sebagai input dan mengembalikan angka sebagai output. Dengan demikian:Jadi kita bisa melakukan ini:
Dengan kata lain, "currying" dan "aplikasi parsial" adalah dua fungsi yang sama sekali berbeda. Currying mengambil tepat 1 input, sedangkan aplikasi parsial membutuhkan 2 (atau lebih) input.
Meskipun keduanya mengembalikan fungsi sebagai output, fungsi yang dikembalikan adalah bentuk yang sama sekali berbeda seperti yang ditunjukkan di atas.
sumber
n-ary
menjadi(x - n)-ary
, menjelajah darin-ary
ken * 1-ary
. Fungsi yang diterapkan sebagian memiliki cakupan yang lebih kecil (dari aplikasi), yaituAdd7
kurang ekspresif daripadaAdd
. Fungsi kari di sisi lain sama ekspresifnya dengan fungsi aslinya.f2(7)(5) is just a syntactic shortcut
? (Saya tahu sedikit.) Tidakf2
mengandung / "tahu tentang" 7?curry
implementasi di suatu tempat (jangan pikir itu dalamfunctools
)Catatan: ini diambil dari F # Basics , artikel pengantar yang sangat baik untuk pengembang .NET masuk ke pemrograman fungsional.
sumber
Pertanyaan menarik. Setelah sedikit mencari, "Aplikasi Fungsi Sebagian tidak kari" memberikan penjelasan terbaik yang saya temukan. Saya tidak bisa mengatakan bahwa perbedaan praktisnya sangat jelas bagi saya, tetapi kemudian saya bukan ahli FP ...
Halaman lain yang tampak bermanfaat (yang saya akui belum sepenuhnya saya baca) adalah "Currying and Partial Application with Java Closures" .
Memang terlihat seperti ini adalah pasangan istilah yang membingungkan, ingatlah.
sumber
Saya telah menjawab ini di utas lain https://stackoverflow.com/a/12846865/1685865 . Singkatnya, aplikasi fungsi parsial adalah tentang memperbaiki beberapa argumen dari fungsi multivariabel yang diberikan untuk menghasilkan fungsi lain dengan argumen yang lebih sedikit, sementara Currying adalah tentang mengubah fungsi argumen N menjadi fungsi unary yang mengembalikan fungsi unary ... [Contoh dari Kari ditampilkan di akhir posting ini.]
Currying sebagian besar adalah kepentingan teoretis: seseorang dapat mengekspresikan komputasi hanya menggunakan fungsi unary (yaitu setiap fungsi unary). Dalam praktik dan sebagai produk sampingan, ini adalah teknik yang dapat membuat banyak aplikasi fungsional yang berguna (tetapi tidak semua) sepele, jika bahasa tersebut memiliki fungsi yang digulung. Sekali lagi, ini bukan satu-satunya cara untuk mengimplementasikan aplikasi parsial. Jadi Anda bisa menemukan skenario di mana aplikasi sebagian dilakukan dengan cara lain, tetapi orang-orang salah mengartikannya sebagai Currying.
(Contoh Kari)
Dalam praktiknya orang tidak akan hanya menulis
atau javascript yang setara
dari pada
demi Currying.
sumber
Currying adalah fungsi dari satu argumen yang mengambil fungsi
f
dan mengembalikan fungsi baruh
. Catatan yangh
mengambil argumen dariX
dan mengembalikan fungsi yang memetakanY
keZ
:Aplikasi parsial adalah fungsi dari dua (atau lebih) argumen yang mengambil fungsi
f
dan satu atau lebih argumen tambahan kef
dan mengembalikan fungsi barug
:Kebingungan muncul karena dengan fungsi dua argumen kesetaraan berikut berlaku:
Kedua belah pihak akan menghasilkan fungsi satu argumen yang sama.
Kesetaraan tidak benar untuk fungsi arity yang lebih tinggi karena dalam hal ini currying akan mengembalikan fungsi satu argumen, sedangkan aplikasi parsial akan mengembalikan fungsi multi-argumen.
Perbedaannya juga dalam perilaku, sedangkan kari mengubah seluruh fungsi asli secara rekursif (satu kali untuk setiap argumen), aplikasi parsial hanyalah penggantian satu langkah.
Sumber: Currying Wikipedia .
sumber
Perbedaan antara aplikasi kari dan sebagian dapat digambarkan dengan baik melalui contoh JavaScript berikut ini:
Aplikasi parsial menghasilkan fungsi arity yang lebih kecil; dalam contoh di atas,
f
memiliki arity 3 sementarapartial
hanya arity 2. Lebih penting lagi, fungsi yang diterapkan sebagian akan mengembalikan hasilnya segera setelah dipanggil , bukan fungsi lain di rantai currying. Jadi jika Anda melihat sesuatu sepertipartial(2)(3)
, itu bukan aplikasi parsial dalam kenyataannya.Bacaan lebih lanjut:
sumber
Jawaban sederhana
Curry: memungkinkan Anda memanggil suatu fungsi, membaginya dalam beberapa panggilan, memberikan satu argumen per-panggilan.
Partial: memungkinkan Anda memanggil suatu fungsi, membaginya dalam beberapa panggilan, memberikan beberapa argumen per-panggilan.
Petunjuk sederhana
Keduanya memungkinkan Anda untuk memanggil fungsi yang menyediakan lebih sedikit argumen (atau, lebih baik, menyediakannya secara kumulatif). Sebenarnya keduanya mengikat (pada setiap panggilan) nilai tertentu untuk argumen fungsi tertentu.
Perbedaan nyata dapat dilihat ketika fungsi memiliki lebih dari 2 argumen.
Sederhana e (c) (sampel)
(dalam Javascript)
mengapa selalu melewati argumen, seperti konteks dan panggilan balik, jika mereka akan selalu sama? Ikat saja beberapa nilai untuk fungsi tersebut
dan menyebutnya di subject1 dan foobar dengan
Nyaman bukan? 😉
Dengan kari Anda harus melewati satu argumen per waktu
Penolakan
Saya melewatkan semua penjelasan akademik / matematika. Karena aku tidak tahu itu. Mungkin itu membantu 🙃
sumber
Saya punya banyak pertanyaan saat belajar dan sejak itu telah ditanyakan berkali-kali. Cara paling sederhana yang bisa saya jelaskan perbedaannya adalah bahwa keduanya sama-sama :) Mari saya jelaskan ... jelas ada perbedaan.
Baik aplikasi parsial maupun currying melibatkan penyediaan argumen ke suatu fungsi, mungkin tidak sekaligus. Contoh yang cukup kanonik adalah menambahkan dua angka. Dalam pseudocode (sebenarnya JS tanpa kata kunci), fungsi dasar mungkin sebagai berikut:
Jika saya ingin fungsi "addOne", saya bisa menerapkannya sebagian atau menjilatnya:
Sekarang menggunakannya jelas:
Jadi apa bedanya? Yah, itu halus, tetapi aplikasi parsial melibatkan penyediaan beberapa argumen dan fungsi yang dikembalikan kemudian akan menjalankan fungsi utama pada doa berikutnya sedangkan currying akan terus menunggu sampai memiliki semua argumen yang diperlukan:
Singkatnya, gunakan aplikasi parsial untuk mengambil beberapa nilai, mengetahui bahwa saat Anda memanggil metode berikutnya, itu akan mengeksekusi, meninggalkan semua argumen yang tidak ditentukan tidak ditentukan; gunakan currying ketika Anda ingin terus mengembalikan fungsi yang diterapkan sebagian sebanyak yang diperlukan untuk memenuhi tanda tangan fungsi. Satu contoh akhir yang dibuat:
Semoga ini membantu!
UPDATE: Beberapa bahasa atau implementasi lib akan memungkinkan Anda untuk lulus arity (jumlah total argumen dalam evaluasi akhir) ke implementasi aplikasi parsial yang dapat mengubah dua deskripsi saya menjadi kekacauan yang membingungkan ... tetapi pada saat itu, kedua teknik tersebut sebagian besar dipertukarkan.
sumber
Bagi saya sebagian aplikasi harus membuat fungsi baru di mana argumen yang digunakan sepenuhnya terintegrasi ke dalam fungsi yang dihasilkan.
Sebagian besar bahasa fungsional menerapkan currying dengan mengembalikan penutupan: jangan mengevaluasi di bawah lambda ketika diterapkan sebagian. Jadi, untuk aplikasi parsial menjadi menarik, kita perlu membuat perbedaan antara currying dan aplikasi parsial dan menganggap aplikasi parsial sebagai currying plus evaluasi di bawah lambda.
sumber
Saya bisa saja sangat salah di sini, karena saya tidak memiliki latar belakang yang kuat dalam matematika teoretis atau pemrograman fungsional, tetapi dari perampokan singkat saya ke FP, tampaknya kari cenderung mengubah fungsi argumen N menjadi fungsi N dari satu argumen, sedangkan aplikasi parsial [dalam praktek] bekerja lebih baik dengan fungsi variad dengan jumlah argumen yang tidak ditentukan. Saya tahu beberapa contoh dalam jawaban sebelumnya menentang penjelasan ini, tetapi itu telah membantu saya untuk paling memisahkan konsep. Pertimbangkan contoh ini (ditulis dalam CoffeeScript untuk ringkasnya, permintaan maaf saya jika membingungkan lebih lanjut, tapi tolong minta klarifikasi, jika perlu):
Ini jelas merupakan contoh yang dibuat-buat, tetapi perhatikan bahwa sebagian menerapkan fungsi yang menerima sejumlah argumen memungkinkan kita untuk mengeksekusi fungsi tetapi dengan beberapa data awal. Currying suatu fungsi serupa tetapi memungkinkan kita untuk mengeksekusi fungsi N-parameter dalam potongan sampai, tetapi hanya sampai, semua parameter N diperhitungkan.
Sekali lagi, ini adalah pendapat saya dari hal-hal yang saya baca. Jika ada yang tidak setuju, saya akan sangat menghargai komentar mengapa daripada langsung downvote. Juga, jika CoffeeScript sulit dibaca, silakan kunjungi coffeescript.org, klik "coba coffeescript" dan tempelkan kode saya untuk melihat versi yang dikompilasi, yang (semoga) lebih masuk akal. Terima kasih!
sumber
Saya akan menganggap kebanyakan orang yang mengajukan pertanyaan ini sudah akrab dengan konsep dasar sehingga mereka tidak perlu membicarakan hal itu. Tumpang tindihlah yang merupakan bagian yang membingungkan.
Anda mungkin dapat sepenuhnya menggunakan konsep-konsep ini, tetapi Anda memahaminya bersama-sama sebagai pengaburan konseptual amorf pseudo-atomik ini. Yang hilang adalah mengetahui di mana batas di antara mereka.
Daripada mendefinisikan apa masing-masing, lebih mudah untuk menyoroti perbedaan mereka saja — batasnya.
Currying adalah saat Anda mendefinisikan fungsi.
Aplikasi Parsial adalah ketika Anda memanggil fungsi.
Aplikasi adalah matematika-berbicara untuk memanggil suatu fungsi.
Aplikasi parsial membutuhkan memanggil fungsi curried dan mendapatkan fungsi sebagai tipe kembali.
sumber
Ada jawaban bagus lainnya di sini tapi saya percaya contoh ini (sesuai pemahaman saya) di Jawa mungkin bermanfaat bagi sebagian orang:
Jadi currying memberi Anda fungsi satu argumen untuk membuat fungsi, di mana sebagian aplikasi membuat fungsi wrapper yang mengkode satu atau lebih argumen.
Jika Anda ingin menyalin & menempel, yang berikut ini lebih ribut tetapi lebih ramah untuk digunakan karena jenisnya lebih lunak:
sumber
Dalam menulis ini, saya bingung kari dan tidak. Mereka adalah transformasi terbalik pada fungsi. Tidak masalah apa yang Anda panggil, selama Anda mendapatkan apa yang diwakili oleh transformasi dan kebalikannya.
Ketidaksesuaian tidak didefinisikan dengan sangat jelas (atau lebih tepatnya, ada definisi "bertentangan" yang semuanya menangkap semangat gagasan). Pada dasarnya, ini berarti mengubah fungsi yang mengambil banyak argumen menjadi fungsi yang membutuhkan satu argumen. Sebagai contoh,
Sekarang, bagaimana Anda mengubahnya menjadi fungsi yang membutuhkan satu argumen? Kamu curang, tentu saja!
Perhatikan bahwa plus sekarang mengambil argumen tunggal (yang terdiri dari dua hal). Super!
Apa gunanya ini? Nah, jika Anda memiliki fungsi yang membutuhkan dua argumen, dan Anda memiliki sepasang argumen, senang mengetahui bahwa Anda dapat menerapkan fungsi ke argumen, dan masih mendapatkan apa yang Anda harapkan. Dan, sebenarnya, pipa ledeng untuk melakukannya sudah ada, sehingga Anda tidak perlu melakukan hal-hal seperti pencocokan pola eksplisit. Yang harus Anda lakukan adalah:
Jadi apa aplikasi fungsi parsial? Ini adalah cara yang berbeda untuk mengubah fungsi dalam dua argumen menjadi fungsi dengan satu argumen. Ini bekerja secara berbeda. Sekali lagi, mari kita ambil (+) sebagai contoh. Bagaimana kita mengubahnya menjadi fungsi yang menggunakan Int tunggal sebagai argumen? Kami curang!
Itulah fungsi yang menambahkan nol ke Int.
menambahkan 1 ke Int. Dll. Dalam setiap kasus ini, (+) "diterapkan sebagian".
sumber