Apa itu dalam pemrograman fungsional yang membuat perbedaan?
Pemrograman fungsional pada prinsipnya bersifat deklaratif . Anda mengatakan apa hasil Anda alih-alih bagaimana cara menghitungnya.
Mari kita lihat implementasi dari snippet Anda yang sangat fungsional. Dalam Haskell akan menjadi:
predsum pred numbers = sum (filter pred numbers)
Apakah jelas apa hasilnya? Cukup begitu, itu adalah jumlah angka yang memenuhi predikat. Bagaimana cara menghitungnya? Saya tidak peduli, tanyakan pada kompiler.
Anda bisa mengatakan bahwa menggunakan sum
dan filter
merupakan trik dan itu tidak masuk hitungan. Biarkan menerapkannya tanpa bantuan ini (meskipun cara terbaik adalah menerapkannya terlebih dahulu).
Solusi "Pemrograman Fungsional 101" yang tidak digunakan sum
adalah dengan rekursi:
sum pred list =
case list of
[] -> 0
h:t -> if pred h then h + sum pred t
else sum pred t
Masih cukup jelas apa hasilnya dalam hal panggilan fungsi tunggal. Itu bisa 0
, atau recursive call + h or 0
, tergantung pada pred h
. Masih cukup lurus ke depan, bahkan jika hasil akhirnya tidak segera jelas (meskipun dengan sedikit latihan ini benar-benar berbunyi seperti for
lingkaran).
Bandingkan dengan versi Anda:
public int Sum(Func<int,bool> predicate, IEnumerable<int> numbers){
int result = 0;
foreach(var item in numbers)
if (predicate(item)) result += item;
return result;
}
Apa hasilnya? Oh, saya melihat: lajang return
pernyataan, tidak ada kejutan di sini: return result
.
Tapi apa itu result
? int result = 0
? Sepertinya tidak benar. Anda melakukan sesuatu nanti dengan itu 0
. Oke, Anda menambahkannya item
. Dan seterusnya.
Tentu saja, bagi sebagian besar programmer ini cukup jelas apa yang terjadi dalam fungsi sederhana seperti ini, tetapi tambahkan beberapa return
pernyataan tambahan dan tiba-tiba semakin sulit untuk dilacak. Semua kode adalah tentang bagaimana , dan apa yang tersisa bagi pembaca untuk mencari tahu - ini jelas gaya yang sangat penting .
Jadi, apakah variabel dan loop salah?
Tidak.
Ada banyak hal yang lebih mudah dijelaskan oleh mereka, dan banyak algoritma yang membutuhkan keadaan bisa berubah menjadi cepat. Tetapi variabel pada dasarnya imperatif, menjelaskan bagaimana alih-alih apa , dan memberikan sedikit prediksi tentang nilai mereka mungkin beberapa baris kemudian atau setelah beberapa iterasi loop. Loop biasanya membutuhkan keadaan yang masuk akal, dan karenanya mereka pada dasarnya juga penting.
Variabel dan loop sama sekali bukan pemrograman fungsional.
Ringkasan
Pemrograman fungsi kontemporsial sedikit lebih gaya dan cara berpikir yang berguna daripada paradigma. Preferensi kuat untuk fungsi murni ada dalam pola pikir ini, tetapi sebenarnya hanya sebagian kecil saja.
Sebagian besar bahasa yang tersebar luas memungkinkan Anda menggunakan beberapa konstruksi fungsional. Misalnya dalam Python Anda dapat memilih antara:
result = 0
for num in numbers:
if pred(result):
result += num
return result
atau
return sum(filter(pred, numbers))
atau
return sum(n for n in numbers if pred(n))
Ekspresi fungsional ini cocok untuk masalah semacam itu dan hanya membuat kode lebih pendek (dan lebih pendek bagus ). Anda seharusnya tidak mengganti kode imperatif dengan mereka, tetapi ketika mereka cocok, mereka hampir selalu merupakan pilihan yang lebih baik.
item
variabel dimutasi dalam loop.