Contoh nyata menggunakan fungsi kari? [Tutup]

8

Saya kesulitan menemukan contoh kehidupan nyata menggunakan fungsi kari dan mendapatkan manfaat menggunakan kari.

Ketika saya fungsi google curry saya sering melihat contoh suka

let add = x => y => x + y;
let add10 = add(10);
console.log(add10(20));

Saya harus mengatakan saya benar-benar tidak melihat nilai dari menggunakan kari dalam contoh ini.

Setelah membaca jawaban dalam SO ini /programming/113780/javascript-curry-what-are-the-praktis-aplikasi saya masih tidak melihat manfaat dari menggunakannya.

Misalnya, jawaban skor tertinggi memberikan contoh konverter, tetapi contoh itu dapat ditulis ulang tanpa kari seperti yang ditunjukkan oleh jawaban lain.

Saya juga membaca jawaban. Apa keuntungan dari kari? (walaupun diskusi tidak terbatas pada javascript) Saya masih merasa bahwa versi kari dapat ditulis ulang tanpa kari (dalam js).

Jadi bisakah seseorang menunjukkan kepada saya keuntungan / manfaat "nyata" dari menggunakan kari dalam javascript?

---- perbarui ----

Kecuali untuk jawaban yang saya dapatkan, saya juga menemukan contoh log di sini menunjukkan manfaat menggunakannya.

