Apakah pemrograman fungsional hanya berbeda, atau apakah sebenarnya benar-benar lebih sulit?

12

Apakah pemrograman fungsional hanya berbeda , atau apakah sebenarnya benar-benar lebih sulit ?

Katakan seseorang yang belum pernah belajar pemrograman sama sekali sebelumnya, dan diajarkan pemrograman fungsional. vs seseorang yang tidak pernah belajar pemrograman sama sekali sebelumnya, dan diajarkan pemrograman imperatif. mana yang akan dia temukan lebih keras? atau sama?

Pertanyaan saya: katakan masalahnya sekarang adalah untuk memasukkan unta,

sedemikian rupa sehingga qwe_asd_zxc_rty_fgh_vbnmenjadiqweAsdZxcRtyFghVbn

Cara proseduralnya adalah:

  1. membaginya di sepanjang _
  2. loop melalui array yang melewatkan item pertama
  3. untuk setiap entri, kami menggunakan huruf besar untuk huruf pertama
  4. gabungkan hasilnya bersama

Cara fungsional adalah:

  1. jika tidak dapat menemukan _kembaliinput
  2. potong inputdulu _(seperti yang kita dapatkan qwedan asd_zxc_rty_gfh_cvb)
  3. huruf besar huruf pertama headdan bahas itu denganf(tail)

Ok jika Anda memiliki latar belakang fungsional DAN memiliki pengalaman substansial dalam pemrograman prosedural, saya ingin bertanya: apakah Anda membutuhkan waktu lebih lama untuk mencari cara prosedural atau akankah Anda membutuhkan waktu lebih lama untuk mengetahui cara fungsional?

Jika Anda memiliki latar belakang prosedural tetapi memiliki pengalaman bertahun-tahun dengan pemrograman fungsional, saya ingin mengajukan pertanyaan yang sama: akankah Anda membutuhkan waktu lebih lama untuk mencari cara prosedural atau akankah lebih lama bagi Anda untuk mengetahui fungsional cara?

Pacerier
sumber
5
Ehrm, "cara prosedural" tampaknya sangat fungsional bagi saya jika kita gunakan mapuntuk langkah 3 daripada loop yang bermutasi. Pendekatan kedua adalah sesuatu yang saya hanya akan mempertimbangkan jika tidak ada fungsi split di perpustakaan standar (dalam hal ini harus dibandingkan dengan solusi imperatif yang juga tidak digunakan split).
sepp2k
8
Tidak ada yang khusus fungsional atau prosedural tentang salah satu contoh Anda. Kedengarannya bagi saya seperti Anda mencoba memperkirakan dari pemahaman yang salah tentang pemrograman fungsional. Tidak heran Anda mendapatkan hasil yang tidak biasa.
Rein Henrichs
Saya tidak berpikir pemrograman fungsional itu sulit, hanya saja berbeda. Jika Anda tidak memiliki pengalaman pemrograman juga mudah dipelajari, tetapi karena alasan tertentu begitu Anda belajar pemrograman imperatif, pemrograman fungsional menjadi sulit.
dan_waterworth
1
Saya pikir perbedaan antara fungsional dan prosedural menjadi diperdebatkan, karena bahasa Mainstream seperti JavaScript, C #, Groovy mengandung lebih banyak fitur fungsional.
user281377
2
Pemrograman imperatif jauh lebih sulit dan kontra-intuitif bagi mereka yang tidak memiliki pengalaman pemrograman sebelumnya. Ekspresi seperti x=x+1dapat meledakkan otak yang tidak terpapar. Pemrograman fungsional adalah alami, itu tidak lebih dari fungsi matematika murni dan convinient ketat.
SK-logic

Jawaban:

12

Hanya berbeda. Pemrograman fungsional jauh lebih dekat hubungannya dengan matematika, yang kebanyakan orang kenal. Keseluruhan "variabel tak berubah" hanya mengejutkan bagi para pemrogram penting di mana pola pikir "bisa berubah" sudah tertanam kuat.

Bagi pendatang baru, seringkali cukup intuitif bahwa Anda tidak bisa begitu saja mengubah nilai sesuatu.

Di mana saya belajar CS, kami diajarkan bahasa fungsional sebagai kursus pertama kami. Dan semua orang yang telah belajar C ++ atau Java sebelumnya berjuang dengan itu. Mereka yang baru dalam pemrograman mengambilnya dengan cukup mudah.

