Apa perbedaan antara pemrograman prosedural dan pemrograman fungsional? [Tutup]

247

Saya telah membaca artikel Wikipedia untuk pemrograman prosedural dan pemrograman fungsional , tetapi saya masih sedikit bingung. Bisakah seseorang merebusnya sampai ke inti?

Thomas Owens
sumber
Wikipedia menyiratkan bahwa FP adalah bagian dari (yaitu selalu) pemrograman deklaratif, tetapi itu tidak benar dan mengonfigurasi taksonomi IP vs DP .
Shelby Moore III

Jawaban:

151

Bahasa fungsional (idealnya) memungkinkan Anda untuk menulis fungsi matematika, yaitu fungsi yang mengambil n argumen dan mengembalikan nilai. Jika program dijalankan, fungsi ini dievaluasi secara logis sesuai kebutuhan. 1

Bahasa prosedural, di sisi lain, melakukan serangkaian langkah berurutan . (Ada cara mengubah logika sekuensial menjadi logika fungsional yang disebut gaya kelanjutan lewat .)

Sebagai konsekuensinya, program murni fungsional selalu menghasilkan nilai yang sama untuk suatu input, dan urutan evaluasi tidak didefinisikan dengan baik; yang berarti bahwa nilai tidak pasti seperti input pengguna atau nilai acak sulit untuk dimodelkan dalam bahasa yang murni fungsional.


1 Seperti semua hal lain dalam jawaban ini, itu adalah generalisasi. Properti ini, mengevaluasi perhitungan ketika hasilnya dibutuhkan daripada secara berurutan di mana ia disebut, dikenal sebagai "kemalasan". Tidak semua bahasa fungsional sebenarnya universal malas, juga kemalasan tidak terbatas pada pemrograman fungsional. Sebaliknya, deskripsi yang diberikan di sini memberikan "kerangka mental" untuk berpikir tentang gaya pemrograman yang berbeda yang bukan kategori yang berbeda dan berlawanan melainkan ide-ide yang mengalir.

Konrad Rudolph
sumber
9
Nilai yang tidak pasti seperti input pengguna atau nilai acak sulit untuk dimodelkan dalam bahasa murni fungsional, tetapi ini adalah masalah yang diselesaikan. Lihat monad.
Apocalisp
" langkah-langkah berurutan , di mana program fungsional akan disarangkan" berarti menyediakan pemisahan-masalah dengan menekankan komposisi fungsi , yaitu memisahkan dependensi di antara subkomputasi dari perhitungan deterministik.
Shelby Moore III
ini tampaknya salah - prosedur dapat juga disarangkan, prosedur dapat memiliki parameter
Hurda
1
@ Burda Ya, bisa mengatakan ini lebih baik. Intinya adalah bahwa pemrograman prosedural terjadi secara bertahap dalam urutan yang ditentukan sebelumnya, sedangkan program fungsional tidak dijalankan secara bertahap; alih-alih, nilai dihitung ketika dibutuhkan. Namun, kurangnya definisi terminologi pemrograman yang disepakati secara umum membuat generalisasi seperti itu menjadi sia-sia. Saya telah mengubah jawaban saya dalam hal itu.
Konrad Rudolph
97

Pada dasarnya kedua gaya itu, seperti Yin dan Yang. Satu terorganisir, sementara yang lain kacau. Ada situasi ketika pemrograman Fungsional adalah pilihan yang jelas, dan situasi lain pemrograman Prosedural adalah pilihan yang lebih baik. Inilah sebabnya mengapa setidaknya ada dua bahasa yang baru-baru ini keluar dengan versi baru, yang mencakup kedua gaya pemrograman. ( Perl 6 dan D 2 )

Prosedural:

  • Output dari suatu rutin tidak selalu memiliki korelasi langsung dengan input.
  • Semuanya dilakukan dalam urutan tertentu.
  • Eksekusi rutin dapat memiliki efek samping.
  • Cenderung menekankan implementasi solusi secara linear.

Perl 6

