Saya benar-benar kesulitan memahami perbedaan antara paradigma pemrograman prosedural dan fungsional .
Berikut adalah dua paragraf pertama dari entri Wikipedia tentang pemrograman fungsional :
Dalam ilmu komputer, pemrograman fungsional adalah paradigma pemrograman yang memperlakukan komputasi sebagai evaluasi fungsi matematika dan menghindari status dan data yang dapat berubah. Ini menekankan penerapan fungsi, berbeda dengan gaya pemrograman imperatif, yang menekankan perubahan status. Pemrograman fungsional berakar pada kalkulus lambda, sistem formal yang dikembangkan pada tahun 1930-an untuk menyelidiki definisi fungsi, aplikasi fungsi, dan rekursi. Banyak bahasa pemrograman fungsional dapat dilihat sebagai elaborasi pada kalkulus lambda.
Dalam praktiknya, perbedaan antara fungsi matematika dan pengertian "fungsi" yang digunakan dalam pemrograman imperatif adalah bahwa fungsi imperatif dapat memiliki efek samping, mengubah nilai status program. Karena itu, mereka kekurangan transparansi referensial, yaitu ekspresi bahasa yang sama dapat menghasilkan nilai yang berbeda pada waktu yang berbeda tergantung pada status program pelaksana. Sebaliknya, dalam kode fungsional, nilai keluaran suatu fungsi hanya bergantung pada argumen yang dimasukkan ke fungsi tersebut, jadi memanggil fungsi
f
dua kali dengan nilai yang sama untuk sebuah argumenx
akan menghasilkan hasil yang sama.f(x)
kedua waktu. Menghilangkan efek samping dapat membuat lebih mudah untuk memahami dan memprediksi perilaku suatu program, yang merupakan salah satu motivasi utama untuk pengembangan pemrograman fungsional.
Di paragraf 2 di mana dikatakan
Sebaliknya, dalam kode fungsional, nilai keluaran suatu fungsi hanya bergantung pada argumen yang dimasukkan ke fungsi, jadi memanggil fungsi
f
dua kali dengan nilai yang sama untuk sebuah argumenx
akan menghasilkan hasil yang sama dif(x)
kedua waktu.
Bukankah itu kasus yang sama persis untuk pemrograman prosedural?
Apa yang harus dicari dalam prosedural vs fungsional yang menonjol?
Jawaban:
Pemrograman Fungsional
Pemrograman fungsional mengacu pada kemampuan untuk memperlakukan fungsi sebagai nilai.
Mari kita pertimbangkan analogi dengan nilai "reguler". Kita dapat mengambil dua nilai integer dan menggabungkannya menggunakan
+
operator untuk mendapatkan integer baru. Atau kita bisa mengalikan bilangan bulat dengan angka floating point untuk mendapatkan angka floating point.Dalam pemrograman fungsional, kita dapat menggabungkan dua nilai fungsi untuk menghasilkan nilai fungsi baru menggunakan operator seperti compose atau lift . Atau kita dapat menggabungkan nilai fungsi dan nilai data untuk menghasilkan nilai data baru menggunakan operator seperti map atau lipat .
Perhatikan bahwa banyak bahasa memiliki kemampuan pemrograman fungsional - bahkan bahasa yang biasanya tidak dianggap sebagai bahasa fungsional. Bahkan Grandfather FORTRAN mendukung nilai fungsi, meskipun tidak menawarkan banyak cara operator penggabung fungsi. Untuk sebuah bahasa yang disebut "fungsional", ia perlu merangkul kapabilitas pemrograman fungsional secara besar-besaran.
Pemrograman Prosedural
Pemrograman prosedural mengacu pada kemampuan untuk merangkum urutan instruksi yang umum ke dalam prosedur sehingga instruksi tersebut dapat dipanggil dari banyak tempat tanpa menggunakan copy-dan-paste. Karena prosedur merupakan pengembangan yang sangat awal dalam pemrograman, kapabilitas hampir selalu terkait dengan gaya pemrograman yang diminta oleh pemrograman bahasa mesin atau perakitan: gaya yang menekankan gagasan lokasi penyimpanan dan instruksi yang memindahkan data di antara lokasi tersebut.
Kontras
Kedua gaya tersebut tidak benar-benar berlawanan - mereka hanya berbeda satu sama lain. Ada bahasa yang sepenuhnya merangkul kedua gaya (LISP, misalnya). Skenario berikut mungkin memberikan gambaran tentang beberapa perbedaan dalam kedua gaya tersebut. Mari tulis beberapa kode untuk persyaratan yang tidak masuk akal di mana kita ingin menentukan apakah semua kata dalam daftar memiliki jumlah karakter ganjil. Pertama, gaya prosedural:
Saya akan menganggapnya sebagai mengingat bahwa contoh ini dapat dipahami. Sekarang, gaya fungsional:
Bekerja dari dalam ke luar, definisi ini melakukan hal-hal berikut:
compose(odd, length)
menggabungkan fungsiodd
danlength
untuk menghasilkan fungsi baru yang menentukan apakah panjang string ganjil.map(..., words)
memanggil fungsi baru itu untuk setiap elemen diwords
, yang pada akhirnya mengembalikan daftar nilai boolean baru, masing-masing menunjukkan apakah kata yang bersangkutan memiliki jumlah karakter ganjil.apply(and, ...)
menerapkan operator "dan" ke daftar yang dihasilkan, dan menyatukan semua boolean untuk menghasilkan hasil akhir.Anda dapat melihat dari contoh-contoh ini bahwa pemrograman prosedural sangat memperhatikan nilai-nilai yang dipindahkan di dalam variabel dan secara eksplisit menjelaskan operasi yang diperlukan untuk menghasilkan hasil akhir. Sebaliknya, gaya fungsional menekankan kombinasi fungsi yang diperlukan untuk mengubah masukan awal menjadi keluaran akhir.
Contoh ini juga menunjukkan ukuran relatif yang khas dari kode prosedural versus kode fungsional. Lebih lanjut, ini menunjukkan bahwa karakteristik kinerja kode prosedural mungkin lebih mudah dilihat daripada kode fungsional. Pertimbangkan: apakah fungsi menghitung panjang semua kata dalam daftar, atau apakah masing-masing berhenti segera setelah menemukan kata panjang genap pertama? Di sisi lain, kode fungsional mengizinkan implementasi berkualitas tinggi untuk melakukan beberapa pengoptimalan yang cukup serius karena ini terutama mengekspresikan maksud daripada algoritma eksplisit.
Bacaan lebih lanjut
Pertanyaan ini sering muncul ... lihat, contoh:
Kuliah penghargaan Turing John Backus menjelaskan motivasi untuk pemrograman fungsional dengan sangat rinci:
Dapatkah Pemrograman Dibebaskan dari Gaya von Neumann?
Saya benar-benar tidak boleh menyebutkan makalah itu dalam konteks sekarang karena ini menjadi sangat teknis, cukup cepat. Saya tidak bisa menolak karena saya pikir itu benar-benar mendasar.
Adendum - 2013
Komentator menunjukkan bahwa bahasa kontemporer populer menawarkan gaya pemrograman lain di atas prosedural dan fungsional. Bahasa seperti itu sering kali menawarkan satu atau lebih gaya pemrograman berikut:
Lihat komentar di bawah ini untuk mengetahui contoh bagaimana contoh pseudo-code dalam tanggapan ini dapat memanfaatkan beberapa fasilitas yang tersedia dari gaya lain tersebut. Secara khusus, contoh prosedural akan mendapat manfaat dari penerapan hampir semua konstruksi tingkat yang lebih tinggi.
Contoh yang dipamerkan dengan sengaja menghindari pencampuran dalam gaya pemrograman lain ini untuk menekankan perbedaan antara dua gaya yang sedang dibahas.
sumber
odd_words(words)
Definisi Anda melakukan sesuatu yang berbeda dari jawabanallOdd
. Untuk pemfilteran dan pemetaan, pemahaman daftar sering kali lebih disukai, tetapi di sini fungsinyaallOdd
dimaksudkan untuk mengurangi daftar kata menjadi satu nilai boolean.Perbedaan nyata antara pemrograman fungsional dan imperatif adalah pola pikirnya - programmer imperatif memikirkan variabel dan blok memori, sedangkan programmer fungsional berpikir, "Bagaimana cara mengubah data masukan saya menjadi data keluaran" - "program" Anda adalah saluran pipa dan set transformasi pada data untuk diambil dari Input ke Output. Itulah IMO bagian yang menarik, bukan bit "Jangan gunakan variabel".
Sebagai konsekuensi dari pola pikir ini, program KB biasanya mendeskripsikan apa yang akan terjadi, alih-alih mekanisme spesifik bagaimana hal itu akan terjadi - ini sangat berguna karena jika kita dapat dengan jelas menyatakan apa artinya "Pilih" dan "Di mana" dan "Agregat", kita bebas menukar implementasinya, seperti yang kita lakukan dengan AsParallel () dan tiba-tiba aplikasi single-threaded kita berskala ke n core.
sumber
Tidak, karena kode prosedural dapat memiliki efek samping. Misalnya, dapat menyimpan status antar panggilan.
Meskipun demikian, dimungkinkan untuk menulis kode yang memenuhi batasan ini dalam bahasa yang dianggap prosedural. Dan juga mungkin untuk menulis kode yang mematahkan batasan ini dalam beberapa bahasa yang dianggap fungsional.
sumber
Saya tidak setuju dengan jawaban WReach. Mari kita dekonstruksi jawabannya sedikit untuk melihat dari mana ketidaksepakatan itu berasal.
Pertama, kodenya:
dan
Hal pertama yang perlu diperhatikan adalah dia menggabungkan:
pemrograman, dan kehilangan kemampuan untuk gaya pemrograman iteratif untuk memiliki aliran kontrol yang lebih eksplisit daripada gaya fungsional yang khas.
Mari kita bicarakan ini dengan cepat.
Gaya yang berpusat pada ekspresi adalah gaya di mana hal-hal, sebanyak mungkin, mengevaluasi berbagai hal. Meskipun bahasa fungsional terkenal karena kecintaannya pada ekspresi, sebenarnya mungkin untuk memiliki bahasa fungsional tanpa ekspresi yang bisa disusun. Saya akan membuat satu, di mana tidak ada ekspresi, hanya pernyataan.
Ini hampir sama seperti yang diberikan sebelumnya, kecuali fungsi dirantai murni melalui rantai pernyataan dan binding.
Gaya pemrograman sentris iterator mungkin salah satu yang diambil oleh Python. Mari gunakan gaya yang murni iteratif, berpusat pada iterator:
Ini tidak berfungsi, karena setiap klausa adalah proses berulang, dan mereka terikat bersama oleh jeda eksplisit dan dimulainya kembali bingkai tumpukan. Sintaksnya mungkin sebagian terinspirasi dari bahasa fungsional, tetapi diterapkan pada perwujudan yang sepenuhnya berulang-ulang.
Tentu saja, Anda dapat mengompres ini:
Imperatif tidak terlihat terlalu buruk sekarang, eh? :)
Poin terakhir adalah tentang aliran kontrol yang lebih eksplisit. Mari kita tulis ulang kode aslinya untuk menggunakan ini:
Dengan menggunakan iterator, Anda dapat memiliki:
Jadi apa adalah titik bahasa fungsional jika perbedaan antara:
Fitur definitif utama dari bahasa pemrograman fungsional adalah menghilangkan mutasi sebagai bagian dari model pemrograman yang khas. Orang sering mengartikan bahwa bahasa pemrograman fungsional tidak memiliki pernyataan atau menggunakan ekspresi, tetapi ini adalah penyederhanaan. Bahasa fungsional menggantikan komputasi eksplisit dengan deklarasi perilaku, yang kemudian dilakukan pengurangan oleh bahasa.
Membatasi diri Anda pada subset fungsionalitas ini memungkinkan Anda memiliki lebih banyak jaminan tentang perilaku program Anda, dan ini memungkinkan Anda untuk menyusunnya dengan lebih bebas.
Jika Anda memiliki bahasa fungsional, membuat fungsi baru umumnya sesederhana membuat fungsi yang terkait erat.
Ini tidak sederhana, atau mungkin bahkan tidak mungkin, jika Anda belum mengontrol dependensi global suatu fungsi secara eksplisit. Fitur terbaik dari pemrograman fungsional adalah Anda dapat secara konsisten membuat abstraksi yang lebih umum dan percaya bahwa abstraksi tersebut dapat digabungkan menjadi keseluruhan yang lebih besar.
sumber
apply
ini tidak sama dengan afold
ataureduce
, meskipun saya setuju dengan kemampuan bagus untuk memiliki algoritme yang sangat umum.apply
meanfold
orreduce
, tetapi bagi saya sepertinya itu harus dalam konteks ini untuk mengembalikan boolean.Dalam paradigma prosedural (haruskah saya mengatakan "pemrograman terstruktur"?), Anda telah berbagi memori dan instruksi yang dapat berubah yang membaca / menulisnya dalam beberapa urutan (satu demi satu).
Dalam paradigma fungsional, Anda memiliki variabel dan fungsi (dalam pengertian matematis: variabel tidak bervariasi dari waktu ke waktu, fungsi hanya dapat menghitung sesuatu berdasarkan masukannya).
(Ini terlalu disederhanakan, misalnya, FPL biasanya memiliki fasilitas untuk bekerja dengan memori yang bisa berubah sedangkan bahasa prosedural seringkali dapat mendukung prosedur tingkat tinggi sehingga hal-hal tidak begitu jelas; tetapi ini akan memberi Anda gambaran)
sumber
The Charming Python: Pemrograman fungsional dengan Python dari IBM Developerworks sangat membantu saya untuk memahami perbedaannya.
Khusus untuk seseorang yang sedikit mengetahui Python, contoh kode dalam artikel ini di mana melakukan hal-hal yang berbeda secara fungsional dan prosedural dibedakan, dapat menjelaskan perbedaan antara pemrograman prosedural dan fungsional.
sumber
Dalam pemrograman fungsional untuk memahami arti sebuah simbol (variabel atau nama fungsi) Anda hanya perlu mengetahui 2 hal - ruang lingkup saat ini dan nama simbol. Jika Anda memiliki bahasa yang berfungsi murni dengan kekekalan, keduanya adalah konsep "statis" (maaf untuk nama yang kelebihan muatan), artinya Anda dapat melihat keduanya - cakupan saat ini dan nama - hanya dengan melihat kode sumber.
Dalam pemrograman prosedural jika Anda ingin menjawab pertanyaan apa nilai di baliknya
x
Anda juga perlu tahu bagaimana Anda sampai di sana, ruang lingkup dan nama saja tidak cukup. Dan inilah yang saya anggap sebagai tantangan terbesar karena jalur eksekusi ini adalah properti "runtime" dan dapat bergantung pada begitu banyak hal yang berbeda, sehingga kebanyakan orang belajar untuk hanya men-debug dan tidak mencoba memulihkan jalur eksekusi.sumber
Baru-baru ini saya memikirkan perbedaan dalam kaitannya dengan Masalah Ekspresi . Deskripsi Phil Wadler sering dikutip, tetapi jawaban yang diterima untuk pertanyaan ini mungkin lebih mudah diikuti. Pada dasarnya, tampaknya bahasa imperatif cenderung memilih satu pendekatan terhadap masalah tersebut, sedangkan bahasa fungsional cenderung memilih yang lain.
sumber
Satu perbedaan yang jelas antara dua paradigma pemrograman adalah status.
Dalam Pemrograman Fungsional, status dihindari. Sederhananya, tidak akan ada variabel yang diberi nilai.
Contoh:
Namun, Pemrograman Prosedural menggunakan status.
Contoh:
sumber