jalf
sumber
jalf apakah Anda salah satu dari mereka yang baru dalam pemrograman dan mengambilnya dengan cukup mudah?
Pacerier
Saya berada di antara keduanya. Saya telah mencari-cari sedikit dengan C ++ dan beberapa PHP sebelum itu, tetapi tidak cukup untuk benar-benar terbiasa dengan pola pikir imperatif. Polanya cukup jelas ketika Anda melihat kelas secara keseluruhan. Juga, ini hampir satu dekade yang lalu, jadi tidak, saya tidak cukup baru untuk pemrograman hari ini;)
jalf
Variabel tidak berubah? Bukankah matematika merupakan bahasa pemrograman fungsional? variabel dalam Mathematica pasti bisa berubah, bukan?
user56834
20

Hanya berbeda

Ketika Anda memprogram Anda pada dasarnya menerjemahkan cara Anda beralasan ke dalam kode, jarak antara pikiran Anda dan solusi akhir mungkin dikatakan sebagai "celah kognitif". Semakin besar celah semakin sulit bagi Anda untuk menjembataninya.

Jika Anda berasal dari latar belakang prosedural, Anda akan melatih diri Anda untuk berpikir secara prosedural sehingga kesenjangannya kurang dari kode fungsional, dan sebaliknya.

Satu-satunya cara agar paradigma pemrograman secara intrinsik lebih mudah daripada yang lain adalah jika dipetakan ke sesuatu yang sudah Anda ketahui, seperti bahasa biasa, sehingga Anda akan memulai dengan jeda yang lebih pendek.

Fungsional dan prosedural adalah konsep yang cukup lancar dan cenderung tumpang tindih

Homde
sumber
4

Ya, pemrograman fungsional cenderung sulit bagi banyak orang untuk memahaminya (saya cenderung mengatakan, terutama mereka yang sudah lebih dulu mengenal pemrograman prosedural).

Saya juga akan mengatakan contoh pemrograman fungsional Anda sebenarnya bukan contoh pemrograman fungsional yang sangat baik. Ini menggunakan rekursi dan hanya menyusun hasil alih-alih mengubah keadaan, tetapi tidak lebih dari itu.

Untuk mendapatkan contoh pemrograman fungsional yang lebih baik, pertimbangkan masalah yang lebih umum: alih-alih "mencari garis bawah dan mengonversi huruf berikutnya menjadi huruf besar", anggap ini hanya satu kasus khusus dalam mencari pola, dan menjalankan beberapa kode arbitrer saat ditemukan

Banyak bahasa mendukungnya, tetapi untuk melakukannya mereka mengharuskan kami menentukan pola sebagai sesuatu seperti ekspresi reguler. Namun, ekspresi reguler tidak lebih dari bahasa pemrograman tujuan khusus, dan implementasi ET adalah kompiler dan / atau penerjemah untuk bahasa tersebut. Hasil kompilasi RE pada dasarnya adalah fungsi yang mengeksekusi (dalam mesin virtual RE khusus) untuk mencocokkan ekspresi terhadap beberapa input.

Dalam sesuatu seperti Perl, Anda menggunakan bahasa khusus untuk menentukan polanya, dan kompiler khusus untuk mengonversi string itu menjadi semacam hal yang mirip fungsi, dan penerjemah khusus untuk mengambil hal yang seperti fungsi itu menjalankannya. Dalam bahasa fungsional, Anda biasanya menggunakan bahasa itu sendiri untuk menentukan pola, dan menggunakan kompiler bahasa sendiri untuk menghasilkan fungsi nyata . Kita dapat menghasilkan fungsi itu dengan cepat (kira-kira seperti kita dapat mengkompilasi RE ketika kita mau), tetapi ketika kita melakukannya, hasilnya dapat mengeksekusi seperti fungsi lain dalam bahasa alih-alih membutuhkan hal-hal RE khusus untuk melakukannya.

Hasilnya adalah kita dapat menggeneralisasi masalah di atas dengan relatif mudah. Namun, alih-alih mengkodekan '_' dan "huruf besar" secara langsung ke dalam transformasi, kita dapat memiliki sesuatu seperti:

s&r(pattern, transform, string) {
    if (!pattern(string))
        return string
    else
        return transform(matched part of string) + s&r(rest of string);
}

Tetapi, tidak seperti sesuatu di mana kita menentukan pola sebagai RE, kita dapat menentukan pola secara langsung sebagai fungsi nyata, dan masih menggunakannya, sesuatu seperti:

my_pattern(string) return beginning(string) == '_';

