Halo, Habr!
Hari ini kita akan mulai berbicara tentang topik yang sangat penting - pemrograman fungsional. Pentingnya FP dalam pengembangan web modern sulit ditaksir terlalu tinggi. Arsitektur dari setiap proyek modern besar termasuk fungsi perpustakaan yang ditentukan pengguna, dan akan ada pertanyaan wajib pada subjek wawancara di tingkat manapun.
Pengantar Pemrograman Fungsional
Pemrograman fungsional (FP) adalah cara mengatur kode dengan menulis serangkaian fungsi.
EcmaScript, menjadi bahasa pemrograman multi-paradigma, mengimplementasikan, antara lain, paradigma fungsional. Ini berarti bahwa fungsi dalam ES adalah data dan dapat dikirimkan ke fungsi, dikembalikan dari fungsi, dan dapat menerima fungsi itu sendiri. Yaitu fungsi dalam ES adalah
fungsi kelas satu .
Definisi berikut mengikuti dari ini:
Argumen fungsional (funarg) - argumen yang nilainya berfungsi.
Fungsi orde tinggi (FWP, orde-orde tinggi, hof) adalah fungsi yang menerima fungsi sebagai argumen.
Fungsi dengan nilai fungsional (Function bernilai fungsi) - fungsi yang mengembalikan fungsi.
Semua jenis fungsi ini dikondisikan secara kondisional ke dalam fungsi-fungsi kelas satu, dan, sebagai berikut dari definisi di atas, dalam ES semua fungsi adalah objek-objek dari kelas pertama.
Fungsi murni - ideal pemrograman fungsional
Fungsi murni (PF) - selalu mengembalikan hasil yang diprediksi.
Properti PF:
- Hasil eksekusi PF hanya bergantung pada argumen yang diberikan dan algoritma yang mengimplementasikan PF
- Jangan gunakan nilai global
- Jangan memodifikasi nilai luar atau argumen yang diteruskan
- Jangan menulis data ke file, database, atau di tempat lain
Contoh fungsi murni:
const add = (x,y) => x+y;
Contoh pengotor fungsi yang bagus adalah:
var first; var second; function testFn() { var a = 10; first = function() { return ++a; } second = function() { return --a; } a = 2; first();
Bayangkan betapa rumitnya menulis tes untuk contoh ini dan seberapa sederhana untuk fungsi murni!
Fungsi-fungsi yang tidak murni dicirikan oleh keadaan eksternal yang bervariasi waktu yang menyulitkan pemeliharaan, pemahaman, dan pengujian kode.
Sebaliknya, fungsi murni selalu dapat dibaca, diuji, menyederhanakan paralelisasi perhitungan, dan mudah digunakan kembali.
Saya pikir Anda memperhatikan bahwa dalam contoh-contoh pada fungsi murni, saya beralih ke sintaks ES6. Ini dilakukan dengan sengaja. Sintaks fungsi ini disebut "fungsi panah", tetapi sebenarnya ini merupakan implementasi dari abstraksi matematis, diciptakan sejak lama. Tentang itu lebih jauh.
Lambda - fungsi
Inilah yang bentuk tulisan panah ini disebut dalam matematika dan beberapa bahasa pemrograman lainnya. Pemrograman fungsional sangat erat kaitannya dengan mat. analisis, jadi jangan kaget.
Istilah kalkulus Lambda diperkenalkan kembali pada tahun 1930-an oleh Gereja Alonzo. Pada dasarnya, kalkulus lambda tidak lebih dari bentuk formal menggambarkan persamaan matematika. Lebih detail di
sini .
Dalam ES, fungsi lambda sangat sering mengimplementasikan penutupan:
const add = x => y => x + y;
Singkat dan ringkas. Fungsi add adalah lambda yang mengambil argumen x, menyimpannya dalam penutup, dan mengembalikan fungsi.
Bandingkan dengan kode ini:
funtion add(x) { return function (y) { return x + y; } }
Jelas, opsi pertama terlihat lebih baik.
Kekebalan
Immutable (immutable, immunity) adalah objek yang kondisinya tidak dapat diubah setelah penciptaan. Hasil modifikasi objek semacam itu akan selalu menjadi objek baru, sedangkan objek lama tidak akan berubah.
Kekekalan adalah cawan emas pemrograman fungsional.
Pertimbangkan sebuah contoh:
const impureAddProp = (key, value, object) => { object[key] = value;
Seperti yang Anda lihat, dalam contoh ini, kami memutasikan objek Pengguna dengan menambahkan properti ke sana. Sekarang objek Pengguna adalah semacam "keadaan bersama" untuk fungsi impureAddProp dan fungsi lain yang akan memutasinya. Pendekatan ini lebih sulit untuk diuji karena Saat mengubah fungsi apa pun yang berinteraksi dengan status bersama, orang harus selalu mengingat kemungkinan kesalahan dalam fungsi lainnya.
Dari sudut pandang pemrograman fungsional, itu akan benar:
const pureAddProp = (key, value, object) => ({ ...object, [key]: value }); const User= { name: 'Alex' }; const Admin= pureAddProp ('isAdmin', true, User);
Jadi objek Pengguna akan tetap tidak berubah. Kami memodifikasi salinan data, yang selalu aman.
Kesimpulan
Hari ini kita telah memeriksa beberapa konsep teoritis penting. Kami berkenalan dengan fungsi-fungsi murni, bentuk lambda dari fungsi perekaman dan konsep immutability dalam fp. Namun, artikel ini adalah semacam pengantar. Gagasan utama, teknik, dan โbagian sulitโ dari pemrograman fungsional akan ada dalam artikel berikut.
Pemrograman fungsional diimplementasikan oleh banyak perpustakaan. Ini rambda, dan lodash, dan banyak lainnya. Dalam proyek nyata, Anda, tentu saja, akan menggunakannya. Di bawah kap perpustakaan mana pun, masih akan ada javascript asli yang sama, jadi dalam artikel berikut ini kami akan menganalisis FP, menerapkan semua konsepnya pada JS asli.
Catatan tambahan
Mulai menulis artikel, saya memikirkan rencana berikut:
- menulis terjemahan artikel berbahasa Inggris yang menarik
- untuk menyoroti beberapa area yang relevan di JS (konsep utama, OOP dalam hal spesifikasi, pola, pemrograman fungsional EcmaScript).
Hingga saat ini, artikel utama di tiga bidang telah ditulis:
- ini dan ScopeChain dalam EcmaScript - di sini saya menjelaskan konsep-konsep kunci seperti spesifikasi sebagai konteks eksekusi, kata kunci ini, dan properti konteks ScopeChain (lingkup rantai). Dalam kerangka arah ini, artikel saya tentang lingkungan Lexical dan Penutupan diterbitkan secara harfiah hari ini.
- Pandangan dari EcmaScript pada teori umum OOP - perbedaan antara pengetikan kelas statis dan organisasi prototipe dinamis dijelaskan di sini, model pendelegasian dan pengetikan bebek dibongkar
- Pola elegan dalam JavaScript modern (seri kompilasi Bill Sourour pada siklus) - berikut adalah dua pola yang dapat berguna dalam beberapa situasi. Pendekatan saya dalam hal pola cukup sederhana: lebih baik untuk mengetahui sebanyak mungkin pola, karena cepat atau lambat berguna
Dan sekarang giliran pemrograman fungsional. Di masa depan, saya akan menulis artikel sebagai kelanjutan dari masing-masing bidang ini. Sebagai contoh, artikel berikut akan membahas konsep-konsep kunci OOP: enkapsulasi, abstraksi, pengotor (dan goresan), antarmuka, dll. Saya juga berencana untuk berbicara tentang bagaimana OOP dalam ES diterapkan di bawah tenda, mis. tentang sifat-sifat [[Prototipe]], [[Kelas]] dan banyak lagi. Bicara tentang bagaimana v8 membuat entitas dan instance kelas, fungsi.
Banyak pertanyaan muncul di komentar, jadi saya ingin menjelaskan tujuan yang saya tetapkan untuk artikel saya. Saya tidak menulis tutorial atau meninjau dokumentasi. Menurut pendapat saya, ini tidak masuk akal. Saya tidak menyarankan Anda dengan instrumen atau pola tertentu, pilihan mereka sepenuhnya terserah Anda.
Dalam artikel-artikel itu, saya akan meninjau konsep-konsepnya, memberi tahu bagaimana konsep-konsep itu disusun di bawah tenda (menurut saya, ini meningkatkan pemahaman tentang apa yang kita tulis dan mengapa kita menulis dengan cara ini), atau saya berbicara tentang beberapa hal yang memperluas wawasan saya. Menurut saya ini sangat penting. Lihatlah perusahaan seperti Yandex atau Edadil, mereka terus-menerus berbicara tentang semacam ide orisinal. Entah ini bitmap dalam reaksi, maka aplikasi vue hampir sepenuhnya pada kelas es6. Kebanyakan pengembang web tidak akan pernah memikirkan hal seperti itu. Ini membutuhkan pandangan yang luas.
Saya sendiri mempelajari dan mempelajari web dengan cara ini, yaitu setelah membaca tutorial atau dok, saya mencoba memahami cara alat yang dijelaskan ini bekerja di bawah tenda, untuk memahami mekanisme internalnya.
Sampai artikel selanjutnya, teman-teman!