Qiulang
sumber
2
Saya setuju bahwa sebagian besar contoh dasar kari yang Anda temukan online sangat tidak mengesankan.
user949300
@ user949300 BTW, saya benar-benar tidak mengerti mengapa pertanyaan saya dibatalkan. Bukankah pertanyaan "valid" ketika Anda berpikir tentang js kari? Saya khawatir itu akan ditutup pada SO jadi saya bertanya di sini. :(
Qiulang
Saya menemukan currying sebagian besar berguna ketika fungsi lib eksternal mengharapkan fungsi (misalnya panggilan balik) yang mengambil sejumlah argumen dan Anda memiliki fungsi (misalnya penangan) yang membutuhkan lebih banyak argumen, tetapi Anda ingin memberikan nilai konstan untuk argumen tambahan ini. Salinan sebagian kemudian lebih mudah dibaca daripada membuat fungsi panah
tutuDajuju
3
"Aku masih merasa bahwa versi kari dapat ditulis ulang tanpa kari" - Ini adalah hal yang sepele, karena itu semua tentang kari. Seluruh titik currying adalah pengamatan bahwa fungsi n parameter dapat ditulis ulang sebagai fungsi parameter n-1 yang mengembalikan fungsi yang mengambil parameter ke-n. Perhatikan juga bahwa pernyataan ini berlaku untuk hampir semua hal. Setiap forloop dapat ditulis ulang sebagai whileloop. Setiap ifpernyataan dapat ditulis ulang sebagai satu whilelingkaran. Setiap whileloop dapat ditulis ulang sebagai goto. Itu tidak berarti mereka tidak berguna.
Jörg W Mittag

Jawaban:

8

Saya hampir tidak pernah menggunakan Currying sendiri, tapi inilah contoh terbaru yang terbukti bermanfaat. Saya mengkodekan untuk game Battlesnake , tetapi ini akan berlaku untuk banyak game. Mereka memberi Anda berbagai array, memberikan lokasi ular, ular musuh, dan makanan Anda. Katakanlah Anda mempertimbangkan untuk pindah ke titik {x, y} tertentu, dan Anda ingin memeriksa apakah itu mengandung ular, makanan, atau bahkan diri Anda sendiri. Lulus pertama adalah menulis kode seperti ini (saya akan menggunakan campuran fungsi dan panah ketinggalan jaman baru)

// utility function
function samePoint(p1, p2) {
  return (p1.x === p2.x) && (p1.y === p2.y);
}

dan di suatu tempat dalam kode pergi

let possibleMove = {x,y}; // where you are thinking of moving
...
if (foodArray.some((p) => samePoint(p, possibleMove )) {
  // this move looks tasty, give it a bonus value...
}

Tidak buruk, tetapi, karena Anda akan melakukan ini banyak banyak tempat dalam kode Anda, sedikit membosankan dan kikuk. Dan, dari pengalaman saya, mudah mengacaukan dua argumen. :-( Masalah mendasar adalah bahwa some()(atau find()) menerima fungsi mengambil hanya satu argumen, dan Anda benar-benar membutuhkan dua argumen , dua titik Jadi, Anda memikirkan currying Berikut banyak akan menggunakan panah, saya menemukan fungsi bersarang lebih jelas.!:

function samePointAs(p1) {
  return function(p2) {
    return samePoint(p1, p2);
  }
}

Lalu, tes "is that food" Anda menjadi

let possibleMove = {x,y}; // where you are thinking of moving
...
if (foodArray.some(samePointAs(possibleMove )) {
  // this move looks tasty, give it a bonus value...
}

Apakah ini akan menjadikan Anda seorang jutawan internet? Mungkin tidak. Tapi itu memang menyederhanakan, dan, dalam hal ini, memperjelas kode Anda.

pengguna949300
sumber
Hai Saya suka Anda contoh jadi saya menandai jawaban Anda sebagai jawaban yang diterima. Terima kasih.
Qiulang
Hai, pertanyaan saya ditunda. Bahkan mendapat suara penghapusan. Saya mencoba mengeditnya untuk membuatnya ditunda tanpa hasil. Saya ingin tahu, bisakah Anda membantu saya mengeditnya?
Qiulang
14

Saya suka kari dalam contoh Anda tidak masuk akal. Untuk melihat fungsi currying, Anda harus menggabungkannya dengan fungsi urutan yang lebih tinggi: fungsi yang menggunakan fungsi lain sebagai parameter.

Contoh paling umum dari ini adalah memetakan, memfilter, dan mengurangi, meskipun situasi umum lainnya adalah panggilan balik. Saat Anda menerapkan fungsi secara parsial, Anda bisa meneruskan fungsi yang diterapkan sebagian ke fungsi-fungsi tingkat tinggi ini. Currying masuk akal ketika sebagian besar waktu Anda ingin menggunakan fungsi adalah untuk aplikasi parsial sehingga dapat diteruskan ke fungsi urutan lebih tinggi lainnya.

Contoh yang lebih ilustratif mungkin terlihat seperti ini:

let array1 = [1, 4, 9, 16];
let add = x => y => x + y;
array2 = array1.map(foo ? add(10) : add(20));

Currying tidak pernah diperlukan, ya, karena Anda selalu dapat membuat fungsi anonim / panah dari fungsi biasa saat Anda membutuhkannya, tetapi dalam beberapa situasi mungkin sangat nyaman untuk memiliki fungsi kari dibandingkan dengan yang biasa (dan dalam situasi lain, itu hanya membuat hal-hal menjengkelkan dan lambat).

Lie Ryan
sumber
2
"tetapi dalam beberapa situasi bisa sangat nyaman untuk memiliki fungsi kari dibandingkan dengan yang biasa" jadi bisakah Anda memberikan beberapa contohnya? Terima kasih!
Qiulang
@ Qiulang salah satu contohnya adalah jika Anda memiliki serangkaian logika konfigurasi yang mengontrol cara memanggil fungsi yang memiliki banyak parameter. Jika Anda tidak memiliki fungsi curried, Anda harus sering membuat objek yang memiliki API lancar, atau menyediakan semacam metode clone_and_update (), atau Anda harus membuat kelas Builder terpisah untuk membangun parameter fungsi secara bertahap. Contoh khas dari ini adalah pembuat kueri ORM. Dengan fungsi curried, Anda bisa memanggil fungsi seperti biasa pada setiap langkah.
Lie Ryan
@ LieRyan Dalam JavaScript , di mana sangat sepele untuk membuat opsi "objek" menggunakan {}, saya belum menemukan kelas Builder sangat berguna atau umum. Bisakah Anda mengutip beberapa contoh?
user949300
1
@ user949300 Membuat dua puluh objek dengan sepuluh anggota yang hanya berbeda dengan satu atau dua parameter tidak lebih mudah di JS daripada dalam bahasa lain. Dengan objek pembangun yang tidak berubah yang menggunakan antarmuka yang lancar, Anda bisa membangun objek konfigurasi dasar kemudian hanya bercabang untuk membuat set argumen yang berbeda. Pola semacam ini mungkin sering terlihat terlalu berat dalam kode aplikasi, tetapi itu cukup umum untuk perpustakaan / penulis kerangka kerja.
Lie Ryan
1
Poin diambil, tetapi @LieRyan dengan model baru Object.assign()itu cukup mudah untuk bercabang dari konfigurasi dasar.
user949300