Apakah Javascript Bahasa Pemrograman Fungsional

34
  • Apakah Javascript adalah bahasa fungsional? Saya tahu ia memiliki objek & Anda juga dapat melakukan OOP, tetapi apakah ini juga merupakan bahasa fungsional, dapatkah digunakan dengan cara itu?
  • Anda tahu bagaimana OOP menjadi / tampak seperti evolusi berikutnya dalam pemrograman, apakah itu berarti bahwa 'Pemrograman Fungsional' adalah evolusi berikutnya (Catatan: ini BUKAN prompt untuk pendapat. TAPI prompt untuk jawaban berdasarkan bukti faktual, & catatan ini adalah lebih banyak untuk moderator daripada kontributor;)).
  • Saya belajar paling baik melalui contoh-contoh, mungkin seseorang dapat menunjukkan melakukan tugas yang sama dengan cara OOP & kemudian dengan cara Pemrograman Fungsional bagi saya untuk memahami & membandingkan apa yang pemrograman fungsional lakukan / adalah.

Saya tidak benar-benar sepenuhnya memahami 'Pemrograman Fungsional' jujur: P Jadi membandingkan Javascript dengan pemrograman fungsional mungkin sama sekali salah.

Untuk menempatkan pemrograman Fungsional dalam istilah awam: apakah itu hanya manfaat abstrasi MELALUI menggunakan fungsi anonim?

Atau apakah itu terlalu sederhana? Secara sederhana, OOP adalah manfaat dari abstraksi melalui objek, tapi saya percaya itu agak terlalu sederhana untuk menggambarkan OOP.

Apakah ini contoh yang baik dari pemrograman fungsional? ...

Contoh Javascript OOP:

// sum some numbers
function Number( v )
{ 
  this.val = v;
}

Number.prototype.add( /*Number*/ n2 )
{
    this.val += n2.val;
}

Contoh pemrograman fungsional:

function forEach(array, action) 
{
   for (var i = 0; i < array.length; i++)
       action(array[i]);
}  

function add(array)
{
    var i=0;
    forEach(array, function(n)
    {
        i += n;
    });
    return i;
}

var res = add([1,9]);
Marek
sumber
Itu tergantung pada definisi "bahasa pemrograman fungsional". Dalam arti luas, dapat dipahami sebagai kemampuan untuk membangun nilai-nilai fungsional dengan nilai-nilai tertutup, yaitu memiliki konstruksi "lambda" (dalam arti lambda-calculus), dan kemudian Javascript sesuai dengan tagihan.
Basile Starynkevitch
2
Or is that way too simple?Ya, benar. Fungsi anonim kadang-kadang dikaitkan dengan bahasa fungsional dan bahasa multi-paradigma yang mendukung pemrograman fungsional, tetapi mereka bukan karakteristik unik dari bahasa fungsional. Tetapi jika Anda melihatnya sebagai implementasi kalkulus λ, yah mereka adalah bagian inti dari pemrograman fungsional, poin utamanya adalah bahwa itu tidak begitu sederhana :)
yannis
Desain Javascript mencegah implementasi yang dapat melakukan optimasi panggilan-ekor. Dalam buku-buku saya itu saja mencegahnya diberi label fungsional.
dan_waterworth
I know it has objects & you can do OOP with it alsoTidak, kamu tidak bisa. Ini pemrograman berbasis prototipe yang menghilangkan perbedaan antara kelas dan objek. Secara pribadi saya menganggap pemrograman berbasis prototipe cacat pada tingkat dasar ini.
RokL
Javascript bukan bahasa fungsional, tentu saja ia memiliki fitur fungsional tetapi begitu juga imperatif C yang baik, sebenarnya setiap bahasa memiliki fitur fungsional dasar. Bahasa fungsional murni, seperti Haskell, ML, dll, adalah bahasa deklaratif, bukan imperatif.
ALXGTV

Jawaban:

72

Apakah Javascript adalah bahasa fungsional? Saya tahu ia memiliki objek & Anda juga dapat melakukan OOP, tetapi apakah ini juga merupakan bahasa fungsional, dapatkah digunakan dengan cara itu?