sub factorial ( UInt:D $n is copy ) returns UInt {

  # modify "outside" state
  state $call-count++;
  # in this case it is rather pointless as
  # it can't even be accessed from outside

  my $result = 1;

  loop ( ; $n > 0 ; $n-- ){

    $result *= $n;

  }

  return $result;
}

D 2

int factorial( int n ){

  int result = 1;

  for( ; n > 0 ; n-- ){
    result *= n;
  }

  return result;
}

Fungsional:

  • Seringkali bersifat rekursif.
  • Selalu mengembalikan output yang sama untuk input yang diberikan.
  • Urutan evaluasi biasanya tidak ditentukan.
  • Harus tanpa kewarganegaraan. yaitu Tidak ada operasi yang dapat memiliki efek samping.
  • Cocok untuk eksekusi paralel
  • Cenderung menekankan pendekatan memecah belah dan menaklukkan.
  • Mungkin memiliki fitur Evaluasi Malas.

Haskell

(disalin dari Wikipedia );

fac :: Integer -> Integer

fac 0 = 1
fac n | n > 0 = n * fac (n-1)

atau dalam satu baris:

fac n = if n > 0 then n * fac (n-1) else 1

Perl 6

proto sub factorial ( UInt:D $n ) returns UInt {*}

multi sub factorial (  0 ) { 1 }
multi sub factorial ( $n ) { $n * samewith $n-1 } # { $n * factorial $n-1 }

D 2

pure int factorial( invariant int n ){
  if( n <= 1 ){
    return 1;
  }else{
    return n * factorial( n-1 );
  }
}

Catatan:

Faktorial sebenarnya adalah contoh umum untuk menunjukkan betapa mudahnya membuat operator baru di Perl 6 dengan cara yang sama seperti Anda membuat subrutin. Fitur ini sudah tertanam dalam Perl 6 sehingga sebagian besar operator dalam implementasi Rakudo didefinisikan dengan cara ini. Hal ini juga memungkinkan Anda untuk menambahkan kandidat multi Anda sendiri ke operator yang ada.

sub postfix:< ! > ( UInt:D $n --> UInt )
  is tighter(&infix:<*>)
  { [*] 2 .. $n }

say 5!; # 120␤

Contoh ini juga memperlihatkan pembuatan rentang ( 2..$n) dan meta-operator pengurangan daftar ( [ OPERATOR ] LIST) yang dikombinasikan dengan operator perkalian infiks numerik. ( *)
Ini juga menunjukkan bahwa Anda dapat memasukkan --> UInttanda tangan alih-alih returns UIntsetelahnya.

(Anda bisa lolos dari memulai rentang dengan 2sebagai "operator" kelipatan akan kembali 1ketika dipanggil tanpa argumen)

Brad Gilbert
sumber
Hai, dapatkah Anda memberikan contoh untuk 2 poin berikut yang disebutkan untuk "Prosedural" dengan mempertimbangkan contoh penerapan faktorial dalam Perl 6. 1) Output dari suatu rutin tidak selalu memiliki korelasi langsung dengan input. 2) Eksekusi rutin dapat memiliki efek samping.
Naga Kiran
sub postfix:<!> ($n) { [*] 1..$n }
Brad Gilbert
@BradGilbert -Bisakah No operation can have side effectsAnda menjelaskannya?
kushalvm
2
Mungkin jawaban terbaik yang pernah saya temukan .... Dan, saya melakukan riset pada poin-poin individual itu .. yang benar-benar membantu saya! :)
Navaneeth
1
@AkashBisariya sub foo( $a, $b ){ ($a,$b).pick }← tidak selalu mengembalikan output yang sama untuk input yang sama, sedangkan yang berikut tidaksub foo( $a, $b ){ $a + $b }
Brad Gilbert
70

Saya belum pernah melihat definisi ini diberikan di tempat lain, tetapi saya pikir ini meringkas perbedaan yang diberikan di sini dengan cukup baik:

Pemrograman fungsional berfokus pada ekspresi

Pemrograman prosedural berfokus pada pernyataan

Ekspresi memiliki nilai. Program fungsional adalah ekspresi yang nilainya adalah urutan instruksi yang dapat dilakukan komputer.

