Saya memiliki latihan dengan Python sebagai berikut:
polinomial diberikan sebagai tupel koefisien sehingga kekuatan ditentukan oleh indeks, misalnya: (9,7,5) berarti 9 + 7 * x + 5 * x ^ 2
tulis fungsi untuk menghitung nilainya untuk diberikan x
Karena saya ke pemrograman fungsional belakangan ini, saya menulis
def evaluate1(poly, x):
coeff = 0
power = 1
return reduce(lambda accu,pair : accu + pair[coeff] * x**pair[power],
map(lambda x,y:(x,y), poly, range(len(poly))),
0)
yang saya anggap tidak terbaca, jadi saya menulis
def evaluate2(poly, x):
power = 0
result = 1
return reduce(lambda accu,coeff : (accu[power]+1, accu[result] + coeff * x**accu[power]),
poly,
(0,0)
)[result]
yang setidaknya sama tidak terbaca, jadi saya menulis
def evaluate3(poly, x):
return poly[0]+x*evaluate(poly[1:],x) if len(poly)>0 else 0
yang mungkin kurang efisien (sunting: saya salah!) karena menggunakan banyak perkalian alih-alih eksponensial, pada prinsipnya, saya tidak peduli tentang pengukuran di sini (sunting: Betapa bodohnya saya! Mengukur akan menunjukkan kesalahpahaman saya!) dan masih belum terbaca (bisa dibilang) sebagai solusi berulang:
def evaluate4(poly, x):
result = 0
for i in range(0,len(poly)):
result += poly[i] * x**i
return result
Apakah ada solusi murni fungsional yang dapat dibaca seperti keharusan dan mendekati efisiensi?
Memang, perubahan representasi akan membantu, tetapi ini diberikan oleh latihan.
Bisa juga Haskell atau Lisp, bukan hanya Python.
for
loop, misalnya) adalah tujuan yang buruk untuk dibidik dengan Python. Mengikat variabel secara bijaksana dan tidak memutasikan objek memberi Anda hampir semua manfaat dan membuat kode jauh lebih mudah dibaca. Karena objek nomor tidak dapat diubah dan hanya mengubah dua nama lokal, solusi "imperatif" Anda lebih menyadari nilai pemrograman fungsional daripada kode Python "murni murni" apa pun.lambda
, dibandingkan dengan bahasa dengan fungsi sintaksis anonim yang lebih ringan. Sebagian dari itu mungkin berkontribusi pada penampilan "najis".Jawaban:
Metode Horner mungkin lebih efisien secara komputasi seperti yang ditunjukkan @delnan, tapi saya akan menyebut ini cukup mudah dibaca dengan Python untuk solusi eksponensial:
sumber
sum(coeff * X**power for power, coeff in enumerate(poly))
map
danfilter
. Kita juga dapat menganggapnya sebagai untuk loop dari bentuk tertentu, tetapi loop dari bentuk itu setara dengan kombinator funcitonal yang disebutkan sebelumnya.Banyak bahasa fungsional memiliki implementasi mapi yang memungkinkan Anda memiliki indeks yang dianyam melalui peta. Gabungkan itu dengan jumlah dan Anda memiliki yang berikut di F #:
sumber
map
kerjanya, itu harus cukup sederhana untuk menulis sendiri.Saya tidak mengerti bagaimana kode Anda berhubungan dengan ruang lingkup masalah yang Anda tentukan, jadi saya akan memberikan versi saya tentang apa yang kode Anda mengabaikan ruang lingkup masalahnya (berdasarkan pada kode imperatif yang Anda tulis).
Haskell yang mudah dibaca (pendekatan ini dapat dengan mudah diterjemahkan ke bahasa FP mana pun yang memiliki daftar yang merusak dan keluar murni dan dapat dibaca):
Kadang-kadang pendekatan sederhana naif dalam haskell seperti itu lebih bersih daripada pendekatan yang lebih ringkas untuk orang yang kurang terbiasa dengan FP.
Pendekatan imperatif yang lebih jelas yang masih sepenuhnya murni adalah:
bonus untuk pendekatan kedua sedang di ST monad itu akan berkinerja sangat baik.
Meskipun untuk memastikan, implementasi nyata yang paling mungkin dari Haskeller adalah zipwith yang disebutkan dalam jawaban lain di atas.
zipWith
adalah pendekatan yang sangat khas dan saya percaya Python dapat meniru pendekatan zipping menggabungkan fungsi dan pengindeks yang dapat dipetakan.sumber
Jika Anda hanya memiliki tuple (tetap), mengapa tidak melakukan ini (di Haskell):
Jika Anda memiliki daftar koefisien, Anda dapat menggunakan:
atau dengan potongan seperti yang Anda miliki:
sumber
tuple
mengartikan serangkaian nilai ukuran tetap, masing-masing dari tipe yang berpotensi berbeda, yang tidak dapat ditambahkan atau dihapus. Saya tidak pernah benar-benar mengerti mengapa bahasa yang dinamis dengan daftar, yang menerima input heterogen, membutuhkannya.Ada serangkaian langkah umum yang dapat Anda gunakan untuk meningkatkan keterbacaan algoritma fungsional:
evaluateTerm
daripada ekspresi lambda yang panjang. Hanya karena Anda dapat menggunakan lambda tidak selalu berarti Anda harus melakukannya .enumerate
atauzipWith
.sumber