Saya telah membaca beberapa tutorial Java 8 sebelumnya.
Saat ini saya menemukan topik berikut: Apakah java mendukung kari?
Di sini, saya melihat kode berikut:
IntFunction<IntUnaryOperator> curriedAdd = a -> b -> a + b;
System.out.println(curriedAdd.apply(1).applyAsInt(12));
Saya mengerti bahwa contoh ini menjumlahkan 2 elemen tetapi saya tidak dapat memahami konstruksinya:
a -> b -> a + b;
Menurut bagian kiri ekspresi, baris ini harus mengimplementasikan fungsi berikut:
R apply(int value);
Sebelumnya, saya hanya bertemu lambda hanya dengan satu anak panah.
Jawaban:
Jika Anda mengekspresikan ini sebagai sintaks lambda non-singkatan atau sintaks kelas anonim Java pre-lambda, lebih jelas apa yang terjadi ...
Pertanyaan asli. Mengapa dua anak panah? Sederhana, ada dua fungsi yang didefinisikan ... Fungsi pertama adalah fungsi yang menentukan fungsi, yang kedua adalah hasil dari fungsi itu, yang juga kebetulan merupakan fungsi. Masing-masing membutuhkan
->
operator untuk mendefinisikannya.Non-steno
Pra-Lambda sebelum Java 8
sumber
final int value
pre-lambda
An
IntFunction<R>
adalah sebuah fungsiint -> R
. AnIntUnaryOperator
adalah sebuah fungsiint -> int
.Jadi an
IntFunction<IntUnaryOperator>
adalah fungsi yang mengambilint
sebagai parameter dan mengembalikan fungsi yang mengambilint
sebagai parameter dan mengembalikanint
.Mungkin akan lebih jelas jika Anda menggunakan kelas anonim untuk "mendekomposisi" lambda:
sumber
Menambahkan tanda kurung mungkin membuat ini lebih jelas:
Atau mungkin variabel perantara dapat membantu:
sumber
Mari kita tulis ulang ekspresi lambda itu dengan tanda kurung agar lebih jelas:
Jadi kami mendeklarasikan fungsi yang mengambil
int
yang mengembalikan aFunction
. Lebih khusus lagi, fungsi yang dikembalikan mengambilint
dan mengembalikanint
(jumlah dari dua elemen): ini bisa direpresentasikan sebagaiIntUnaryOperator
.Oleh karena itu,
curriedAdd
adalah fungsi yang mengambilint
dan mengembalikanIntUnaryOperator
, sehingga dapat direpresentasikan sebagaiIntFunction<IntUnaryOperator>
.sumber
Itu dua ekspresi lambda.
sumber
Jika Anda melihat
IntFunction
mungkin menjadi lebih jelas:IntFunction<R>
adalah aFunctionalInterface
. Ini mewakili fungsi yang mengambilint
dan mengembalikan nilai tipeR
.Dalam hal ini, tipe kembaliannya
R
juga aFunctionalInterface
, yaituIntUnaryOperator
. Jadi yang pertama (luar) itu sendiri mengembalikan fungsi.Dalam hal ini: Ketika diterapkan ke
int
,curriedAdd
diharapkan untuk mengembalikan fungsi yang lagi mengambilint
(dan kembali lagiint
, karena itulahIntUnaryOperator
).Dalam pemrograman fungsional, adalah umum untuk menulis jenis fungsi sebagai
param -> return_value
dan Anda melihatnya persis di sini. Jadi jenisnyacurriedAdd
adalahint -> int -> int
(atauint -> (int -> int)
jika Anda menyukainya lebih baik).Sintaks lambda Java 8 sejalan dengan ini. Untuk mendefinisikan fungsi seperti itu, Anda menulis
yang sangat mirip dengan kalkulus lambda sebenarnya:
λb a + b
adalah fungsi yang mengambil satu parameterb
dan mengembalikan nilai (jumlah).λa λb a + b
adalah fungsi yang menerima satu parametera
dan mengembalikan fungsi lain dari satu parameter.λa λb a + b
kembaliλb a + b
dengana
set ke nilai parameter.sumber