Fungsional Pemrograman Tidak Kerja (dan apa yang harus dilakukan tentang hal itu)

Baca tiba-tiba dan dalam isolasi, ini mungkin mudah untuk salah menafsirkan, jadi saya sarankan pertama membaca beberapa artikel terakhir yang telah menyebabkan hal ini:

Setelah menghabiskan waktu yang lama di dunia pemrograman fungsional, dan menggunakan Erlang sebagai pergi-untuk bahasa untuk masalah rumit, saya akhirnya menyimpulkan bahwa pemrograman fungsional murni tidak layak. Ini bukan kegagalan karena masalah lunak seperti pemasaran, tetapi karena semakin jauh Anda pergi ke jalan murni fungsional overhead lebih mental yang terlibat dalam menulis program yang kompleks. Kedengarannya seperti deskripsi pemrograman secara umum - masalah mendapatkan jauh lebih sulit untuk memecahkan karena mereka meningkatkan dalam lingkup - tapi itu tingkat yang lebih rendah banyak dan spesifik dari itu.kicker adalah bahwa apa yang sering teka-teki yang luar biasa dalam Erlang (atau Haskell) berubah menjadi kode langsung di Python atau Perl atau bahkan C.

Bayangkan Anda telah menerapkan sebuah program besar dalam cara fungsional murni. Semua data dengan benar ulir dalam dan keluar dari fungsi, dan tidak ada update yang benar-benar merusak untuk berbicara tentang. Sekarang memilih dua fungsi tingkat terendah dan paling terisolasi di seluruh basis kode. Mereka digunakan di semua tempat, tetapi tidak pernah disebut dari modul yang sama. Sekarang membuat ini tergantung satu sama lain: fungsi A berperilaku berbeda tergantung pada jumlah kali fungsi B telah disebut dan sebaliknya.

Dalam C, ini mudah! Hal ini dapat dilakukan dengan cepat dan rapi dengan menambahkan beberapa variabel global. Dalam kode murni fungsional, ini adalah suatu tempat antara rearchitecting utama dari aliran data dan putus asa.

Contoh kedua: Ini adalah teknik kompilasi umum untuk C dan bahasa penting lainnya untuk mengkonversi program untuk bentuk tunggal-tugas. Artinya, di mana variabel diinisialisasi dan tidak pernah berubah.Sangat mudah untuk mekanis mengkonversi serangkaian pembaruan yang merusak ke dalam apa dasarnya kode murni. Berikut adalah pernyataan sederhana:

if (a > 0) {
   a++;
}

Dalam single-tugas membentuk variabel baru diperkenalkan untuk menghindari memodifikasi variabel yang ada, dan hasilnya agak Erlangy:

if (a > 0) {
   a1 = a + 1;
} else {
   a1 = a;
}

Yang terakhir adalah bersih bahwa Anda tahu variabel tidak akan berubah. Mereka tidak variabel sama sekali, namun nama-nama untuk nilai-nilai. Tapi menulis yang terakhir langsung dapat canggung.Tergantung di mana Anda berada dalam kode, nilai sekarang dari apa pun "a" mewakili memiliki nama yang berbeda. Memasukkan pernyataan di tengah membutuhkan menciptakan nama baru untuk hal-hal, dan Anda perlu untuk memastikan Anda referensi versi yang tepat. (Ada lebih banyak ruang untuk kesalahan sekarang: Anda tidak hanya mengatakan "a", tetapi nama nilai yang Anda inginkan dalam rantai saat perhitungan.)

Dalam kedua contoh ini kode penting sebenarnya adalah optimalisasi kode fungsional. Anda bisa melewati keadaan global dalam dan keluar dari setiap fungsi dalam program Anda, tapi mengapa tidak membuat implisit? Anda bisa pergi melalui rasa sakit mencoba untuk menulis dalam bentuk tunggal-tugas langsung, tapi karena ada terjemahan mekanik dari satu ke yang lain, mengapa tidak menggunakan bentuk yang lebih mudah untuk menulis di?

Pada titik ini saya harus membuat jelas: pemrograman fungsional berguna dan penting. Ingat, itu dikembangkan sebagai cara untuk membuat kode lebih mudah untuk alasan tentang dan untuk menghindari "update spaghetti memori." Garis antara "penting" dan "fungsional" kabur. Jika program Haskell berisi bahasa domain BASIC-seperti tertentu yang juga ditulis dalam Haskell, adalah program secara keseluruhan fungsional atau keharusan? Apakah itu penting?

Bagi saya, apa yang telah bekerja keluar adalah pergi ke jalan murni fungsional sebanyak mungkin, tapi jatuh kembali pada teknik penting ketika terlalu banyak tekanan kode telah dibangun. Beberapa kasus ini terkenal dan diterima, seperti nomor generasi acak (di mana benih tersebut dimodifikasi belakang layar), dan sebagian besar jenis I / O (di mana posisi dalam file dikelola untuk Anda).

Belajar bagaimana menemukan katup pelepas tekanan yang sama dalam kode Anda sendiri membutuhkan latihan.

Salah satu dari sedikit saran saya dapat menawarkan adalah bahwa terjadi untuk solusi yang jelas bergerak struktur data inti dari fungsional ke kode penting mungkin bukan pendekatan yang terbaik.Pada contoh Pac-Man dari Murni Fungsional Retrogames , itu benar-benar bisa dilakukan untuk menulis bahwa permainan tua dalam gaya murni fungsional. Dependensi dapat bekerja; aliran data tidak benar-benar buruk. Ini mungkin masih menjadi usaha berantakan, dengan banyak potongan-potongan kecil data untuk melacak, dan selektif bagian yang bergerak keluar dari dunia murni fungsional akan menghasilkan kode yang lebih mudah dikelola. Sekarang target yang jelas adalah salah negara Pac-Man sendiri atau hantu, tetapi mereka adalah bagian dari aliran data inti dari program ini. Membuat mereka secara global dapat diakses dan dimodifikasi dan tiba-tiba sebagian besar dari kode telah bergeser dari fungsional ke imperatif ... dan itu bukan tujuan.

Pendekatan yang lebih baik adalah untuk mencari kecil, stateful, bit data yang bisa digunakan dalam berbagai tempat, tidak hanya di jalur aliran data utama. Sebuah calon yang baik dalam contoh ini adalah waktu permainan saat ini (alias jumlah frame berlalu). Ada preseden jelas bahwa fungsi waktu / tanggal, seperti Erlang now(), menutupi sedikit negara, dan itulah yang membuat mereka berguna.Kemungkinan lain adalah skor. Ini adalah nilai yang sederhana yang akan diperbarui dalam berbagai situasi. Menjadikannya counter global sejati menghilangkan seluruh lapisan threading data, dan itu sederhana: hanya memiliki fungsi untuk menambah counter skor dan fungsi lain untuk mengambil nilai saat ini. Tidak ada alasan untuk menambah kompleksitas tambahan hanya untuk menghindari memiliki variabel global tunggal, sesuatu yang C / Python / Lua / Ruby programmer bahkan tidak akan berkedip pada.