Saya telah belajar perbedaan mendasar antara foldLeft
danreduceLeft
foldLeft:
- nilai awal harus diteruskan
kurangiLeft:
- mengambil elemen pertama dari koleksi sebagai nilai awal
- melempar pengecualian jika koleksi kosong
Apakah ada perbedaan lain?
Adakah alasan khusus untuk memiliki dua metode dengan fungsi serupa?
scala
functional-programming
fold
higher-order-functions
Rajesh Pitty
sumber
sumber
Jawaban:
Beberapa hal untuk disebutkan di sini, sebelum memberikan jawaban yang sebenarnya:
left
, melainkan tentang perbedaan antara mengurangi dan melipatKembali ke pertanyaan Anda:
Inilah tanda tangan
foldLeft
(bisa jugafoldRight
untuk poin yang akan saya buat):Dan di sini adalah tanda tangan
reduceLeft
(lagi arah tidak masalah di sini)Keduanya terlihat sangat mirip dan menyebabkan kebingungan.
reduceLeft
adalah kasus khusus darifoldLeft
(yang omong-omong berarti bahwa Anda kadang - kadang dapat mengekspresikan hal yang sama dengan menggunakan salah satu dari mereka).Ketika Anda memanggil
reduceLeft
say pada aList[Int]
itu akan benar-benar mengurangi seluruh daftar bilangan bulat menjadi nilai tunggal, yang akan bertipeInt
(atau supertypeInt
, karenanya[B >: A]
).Ketika Anda menelepon
foldLeft
mengatakan padaList[Int]
itu akan melipat seluruh daftar (bayangkan menggulung selembar kertas) menjadi nilai tunggal, tetapi nilai ini tidak harus bahkan terkait denganInt
(karenanya[B]
).Berikut ini sebuah contoh:
Metode ini mengambil
List[Int]
dan mengembalikan aTuple2[List[Int], Int]
atau(List[Int], Int)
. Ini menghitung jumlah dan mengembalikan tupel dengan daftar bilangan bulat dan jumlahnya. Ngomong-ngomong, daftar dikembalikan ke belakang, karena kami menggunakanfoldLeft
alih-alihfoldRight
.Tonton One Fold untuk mengatur semuanya untuk penjelasan yang lebih mendalam.
sumber
B
itu supertypeA
? SepertinyaB
seharusnya menjadi subtipeA
, bukan supertipe. Misalnya, dengan asumsiBanana <: Fruit <: Food
, jika kita memiliki daftarFruit
s, tampaknya itu mungkin mengandung beberapaBanana
s, tetapi jika berisiFood
s, maka jenisnya akanFood
, benar? Jadi dalam hal ini, jikaB
adalah supertypeA
dan ada daftar yang berisi keduanyaB
danA
, daftar harus bertipeB
, bukanA
. Bisakah Anda menjelaskan perbedaan ini?List[Banana]
dapat direduksi menjadi satuBanana
atau satuFruit
atau satuFood
. KarenaFruit :> Banana
dan `Makanan:> Pisang '.Banana
mungkin berisiFruit
", yang tidak masuk akal. Penjelasan Anda memang masuk akal -f
fungsi yang diteruskanreduce()
dapat menghasilkan aFruit
atau aFood
, yang berartiB
dalam tanda tangan harus berupa superclass, bukan subclass.reduceLeft
hanyalah metode kenyamanan. Ini setara dengansumber
reducelft
meskipunfold
berfungsi pada daftar kosong sementarareduce
tidak.foldLeft
lebih umum, Anda dapat menggunakannya untuk menghasilkan sesuatu yang sama sekali berbeda dari apa yang awalnya Anda masukkan. SedangkanreduceLeft
hanya dapat menghasilkan hasil akhir dari tipe yang sama atau tipe super dari tipe koleksi. Sebagai contoh:The
foldLeft
akan menerapkan penutupan dengan hasil dilipat terakhir (pertama kali menggunakan nilai awal) dan nilai berikutnya.reduceLeft
di sisi lain pertama-tama akan menggabungkan dua nilai dari daftar dan menerapkannya pada penutupan. Selanjutnya akan menggabungkan sisa nilai dengan hasil kumulatif. Lihat:Jika daftar kosong
foldLeft
dapat menyajikan nilai awal sebagai hasil hukum.reduceLeft
di sisi lain tidak memiliki nilai hukum jika tidak dapat menemukan setidaknya satu nilai dalam daftar.sumber
Alasan dasar mereka berdua di perpustakaan standar Scala mungkin karena mereka berdua di perpustakaan standar Haskell (dipanggil
foldl
danfoldl1
). JikareduceLeft
tidak, itu akan sering didefinisikan sebagai metode kenyamanan di berbagai proyek.sumber
Sebagai referensi,
reduceLeft
akan kesalahan jika diterapkan pada wadah kosong dengan kesalahan berikut.Mengolah kembali kode yang akan digunakan
adalah salah satu opsi potensial. Lain adalah dengan menggunakan
reduceLeftOption
varian yang mengembalikan hasil Opsi dibungkus.sumber
Dari Prinsip Pemrograman Fungsional di Scala (Martin Odersky):
[Berbeda dengan
reduceLeft
, yang melempar pengecualian ketika dipanggil pada daftar kosong.]Kursus ini (lihat kuliah 5.5) memberikan definisi abstrak dari fungsi-fungsi ini, yang menggambarkan perbedaan mereka, meskipun mereka sangat mirip dalam penggunaan pencocokan pola dan rekursi.
Perhatikan bahwa
foldLeft
mengembalikan nilai tipeU
, yang tidak harus tipe yang samaList[T]
, tetapi mengurangiLeft mengembalikan nilai dari tipe yang sama dengan daftar).sumber
Untuk benar-benar memahami apa yang Anda lakukan dengan lipatan / pengurangan, periksa ini: http://wiki.tcl.tk/17983 penjelasan yang sangat bagus. setelah Anda mendapatkan konsep flip, mengurangi akan datang bersama dengan jawaban di atas: list.tail.foldLeft (list.head) (_)
sumber