Terkadang, orang akan mengatakan pemrograman fungsional, ketika yang mereka maksud adalah pemrograman imperatif atau pemrograman prosedural . Sebenarnya, pemrograman fungsional adalah:

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 imperatif, yang menekankan perubahan dalam keadaan. Pemrograman fungsional berakar pada kalkulus lambda, sistem formal yang dikembangkan pada 1930-an untuk menyelidiki definisi fungsi, aplikasi fungsi, dan rekursi. Banyak bahasa pemrograman fungsional dapat dilihat sebagai elaborasi pada kalkulus lambda.

Meskipun Javascript tidak dikenal secara luas atau digunakan sebagai bahasa fungsional, Javascript memiliki beberapa elemen fungsional :

JavaScript memiliki banyak kesamaan dengan Skema. Ini adalah bahasa yang dinamis. Ini memiliki tipe data fleksibel (array) yang dapat dengan mudah mensimulasikan ekspresi-s. Dan yang paling penting, fungsinya adalah lambda.

Skema adalah dialek Lisp , dan mungkin salah satu bahasa yang dipikirkan sebagian besar programmer ketika mereka membahas pemrograman fungsional. Ketika datang ke orientasi objek , Javascript adalah bahasa yang berorientasi objek. Tetapi orientasi objeknya adalah berdasarkan prototipe :

Pemrograman berbasis prototipe adalah gaya pemrograman berorientasi objek di mana kelas tidak ada, dan penggunaan kembali perilaku (dikenal sebagai pewarisan dalam bahasa berbasis kelas) dilakukan melalui proses kloning objek yang ada yang berfungsi sebagai prototipe. Model ini juga dapat dikenal sebagai pemrograman tanpa kelas, berorientasi prototipe atau berbasis instance. Delegasi adalah fitur bahasa yang mendukung pemrograman berbasis prototipe.

Jadi walaupun Javascript berorientasi objek, ia tidak mengikuti model berbasis kelas yang lebih umum , seperti halnya bahasa seperti C ++, C #, Java dan PHP (dan beberapa lainnya). Dan tentu saja itu juga bahasa yang sangat penting, yang mengarah pada kebingungan dengan pemrograman fungsional yang saya jelaskan di atas.

Anda tahu bagaimana OOP menjadi / tampak seperti evolusi berikutnya dalam pemrograman, apakah itu berarti bahwa 'Pemrograman Fungsional' adalah evolusi berikutnya

Orientasi objek dan pemrograman fungsional hanyalah dua dari banyak paradigma pemrograman yang berbeda , mereka adalah gaya pemrograman yang berbeda dengan konsep dan abstraksi yang berbeda. Kata kuncinya adalah "berbeda". Tidak ada paradigma tunggal yang lebih baik daripada yang lain atau lebih berkembang daripada yang lain, masing-masing dan setiap skenario cocok lebih baik dari yang lain. Beberapa mungkin lebih tua asalnya daripada yang lain, tetapi dalam istilah evolusi yang membuat mereka lebih baik, karena mereka telah bertahan lebih lama. Tapi itu bukan cara yang sangat cerdas untuk melihatnya.

Javascript, seperti yang saya jelaskan di atas dan beberapa bahasa lainnya, multi-paradigma. Hal ini memungkinkan Anda untuk menulis kode dalam gaya imperatif, berorientasi objek dan gaya fungsional. Terserah Anda untuk memilih mana yang paling cocok untuk apa pun yang Anda bangun. Ada juga beberapa bahasa paradigma tunggal, contoh kanonik adalah Java, yang hanya memungkinkan untuk pemrograman berorientasi objek berbasis kelas 1 .

Anda harus benar-benar menahan keinginan untuk memperlakukan bahasa & paradigma sebagai pernyataan mode. Ada banyak omong kosong di luar sana, kebanyakan ditulis oleh fanboys / fangirls atau orang pemasaran, dengan sedikit (jika ada) pengetahuan dan pemahaman pemrograman. Istilah seperti "lebih baik", "lebih berkembang" dll, tidak berlaku.

Saya belajar paling baik melalui contoh-contoh, mungkin seseorang dapat menunjukkan melakukan tugas yang sama dengan cara OOP & kemudian dengan cara Pemrograman Fungsional bagi saya untuk memahami & membandingkan apa yang pemrograman fungsional lakukan / adalah.