Dan kemudian kita meneruskan fungsi itu ke s & r. Saat ini, ini adalah fungsi yang sangat sepele, dan kami telah menyandikannya sepenuhnya secara statis. Bahasa fungsional sebagian besar menjadi menarik ketika kita menggunakannya seperti kita dapat RE, dan menghasilkan fungsi yang sama sekali baru dengan cepat berdasarkan pada sesuatu seperti input pengguna, tetapi tidak seperti RE yang berfungsi tidak membutuhkan penerjemah RE khusus untuk menjalankan - itu hanya fungsi normal seperti yang lainnya.

Jerry Coffin
sumber
4

Berikut kode lengkap dalam Racket :

;; camelize : string -> string
(define (camelize str)
  (let ([parts (regexp-split #rx"_" str)])
    ;; result of regexp-split is never empty
    (apply string-append
           (first parts)
           (map string-titlecase (rest parts)))))

(camelize "qwe_asd_zxc_rty_fgh_vbn")
;; => "qweAsdZxcRtyFghVbn"

Sebagai seorang programmer fungsional dengan pengalaman prosedural, saya tidak berpikir itu akan memakan waktu lebih lama untuk "mencari tahu" solusi prosedural, tetapi tentu akan membutuhkan waktu lebih lama untuk mengetiknya.

BTW, contoh hasil yang diharapkan di posting asli salah: itu hilang "h" di akhir.

Ryan Culpepper
sumber
gd untuk menunjukkan itu. diedit
Pacerier
3

Teori hewan peliharaan saya adalah bahwa model pemrograman lebih mudah untuk memahami semakin dekat mereka dengan kerja komputer yang sebenarnya. Pointer sulit dipahami sampai Anda menyadari bahwa mereka pada dasarnya adalah alamat mesin. Rekursi sulit dipahami sampai Anda secara sadar melangkah melalui contoh kecil, melihat frame stack, dan menyadari di mana nilai-nilai berbeda dari variabel yang sama disimpan. Itu tidak berarti bahwa pemrograman assembler lebih mudah daripada pemrograman tingkat tinggi, tetapi setelah melihat bagaimana hal itu dilakukan tidak mengherankan untuk model mental yang merupakan kunci kemahiran - baik dalam pemrograman atau dalam kegunaan umum.

Sekarang, model prosedural agak lebih dekat dengan arsitektur mesin yang biasa: tugas adalah memori (atau register) tulis. Panggilan prosedur benar-benar hanya lompatan mewah, sebuah ifsebenarnya lompatan bersyarat, dll. Tetapi di Lisp, misalnya, tidak ada tingkat rendah yang setara dengan pengikatan leksikal atau ekspresi lambda. Memahami hal itu mengharuskan Anda membayangkan mesin fungsional abstrak yang benar-benar terpisah antara tingkat bahasa dan mesin fisik, karena dan tampaknya kebanyakan orang tidak pernah mencapai sejauh itu.

(Saya saya akrab dengan gagasan bahwa arsitektur von Neumann akhirnya sewenang-wenang, dan kita harus tidak pikiran prasangka pemula dengan rincian yang tidak relevan seperti arsitektur mesin, dan bukannya langsung memperkenalkan mereka semantik bahasa pemrograman. Bahkan, saya sudah Saya sendiri pernah mengajar beberapa kursus. Tetapi semakin saya merasa bahwa ini adalah tujuan yang mulia tetapi salah arah; orang belajar pemrograman dengan membangun pemahaman dari bawah ke atas, dan cara pemrograman fungsional sedikit lebih lama.)

Kilian Foth
sumber
7
Dengan logika itu Assembler harus menjadi yang termudah di antara semua bahasa untuk dipelajari :)
Homde
4
Pemrograman fungsional cukup mudah dimengerti jika Anda melakukannya dari arah yang benar. "Mesin fungsional abstrak" yang Anda sebutkan hanyalah aljabar . Evaluasi dilakukan dengan istilah penulisan ulang; aplikasi fungsi dilakukan dengan substitusi. Pemrogram belajar untuk memecahkan masalah dengan menggunakan alat yang sama yang telah mereka lihat dalam bertahun-tahun matematika. Jika mereka mengejar CS, ada waktu yang cukup untuk memenuhi tumpukan kura-kura nanti; jika tidak, mereka masih belajar keterampilan memecahkan masalah yang berguna dan prinsip-prinsip desain. Lihatlah Cara Mendesain Program .
Ryan Culpepper
2
@mko Tidak, dengan logika ini bytecodes yang sebenarnya 011011001001101...akan menjadi bahasa yang paling mudah untuk dipelajari!
MarkJ
2
@konrad: assembler RISC mungkin bahasa yang paling mudah dipelajari. Untuk mengetahui bagaimana membuatnya melakukan sesuatu yang berguna adalah cerita lain bersama-sama ...
Bryan Boettcher