Pernyataan tidak memiliki nilai dan sebagai gantinya mengubah keadaan beberapa mesin konseptual.

Dalam bahasa murni fungsional tidak akan ada pernyataan, dalam arti bahwa tidak ada cara untuk memanipulasi negara (mereka mungkin masih memiliki konstruksi sintaksis bernama "pernyataan", tetapi kecuali jika memanipulasi keadaan saya tidak akan menyebutnya pernyataan dalam pengertian ini ). Dalam bahasa yang murni prosedural tidak akan ada ekspresi, semuanya akan menjadi instruksi yang memanipulasi keadaan mesin.

Haskell akan menjadi contoh bahasa murni fungsional karena tidak ada cara untuk memanipulasi keadaan. Kode mesin akan menjadi contoh bahasa yang murni prosedural karena segala sesuatu dalam suatu program adalah pernyataan yang memanipulasi keadaan register dan memori mesin.

Bagian membingungkan adalah bahwa sebagian besar bahasa pemrograman mengandung kedua ekspresi dan pernyataan, yang memungkinkan Anda untuk mencampur paradigma. Bahasa dapat diklasifikasikan sebagai lebih fungsional atau lebih prosedural berdasarkan seberapa banyak mereka mendorong penggunaan pernyataan vs ekspresi.

Sebagai contoh, C akan lebih fungsional daripada COBOL karena panggilan fungsi adalah ekspresi, sedangkan memanggil sub program di COBOL adalah pernyataan (yang memanipulasi keadaan variabel bersama dan tidak mengembalikan nilai). Python akan lebih fungsional daripada C karena memungkinkan Anda untuk mengekspresikan logika kondisional sebagai ekspresi menggunakan evaluasi hubung singkat (test && path1 || path2 sebagai lawan pernyataan if). Skema akan lebih fungsional daripada Python karena semua yang ada dalam skema adalah ekspresi.

Anda masih dapat menulis dengan gaya fungsional dalam bahasa yang mendorong paradigma prosedural dan sebaliknya. Lebih sulit dan / atau lebih canggung untuk menulis dalam paradigma yang tidak didukung oleh bahasa.

Omnimike
sumber
2
Penjelasan terbaik dan paling ringkas yang pernah saya lihat di web, bravo!
tommed
47

Dalam ilmu komputer, pemrograman fungsional adalah paradigma pemrograman yang memperlakukan komputasi sebagai evaluasi fungsi matematika dan menghindari keadaan dan data yang bisa berubah. Ini menekankan penerapan fungsi, berbeda dengan gaya pemrograman prosedural yang menekankan perubahan status.

juan
sumber
4
Walaupun ini adalah penjelasan yang paling membantu saya, saya masih bingung pada konsep pemrograman fungsional. Saya mencari gaya pemrograman yang tidak bergantung pada referensi objek eksternal untuk menjalankan (setiap hal fungsi yang harus dijalankan harus diteruskan sebagai parameter). Sebagai contoh, saya tidak akan pernah memasukkan GetUserContext()fungsi, konteks pengguna akan diteruskan. Apakah ini pemrograman fungsional? Terima kasih sebelumnya.
Matt Cashatt
26

Saya percaya bahwa pemrograman prosedural / fungsional / obyektif adalah tentang bagaimana mendekati suatu masalah.

Gaya pertama akan merencanakan semuanya menjadi langkah, dan menyelesaikan masalah dengan menerapkan satu langkah (prosedur) pada suatu waktu. Di sisi lain, pemrograman fungsional akan menekankan pendekatan divide-and-conquer, di mana masalah dibagi menjadi sub-masalah, maka setiap sub-masalah diselesaikan (membuat fungsi untuk menyelesaikan sub masalah itu) dan hasilnya digabungkan ke buat jawaban untuk seluruh masalah. Terakhir, pemrograman Objective akan meniru dunia nyata dengan membuat dunia-mini di dalam komputer dengan banyak objek, yang masing-masing memiliki (agak) karakteristik unik, dan berinteraksi dengan yang lain. Dari interaksi tersebut, hasilnya akan muncul.