Itu akan menjadi cara yang buruk untuk belajar. Orientasi fungsional dan objek adalah gaya yang sangat berbeda, dan contoh apa pun selain yang sangat sederhana tidak akan cocok dengan satu atau gaya lainnya.

1 Tetapi belakangan mencoba memperluas cakupannya ke pemrograman generik, mari kita lihat bagaimana kelanjutannya.


Kesimpulannya:

  • Berkonsentrasi pada belajar Javascript, itu adalah bahasa yang indah dan sangat berguna. Pelajari bahasa, bukan hype.
  • Cukup banyak paradigma yang berbeda, semuanya sama-sama bermanfaat. Terserah Anda untuk memilih mana yang Anda sukai dan mana yang paling cocok apa pun yang Anda bangun.
  • Jika Anda ingin mempelajari pemrograman fungsional, pilih bahasa yang lebih cocok, seperti Skema atau Clojure . Tetapi pertama-tama Anda harus memahami konsep matematika yang terlibat.
  • Lakukan riset sebelum Anda bertanya. Sebagian besar pertanyaan Anda dijawab oleh artikel Wikipedia yang relevan. Mengetahui cara meneliti dan bertanya adalah keterampilan yang sangat penting bagi setiap programmer.
yannis
sumber
5
+1 Respons yang bagus. Karena cara pemrograman pendidikan terstruktur, coders baru tampaknya berpikir paradigma itu eksklusif dan terpisah, tetapi mereka tidak. Cobalah untuk menulis kode OOP yang memanfaatkan konsep fungsional ketika masuk akal untuk melakukannya. Pemrograman yang digerakkan oleh acara adalah sebuah paradigma, tetapi aspek-aspek dari pengaruh EDP tentu saja setiap gui dan program web. Polimorfisme , fitur inti dari OOP, benar-benar pemrograman generik. Memberi nama ide-ide ini membantu kami membuat konsep pemrograman yang baik, tetapi Anda tidak boleh menggunakannya untuk mengesampingkan orang lain.
kojiro
Meskipun pertanyaan awal dan jawaban Anda menggambarkan Javascript dan hubungannya dengan pemrograman fungsional, saya pikir jawaban Anda adalah salah satu perbandingan yang lebih baik antara OO dan pemrograman fungsional yang pernah saya lihat. Sudah selesai dilakukan dengan baik.
AnotherDeveloper
“Itu akan menjadi cara yang buruk untuk belajar.” Saya baru saja selesai membaca buku ini yang menyajikan masalah dan menyelesaikannya dengan berbagai paradigma, termasuk gaya OOP dan FP: github.com/crista/exercises-in-programming-style . Saya belajar banyak dari hal itu!
Nick
@nick Itu hanya bisa menjelaskan kepada Anda seperti apa paradigma itu dan bagaimana cara kerjanya, tetapi tidak memberi tahu Anda mengapa , yang bisa dibilang adalah aspek yang paling penting. Tetapi Anda perlu belajar bagaimana sebelum Anda dapat mengetahui mengapa :) kadang-kadang kita lupa bahwa hal-hal ini adalah sebuah proses.
Matius Brent
8

Javascript dapat digunakan sebagai bahasa fungsional, bahkan ia melakukannya dengan cukup baik. Dimungkinkan untuk mengimplementasikan monads yang memiliki dukungan untuk konstruk lambda dll. Ini tidak secara eksklusif merupakan bahasa fungsional karena ia juga memiliki banyak fitur berorientasi objek tetapi dapat digunakan dengan cara itu. Sebenarnya saya menemukan bahwa menggunakan Javascript sebagai bahasa fungsional adalah cara yang bagus untuk menggunakannya. (Contoh jQuery dan underscore.js)

Zachary K
sumber
bagus & ringkas! Setuju bahwa pemrograman fungsional seringkali merupakan cara termudah untuk menyelesaikan sesuatu dalam js.
bunglestink
Bahkan lebih menarik daripada monad, Anda dapat mengimplementasikan panah adalah JS ( cs.umd.edu/projects/PL/arrowlets ). Sekarang, mengapa ada orang yang ingin panah dalam JavaScript, itu pertanyaan terbuka. Tapi itu bisa dilakukan.
rtperson
Saya akan mengakui bahwa saya tidak cukup mengerti tentang panah untuk mengetahui apakah mereka akan berguna. Tetapi saya sedang mengerjakan sebuah Buku tentang Monads dalam Javascript dan dapat menambahkan satu bab tentang Arrows ( shop.oreilly.com/product/0636920023890.do )
Zachary K
6

