Saya telah belajar bagaimana memprogram terutama dari sudut pandang OOP (seperti kebanyakan dari kita, saya yakin), tetapi saya telah menghabiskan banyak waktu untuk belajar bagaimana menyelesaikan masalah dengan cara fungsional. Saya memiliki pemahaman yang baik tentang bagaimana menyelesaikan masalah perhitungan dengan FP, tetapi ketika datang ke masalah yang lebih rumit saya selalu menemukan diri saya kembali ke membutuhkan benda yang bisa berubah. Sebagai contoh, jika saya menulis simulator partikel, saya ingin partikel "objek" dengan posisi yang dapat diperbarui untuk diperbarui. Bagaimana secara inheren masalah "stateful" biasanya diselesaikan dengan menggunakan teknik pemrograman fungsional?
functional-programming
Andrew Martin
sumber
sumber
Jawaban:
Program fungsional menangani keadaan dengan sangat baik, tetapi membutuhkan cara pandang yang berbeda. Sebagai contoh posisi Anda, satu hal yang perlu dipertimbangkan adalah menjadikan posisi Anda sebagai fungsi waktu alih-alih nilai tetap . Ini berfungsi baik untuk partikel mengikuti jalur matematika tetap, tetapi Anda memerlukan strategi berbeda untuk menangani perubahan di jalur, seperti setelah tabrakan.
Strategi dasar di sini adalah Anda membuat fungsi yang mengambil dalam keadaan dan mengembalikan negara baru . Jadi simulator partikel akan menjadi fungsi yang mengambil
Set
partikel sebagai input dan mengembalikanSet
partikel baru setelah langkah waktu. Kemudian Anda hanya berulang kali memanggil fungsi itu dengan inputnya disetel ke hasil sebelumnya.sumber
Seperti dicatat oleh @KarlBielefeldt, pendekatan fungsional untuk masalah seperti itu adalah melihatnya mengembalikan negara baru dari keadaan sebelumnya. Fungsi itu sendiri tidak menyimpan informasi apa pun, sehingga mereka akan selalu memperbarui status m ke status n .
Saya pikir Anda menemukan ini tidak efisien karena Anda menganggap keadaan sebelumnya harus disimpan dalam memori saat menghitung keadaan baru. Perhatikan bahwa pilihan antara menulis keadaan yang sama sekali baru atau menulis ulang yang lama di tempat adalah detail implementasi dari sudut pandang bahasa fungsional.
Misalnya, saya memiliki daftar sejuta bilangan bulat, dan ingin menambah kesepuluh dengan satu unit. Menyalin seluruh daftar dengan nomor baru di posisi kesepuluh adalah pemborosan, Anda benar; tetapi hanya cara konseptual untuk menggambarkan operasi ke kompiler bahasa atau juru bahasa. Kompiler atau juru bahasa bebas untuk mengambil daftar pertama dan hanya menimpa posisi kesepuluh.
Keuntungan dari menggambarkan operasi dengan cara ini adalah bahwa kompiler dapat mempertimbangkan situasi ketika banyak utas ingin memperbarui daftar yang sama pada posisi yang berbeda. Jika operasi digambarkan sebagai "buka posisi ini dan timpa apa yang Anda temukan", maka itu adalah programmer, bukan kompiler, yang bertugas memastikan bahwa overwrites tidak bertabrakan.
Dengan semua yang dikatakan, bahkan di Haskell ada monad negara yang membantu memodelkan situasi di mana "menjaga negara" adalah solusi yang lebih intuitif untuk masalah. Tetapi tolong perhatikan juga beberapa masalah yang Anda temukan " secara inheren stateful, seperti menulis ke database " memiliki solusi yang tidak dapat diubah seperti Datomic . Ini bisa mengejutkan sampai Anda memahaminya adalah sebuah konsep, belum tentu realisasinya.
sumber
Berlangganan model mental yang tepat membantu orang berpikir lebih baik dan mengelola keadaan. Dalam pikiran saya, model mental terbaik adalah buku flip . Setelah klik ini, Anda akan memahami bahwa FP sangat bergantung pada struktur data persisten yang menangkap keadaan dunia dan bahwa fungsi digunakan untuk mentransisikan keadaan itu tanpa mutasi apa pun.
Rich Hickey menjelaskan ide-ide ini:
Ada pembicaraan lain tetapi ini akan mengirim Anda ke arah yang benar.
sumber
Saat menulis aplikasi besar dan cukup besar, saya sering menemukan manfaat untuk membedakan antara bagian aplikasi yang stateful dan yang stateless.
Kelas / struktur data di bagian stateful menyimpan data aplikasi dan fungsi di bagian ini bekerja dengan pengetahuan implisit dari data aplikasi.
Kelas / struktur data / fungsi di bagian stateless ada untuk mendukung aspek algoritmik murni aplikasi. Mereka tidak memiliki pengetahuan implisit tentang data aplikasi. Mereka bekerja secara murni fungsional. Bagian stateful dari aplikasi dapat mengalami perubahan status sebagai efek samping dari menjalankan fungsi di bagian stateless dari aplikasi.
Bagian tersulit adalah mencari tahu kelas / fungsi mana yang diletakkan di bagian stateless dan kelas / fungsi mana yang diletakkan di bagian stateful, dan memiliki disiplin untuk meletakkannya di file / pustaka yang terpisah.
sumber