Setiap gaya pemrograman memiliki kelebihan dan kelemahannya sendiri. Oleh karena itu, melakukan sesuatu seperti "pemrograman murni" (yaitu murni prosedural - tidak ada yang melakukan ini, omong-omong, yang agak aneh - atau murni fungsional atau murni objektif) sangat sulit, jika bukan tidak mungkin, kecuali beberapa masalah dasar khusus dirancang untuk menunjukkan keunggulan gaya pemrograman (karenanya, kami menyebut mereka yang menyukai kemurnian "weenie": D).

Kemudian, dari gaya tersebut, kami memiliki bahasa pemrograman yang dirancang untuk dioptimalkan untuk beberapa gaya masing-masing. Misalnya, Majelis semua tentang prosedural. Oke, sebagian besar bahasa awal bersifat prosedural, bukan hanya ASM, seperti C, Pascal, (dan Fortran, saya dengar). Kemudian, kita memiliki semua Java yang terkenal di sekolah objektif (Sebenarnya, Java dan C # juga berada dalam kelas yang disebut "berorientasi uang," tetapi itu perlu dibahas lagi). Juga objektif adalah Smalltalk. Di sekolah fungsional, kita akan memiliki "hampir fungsional" (beberapa menganggap mereka tidak murni) keluarga Lisp dan keluarga ML dan banyak "murni fungsional" Haskell, Erlang, dll. Omong-omong, ada banyak bahasa umum seperti Perl, Python , Ruby.

Aaron Hall
sumber
26

Pemrograman Funtional

num = 1 
def function_to_add_one(num):
    num += 1
    return num


function_to_add_one(num)
function_to_add_one(num)
function_to_add_one(num)
function_to_add_one(num)
function_to_add_one(num)

#Final Output: 2

Pemrograman Prosedural

num = 1 
def procedure_to_add_one():
    global num
    num += 1
    return num


procedure_to_add_one()
procedure_to_add_one()
procedure_to_add_one()
procedure_to_add_one()
procedure_to_add_one()

#Final Output: 6

function_to_add_one adalah suatu fungsi

procedure_to_add_one adalah sebuah prosedur

Bahkan jika Anda menjalankan fungsi lima kali, setiap kali itu akan kembali 2

Jika Anda menjalankan prosedur lima kali, pada akhir menjalankan kelima akan memberi Anda 6 .

Hamza Zubair
sumber
5
contoh ini sangat sederhana untuk memahami istilah "stateless" & "data abadi" dalam pemrograman fungsional, membaca semua definisi & perbedaan yang tercantum di atas tidak menghapus kebingungan saya sampai membaca jawaban ini. Terima kasih!
maximus
13

Untuk memperluas komentar Konrad:

Sebagai konsekuensinya, program murni fungsional selalu menghasilkan nilai yang sama untuk suatu input, dan urutan evaluasi tidak didefinisikan dengan baik;

Karena itu, kode fungsional umumnya lebih mudah diparalelkan. Karena (umumnya) tidak ada efek samping dari fungsi, dan mereka (umumnya) hanya bertindak berdasarkan argumen mereka, banyak masalah konkurensi hilang.

Pemrograman fungsional juga digunakan ketika Anda harus mampu membuktikan kode Anda sudah benar. Ini jauh lebih sulit untuk dilakukan dengan pemrograman prosedural (tidak mudah dengan fungsional, tetapi masih lebih mudah).

Penafian: Saya tidak pernah menggunakan pemrograman fungsional selama bertahun-tahun, dan baru saja mulai melihatnya lagi, jadi saya mungkin tidak sepenuhnya benar di sini. :)

Herms
sumber
12

Satu hal yang belum saya lihat benar-benar ditekankan di sini adalah bahwa bahasa fungsional modern seperti Haskell benar-benar lebih pada fungsi kelas satu untuk kontrol aliran daripada rekursi eksplisit. Anda tidak perlu mendefinisikan faktorial secara rekursif di Haskell, seperti yang dilakukan di atas. Saya pikir sesuatu seperti