Evolusi biasanya berarti perubahan bertahap . OOP bukan tambahan tambahan untuk pemrograman prosedural - pada kenyataannya, itu sepenuhnya ortogonal untuk model pemrograman yang mendasarinya dan dapat dikombinasikan dengan salah satu dari mereka. Pemrograman fungsional bukan merupakan tambahan tambahan untuk prosedural, OOP atau apa pun - itu adalah alternatif dasar untuk mengekspresikan prinsip-prinsip komputasi yang mendasar, dan itu sebenarnya pertama dasar seperti yang pernah dirumuskan, jauh sebelum komputer pertama kali muncul. Penting untuk dipahami bahwa semua sistem fundamental semacam itu setara (yaitu, satu dapat diekspresikan dalam bentuk yang lain).

Untuk memahami pendekatan fungsional, Anda harus mendapatkan matematika dasar terlebih dahulu. Jika Anda ingin mengetahui apa artinya kode dalam gaya fungsional dalam Javascript, mulailah menggunakan jQuery .

Logika SK
sumber
2

Tidak.

JavaScript adalah bahasa berorientasi objek pertama dan terutama.

Itu bukan untuk mengatakan bahwa Anda tidak dapat menulis program JavaScript dalam gaya fungsional, karena Anda dapat mengadopsi gaya fungsional di setiap Turing bahasa yang lengkap jika Anda mencoba cukup keras. Anda dapat melakukan pemrograman fungsional dalam assembler jika Anda suka. Tetapi ini tidak membuat setiap bahasa berfungsi. Anda mungkin juga sama-sama memanggil Haskell imperative, atau Java bahasa pemrograman logika - jika Anda mengambil pendekatan ini, istilah itu akan segera menjadi tidak berarti.

IMO cara untuk mengklasifikasikan bahasa ke dalam paradigma yang sesuai adalah dengan mempertimbangkan:

  • Apa gaya dominan yang diaktifkan oleh konstruksi bahasa (jelas OOP untuk JavaScript, bahasa fungsional alih-alih menekankan fungsi dan nilai data yang tidak berubah)
  • Paradigma apa yang didukung dalam pustaka inti bahasa (sekali lagi jelas OOP untuk JavaScript)
  • Fitur apa yang dinonaktifkan atau tidak disarankan dalam bahasa (bahasa fungsional mencegah atau melarang variabel yang dapat diubah, yang tidak berlaku untuk JavaScript)
  • Apa gaya pengembangan yang lazim di komunitas pengembang yang menggunakan bahasa (sekali lagi, OOP jelas lazim di dunia JavaScript)

Secara pribadi saya merasa agak lucu bahwa banyak orang suka mengklaim bahasa adalah "fungsional" hanya karena itu adalah istilah yang trendi saat ini :-)

Jika Anda ingin perspektif yang sedikit panjang namun menghibur tentang paradigma pemrograman selama bertahun-tahun, ada baiknya menonton video Paman Bob Martin "The Last Programming Language" . Bagi saya wawasan besar dari pembicaraan ini adalah bahwa paradigma pemrograman ditentukan oleh fitur apa yang mereka ambil , bukan fitur apa yang mereka masukkan ......

mikera
sumber
What is the dominant style enabled by the language constructsSaya menantang Anda untuk mencoba dan menerapkannya pada Perl ... Atau poin Anda yang lain, sungguh :)
yannis
2
Perl? Tantangan bagus! Ini agak mirip bahasa majelis dalam arti bahwa Anda dapat meretas hampir semua paradigma yang Anda inginkan bersama, tetapi dalam penggunaan umum yang telah saya lihat (scripting) itu digunakan sebagian besar sebagai bahasa imperatif / prosedural.
mikera
Ya, oop juga cukup umum. Tentu saja dengan cara perly. Dan, fungsional juga , meski jarang. perl hanya perl, tidak masuk akal dalam mencoba masuk akal :)
yannis
JavaScript sedikit lebih fungsional daripada Java karena setidaknya memiliki fungsi penutupan dan kelas satu. Tapi kan, JavaScript sama fungsinya dengan C #.
Raynos
2

