Jenis pertanyaan pemula pemrograman fungsional di sini:
Saya telah membaca transkrip beberapa pembicaraan Rich Hickey, dan dalam beberapa ceramahnya yang lebih terkenal, dia merekomendasikan penggunaan antrian sebagai alternatif agar fungsi-fungsi saling memanggil satu sama lain. (Misalnya dalam Desain, Komposisi dan Kinerja dan dalam Simple Made Easy .)
Saya tidak begitu mengerti hal ini, dalam beberapa hal:
Apakah dia berbicara tentang memasukkan data dalam antrian dan kemudian meminta setiap fungsi menggunakannya? Jadi alih-alih fungsi A memanggil fungsi B untuk melakukan komputasi sendiri, kita hanya memiliki fungsi B menampar outputnya pada antrian dan kemudian memiliki fungsi A ambil itu? Atau, sebagai alternatif, apakah kita berbicara tentang menempatkan fungsi pada antrian dan kemudian secara berturut-turut menerapkannya pada data (tentu saja tidak, karena itu akan melibatkan mutasi masif, bukan? Dan juga multiplikasi antrian untuk fungsi multi-arity, atau seperti pohon atau sesuatu? )
Bagaimana hal itu membuat segalanya lebih sederhana? Intuisi saya adalah bahwa strategi ini akan menciptakan lebih banyak kompleksitas, karena antrian akan menjadi semacam keadaan, dan kemudian Anda harus khawatir "bagaimana jika beberapa fungsi lain menyelinap masuk dan memasukkan beberapa data di atas antrian?"
Satu jawaban untuk pertanyaan implementasi pada SO menunjukkan bahwa idenya adalah menciptakan sekelompok antrian yang berbeda. Jadi setiap fungsi menempatkan output dalam antrian sendiri (??). Tapi itu juga membingungkan saya, karena jika Anda menjalankan fungsi sekali, maka mengapa perlu antrian untuk outputnya ketika Anda bisa mengambil output itu dan menampar nama itu sebagai (var, atom, entri dalam besar tabel hash, apa pun). Sebaliknya, jika suatu fungsi berjalan beberapa kali, dan Anda menempelkan outputnya ke antrian, maka Anda telah membuat status pada diri Anda lagi, dan Anda harus khawatir tentang urutan semua hal yang dipanggil, fungsi hilir menjadi kurang murni, dll.
Jelas saya tidak mengerti maksudnya di sini. Bisakah seseorang menjelaskan sedikit?
sumber
Job
objek umum , mendorongnya ke dalam antrian, dan membuat satu atau lebih utas pekerja bekerja pada antrian itu. TheJob
kemudian mengirimkan lebihJob
s ke dalam antrian setelah selesai. Nilai pengembalian digantikan oleh panggilan balik dalam konsep itu. Ini mimpi buruk untuk debug dan verifikasi karena Anda tidak memiliki tumpukan panggilan, dan efisien dan fleksibel untuk alasan yang sama.Jawaban:
Ini lebih merupakan latihan desain daripada rekomendasi umum. Anda biasanya tidak akan membuat antrian di antara semua panggilan fungsi langsung Anda. Itu akan konyol. Namun, jika Anda tidak mendesain fungsi Anda seolah-olah antrian mungkin dimasukkan di antara salah satu panggilan fungsi langsung, Anda tidak dapat secara adil mengklaim bahwa Anda telah menulis kode yang dapat digunakan kembali dan dapat dibuat. Itulah intinya yang dibuat oleh Rich Hickey.
Ini adalah alasan utama di balik kesuksesan Apache Spark , misalnya. Anda menulis kode yang sepertinya membuat panggilan fungsi langsung pada koleksi lokal, dan kerangka kerja menerjemahkan kode itu ke meneruskan pesan pada antrian antara node cluster. Jenis gaya pengkodean yang sederhana, dapat disusun, dapat digunakan kembali, dan pendukung Rich Hickey memungkinkan hal itu.
sumber
Satu hal yang perlu diperhatikan adalah pemrograman fungsional memungkinkan Anda untuk menghubungkan fungsi satu sama lain secara tidak langsung melalui objek mediator yang menangani pengadaan argumen untuk dimasukkan ke dalam fungsi dan secara fleksibel mengarahkan hasilnya ke penerima yang menginginkan hasil mereka. Jadi misalkan Anda memiliki beberapa kode panggilan langsung langsung yang terlihat seperti contoh ini, di Haskell:
Nah, menggunakan
Applicative
kelas Haskell<$>
dan<*>
operatornya dan kita dapat secara otomatis menulis ulang kode itu menjadi ini:... di mana sekarang
myThing
tidak lagi secara langsung meneleponf
dang
, melainkan menghubungkan mereka melalui beberapa mediator tipef
. Jadi misalnya,f
bisa berupa beberapaStream
jenis yang disediakan oleh perpustakaan yang menyediakan antarmuka ke sistem antrian, dalam hal ini kita akan memiliki jenis ini:Sistem seperti ini memang ada. Bahkan, Anda dapat melihat aliran Java 8 sebagai versi dari paradigma ini. Anda mendapatkan kode seperti ini:
Di sini Anda menggunakan fungsi-fungsi berikut:
t -> t.getType() == Transaction.GROCERY
comparing(Transaction::getValue).reversed()
Transaction::getId
toList()
... dan bukannya meminta mereka saling menelepon secara langsung, Anda menggunakan
Stream
sistem untuk menengahi di antara mereka. Contoh kode ini tidak memanggilTransaction::getId
fungsi secara langsung —Stream
memanggilnya dengan transaksi yang selamat dari yang sebelumnyafilter
. Anda dapat menganggapStream
antrian sebagai jenis minimal yang berfungsi pasangan secara tidak langsung dan merutekan nilai di antara mereka.sumber