fac n = foldr (*) 1 [1..n]

adalah konstruksi idiomatis yang sempurna, dan jauh lebih dekat dalam roh untuk menggunakan loop daripada menggunakan rekursi eksplisit.

C Hogg
sumber
10

Pemrograman fungsional identik dengan pemrograman prosedural di mana variabel global tidak digunakan.

Nir O.
sumber
7

Bahasa prosedural cenderung untuk melacak negara (menggunakan variabel) dan cenderung mengeksekusi sebagai urutan langkah-langkah. Bahasa yang murni fungsional tidak melacak keadaan, menggunakan nilai-nilai yang tidak dapat diubah, dan cenderung dieksekusi sebagai serangkaian dependensi. Dalam banyak kasus, status tumpukan panggilan akan menyimpan informasi yang setara dengan apa yang akan disimpan dalam variabel status dalam kode prosedural.

Rekursi adalah contoh klasik pemrograman gaya fungsional.

Baji
sumber
1
Setelah membaca halaman ini saya memikirkan hal yang sama -> "Rekursi adalah contoh klasik dari pemrograman gaya fungsional", dan Anda membersihkannya. Terima kasih, Sekarang saya pikir saya mendapatkan sesuatu.
Mudassir Hussain
6

Konrad berkata:

Sebagai konsekuensinya, program murni fungsional selalu menghasilkan nilai yang sama untuk suatu input, dan urutan evaluasi tidak didefinisikan dengan baik; yang berarti bahwa nilai tidak pasti seperti input pengguna atau nilai acak sulit untuk dimodelkan dalam bahasa yang murni fungsional.

Urutan evaluasi dalam program yang murni fungsional mungkin sulit (er) untuk alasan tentang (terutama dengan kemalasan) atau bahkan tidak penting tapi saya pikir mengatakan itu tidak didefinisikan dengan baik membuatnya terdengar seperti Anda tidak dapat mengetahui apakah program Anda berjalan bekerja sama sekali!

Mungkin penjelasan yang lebih baik adalah bahwa aliran kontrol dalam program fungsional didasarkan pada ketika nilai argumen fungsi dibutuhkan. Hal Baik tentang hal ini bahwa dalam program yang ditulis dengan baik, status menjadi eksplisit: setiap fungsi mencantumkan inputnya sebagai parameter alih-alih mengubah keadaan global secara sewenang-wenang . Jadi pada tingkat tertentu, lebih mudah untuk berpikir tentang urutan evaluasi sehubungan dengan satu fungsi pada suatu waktu . Setiap fungsi dapat mengabaikan seluruh alam semesta dan fokus pada apa yang perlu dilakukan. Ketika dikombinasikan, fungsi dijamin bekerja sama [1] seperti yang mereka lakukan secara terpisah.

... nilai tidak pasti seperti input pengguna atau nilai acak sulit untuk dimodelkan dalam bahasa yang murni fungsional.

Solusi untuk masalah input dalam program murni fungsional adalah dengan menanamkan bahasa imperatif sebagai DSL menggunakan abstraksi yang cukup kuat . Dalam bahasa imperatif (atau non-murni fungsional) ini tidak diperlukan karena Anda dapat "menipu" dan melewati status secara implisit dan urutan evaluasi eksplisit (baik suka atau tidak). Karena ini "curang" dan evaluasi paksa semua parameter untuk setiap fungsi, dalam bahasa imperatif 1) Anda kehilangan kemampuan untuk membuat mekanisme aliran kontrol Anda sendiri (tanpa makro), 2) kode tidak inheren thread aman dan / atau diparalelkan secara default, 3) dan mengimplementasikan sesuatu seperti undo (perjalanan waktu) membutuhkan kerja yang hati-hati (programmer imperatif harus menyimpan resep untuk mendapatkan kembali nilai lama!), Sedangkan pemrograman fungsional murni memberi Anda semua hal ini — dan beberapa lagi saya dapat lupa— "gratis".