Javascript adalah prototypal pertama, dengan kemampuan fungsional - yang diberikan oleh penggunaan fungsi sebagai objek kelas satu.

Ini berarti bahwa Anda dapat menggunakan fungsi sebagai data, yang memiliki efek aneh mengurangi kebutuhan variabel yang mempertahankan status. Jika Anda menemukan diri Anda meraih pernyataan var, atau menggunakan satu atau lebih pernyataan "jika", maka Anda menyimpang dari gaya fungsional.

Keistimewaan lain yang menonjol dari gaya fungsional adalah bahwa fungsi HANYA seharusnya mengembalikan hasil evaluasi mereka dan tidak memiliki efek samping pada keadaan di luar ruang lingkup mereka:

// oops, this is producing a side effect
function sideEffecter(){//theres no input...        
    window.thingy = 'foo';
    // hey, this isn't returning anything!!!
} 

Bahasa fungsional bersifat non-destruktif - artinya mereka tidak mengubah input, tetapi mengembalikan data yang sepenuhnya baru berdasarkan input. Lihat utas ini: https://stackoverflow.com/questions/749084/jquery-map-vs-each

Bahasa fungsional juga menampilkan banyak metode yang sama - dengan nama-nama seperti "peta", "lipat", "kurangi" yang memproses daftar / koleksi. Dalam JS, tidak seperti bahasa lain, kita harus mengangkat ini menjadi ada - lihat perpustakaan seperti underscore.js untuk beberapa contoh, meskipun implementasi terbaru JS memiliki beberapa di antaranya.

Yang penting untuk diingat (IMO) adalah bahwa sementara JS dapat memanfaatkan beberapa pola fungsional, itu tidak selalu dilengkapi dengan baik untuk melaksanakannya.

Ambil iterasi di atas array, misalnya. Anda dapat melakukan ini menggunakan gaya fungsional atau konstruksi loop asli - dan secara umum loop lebih performan. Ambil contoh ini - pukul dengan loop dengan ukuran yang semakin besar dan catat waktu eksekusi di browser yang berbeda (saya sudah melakukan ini, tapi saya kehilangan tolok ukur - maaf!):

var test = ['foo', 'bar', 'baz'], removeFunc, removeLoop;

//(semi)functional style...
// to be really functional each condition in the ternary would be another function
removeFunc = function(src, trg) {
    return src.length === 0 ? 
        src : 
            src[0] === trg ? 
                src.slice(1) : 
                    [src[0]].concat(removeFunc(src.slice(1), trg));
};

//but this is faster
removeLoop = function(src, trg){
    var len = src.length, // using variables to represent state...
        i=0, 
        result = [];        
    while(i < n){
       if(src[i] !== trg){
          result.push(src[i]);
       }
       i = i+1;
    }
}

Selain itu, jika Anda menggunakan konstruksi fungsional untuk menekan loop dengan ukuran yang cukup besar dan tidak menggunakan beberapa bentuk manajemen tumpukan ad-hoc, Anda dapat membanjiri tumpukan (meskipun, agar adil, Anda memerlukan daftar BESAR untuk ini terjadi. ..) Anda juga harus memasukkan campuran optimisasi varian di setiap browser - meskipun jika Anda bekerja di lingkungan Node.js ini jelas lebih merupakan target tetap.

Itu bukan untuk mengatakan Anda tidak boleh menggunakan konstruksi fungsional dalam Javascript - hanya menyadari keterbatasan dalam penerapannya relatif terhadap lingkungannya.

Berikut ini beberapa tautan yang mungkin menarik bagi Anda:

Bab yang bagus tentang Pemrograman Fungsional dalam Javascript dari "Eloquent Javascript" yang luar biasa

Si Kecil Schemer

seorang teman saya menulis perpustakaan JS berdasarkan Little Schemer

Tutorial Skema yang bagus yang dapat membantu Anda lebih memahami FP

sunwukung
sumber