Saya harap ini tidak terdengar seperti semangat, saya hanya ingin menambahkan beberapa perspektif. Pemrograman imperatif dan pemrograman paradigma campuran dalam bahasa yang kuat seperti C # 3.0 masih merupakan cara yang sangat efektif untuk menyelesaikan sesuatu dan tidak ada peluru perak .

[1] ... kecuali mungkin dengan menghormati penggunaan memori (lih. Foldl dan foldl 'di Haskell).

Jared Updike
sumber
5

Untuk memperluas komentar Konrad:

dan urutan evaluasi tidak didefinisikan dengan baik

Beberapa bahasa fungsional memiliki apa yang disebut Evaluasi Malas. Yang berarti suatu fungsi tidak dieksekusi sampai nilainya dibutuhkan. Sampai saat itu fungsi itu sendiri adalah apa yang diedarkan.

Bahasa prosedural adalah langkah 1 langkah 2 langkah 3 ... jika dalam langkah 2 Anda mengatakan tambahkan 2 + 2, ia melakukannya saat itu juga. Dalam evaluasi malas Anda akan mengatakan menambahkan 2 + 2, tetapi jika hasilnya tidak pernah digunakan, itu tidak pernah melakukan penambahan.

Brian Leahy
sumber
4

Jika Anda memiliki kesempatan, saya akan merekomendasikan untuk mendapatkan salinan Lisp / Skema, dan melakukan beberapa proyek di dalamnya. Sebagian besar ide yang belakangan ini menjadi kereta musik diungkapkan dalam Lisp dekade lalu: pemrograman fungsional, lanjutan (sebagai penutup), pengumpulan sampah, bahkan XML.

Jadi itu akan menjadi cara yang baik untuk memulai semua ide saat ini, dan beberapa lagi, seperti perhitungan simbolik.

Anda harus tahu untuk apa pemrograman fungsional baik, dan untuk apa tidak baik. Itu tidak baik untuk semuanya. Beberapa masalah paling baik diungkapkan dalam hal efek samping, di mana pertanyaan yang sama memberikan jawaban yang berbeda tergantung pada kapan ditanya.

Mike Dunlavey
sumber
3

@Creighton:

Di Haskell ada fungsi perpustakaan yang disebut produk :

prouduct list = foldr 1 (*) list

atau hanya:

product = foldr 1 (*)

jadi faktorial "idiomatik"

fac n = foldr 1 (*)  [1..n]

hanya akan

fac n = product [1..n]
Jared Updike
sumber
Ini tidak memberikan jawaban untuk pertanyaan itu. Untuk mengkritik atau meminta klarifikasi dari penulis, tinggalkan komentar di bawah posting mereka.
Nick Kitto
Saya percaya ini telah diposting bertahun-tahun yang lalu, sebelum sistem komentar ditambahkan, jika Anda dapat mempercayainya: stackoverflow.com/help/badges/30/beta?userid=2543
Jared Updike
2

Pemrograman prosedural membagi urutan pernyataan dan konstruksi kondisional ke dalam blok terpisah yang disebut prosedur yang diparameterisasi terhadap argumen yang merupakan nilai (non-fungsional).

Pemrograman fungsional adalah sama kecuali bahwa fungsi adalah nilai kelas satu, sehingga mereka dapat diteruskan sebagai argumen ke fungsi lain dan dikembalikan sebagai hasil dari pemanggilan fungsi.

Perhatikan bahwa pemrograman fungsional adalah generalisasi pemrograman prosedural dalam interpretasi ini. Namun, minoritas menafsirkan "pemrograman fungsional" berarti bebas efek samping yang sangat berbeda tetapi tidak relevan untuk semua bahasa fungsional utama kecuali Haskell.

Jon Harrop
sumber
1

Untuk memahami perbedaannya, kita perlu memahami bahwa paradigma "ayah baptis" pemrograman pemrograman prosedural dan fungsional adalah pemrograman imperatif .

Pada dasarnya pemrograman prosedural hanyalah cara menyusun program-program penting di mana metode utama abstraksi adalah "prosedur." (atau "fungsi" dalam beberapa bahasa pemrograman). Bahkan Pemrograman Berorientasi Objek hanyalah cara lain untuk menyusun program imperatif, di mana negara dirangkum dalam objek, menjadi objek dengan "kondisi saat ini," ditambah objek ini memiliki serangkaian fungsi, metode, dan hal-hal lain yang memungkinkan Anda Programmer memanipulasi atau memperbarui status.

Sekarang, dalam hal pemrograman fungsional, intinya dalam pendekatannya adalah ia mengidentifikasi nilai apa yang harus diambil dan bagaimana nilai-nilai ini harus ditransfer. (jadi tidak ada status, dan tidak ada data yang dapat berubah karena mengambil fungsi sebagai nilai kelas pertama dan meneruskannya sebagai parameter ke fungsi lain).

PS: Memahami setiap paradigma pemrograman digunakan untuk harus menjelaskan perbedaan di antara mereka semua.

PSS: Pada akhirnya, paradigma pemrograman hanyalah pendekatan yang berbeda untuk menyelesaikan masalah.

PSS: jawaban kuora ini punya penjelasan yang bagus.

Fouad Boukredine
sumber
0

Tidak ada jawaban di sini yang menunjukkan pemrograman fungsional idiomatik. Jawaban faktorial rekursif sangat bagus untuk mewakili rekursi dalam FP, tetapi sebagian besar kode tidak rekursif jadi saya tidak berpikir jawaban itu sepenuhnya representatif.

Katakanlah Anda memiliki array string, dan setiap string mewakili integer seperti "5" atau "-200". Anda ingin memeriksa larik masukan string ini terhadap kasus uji internal Anda (Menggunakan perbandingan bilangan bulat). Kedua solusi ditunjukkan di bawah ini

Prosedural

arr_equal(a : [Int], b : [Str]) -> Bool {
    if(a.len != b.len) {
        return false;
    }

    bool ret = true;
    for( int i = 0; i < a.len /* Optimized with && ret*/; i++ ) {
        int a_int = a[i];
        int b_int = parseInt(b[i]);
        ret &= a_int == b_int;  
    }
    return ret;
}

Fungsional

eq = i, j => i == j # This is usually a built-in
toInt = i => parseInt(i) # Of course, parseInt === toInt here, but this is for visualization

arr_equal(a : [Int], b : [Str]) -> Bool =
    zip(a, b.map(toInt)) # Combines into [Int, Int]
   .map(eq)
   .reduce(true, (i, j) => i && j) # Start with true, and continuously && it with each value

Sementara bahasa fungsional murni umumnya adalah bahasa penelitian (Karena dunia nyata menyukai efek samping gratis), bahasa prosedural dunia nyata akan menggunakan sintaksis fungsional yang jauh lebih sederhana bila perlu.

Ini biasanya diimplementasikan dengan perpustakaan eksternal seperti Lodash , atau tersedia built-in dengan bahasa yang lebih baru seperti Rust . Angkat berat dari pemrograman fungsional dilakukan dengan fungsi / konsep seperti map, filter, reduce, currying, partial, tiga terakhir yang Anda dapat melihat untuk pemahaman lebih lanjut.

Tambahan

Agar dapat digunakan di alam bebas, kompiler biasanya harus mencari cara untuk mengubah versi fungsional menjadi versi prosedural secara internal, karena overhead panggilan fungsi terlalu tinggi. Kasus rekursif seperti faktorial yang ditampilkan akan menggunakan trik seperti tail call untuk menghapus O (n) penggunaan memori. Fakta bahwa tidak ada efek samping memungkinkan kompiler fungsional untuk mengimplementasikan && retoptimasi bahkan ketika .reduceitu dilakukan terakhir. Menggunakan Lodash di JS, jelas tidak memungkinkan untuk optimasi apa pun, jadi ini adalah hit untuk kinerja (Yang biasanya tidak menjadi perhatian dengan pengembangan web). Bahasa seperti Rust akan mengoptimalkan secara internal (Dan memiliki fungsi seperti try_folduntuk membantu && retoptimasi).

Nicholas Pipitone
sumber