Adakah yang tahu perlambatan asimptotik terburuk yang mungkin terjadi saat pemrograman murni secara fungsional sebagai lawan imperatif (yaitu memungkinkan efek samping)?
Klarifikasi dari komentar oleh itowlson : adakah masalah yang algoritma non-destruktif yang paling terkenal secara asimptot lebih buruk daripada algoritma destruktif yang paling dikenal, dan jika demikian seberapa banyak?
Jawaban:
Menurut Pippenger [1996] , ketika membandingkan sistem Lisp yang murni fungsional (dan memiliki semantik evaluasi yang ketat, tidak malas) dengan yang dapat bermutasi data, suatu algoritma yang ditulis untuk Lisp yang tidak murni yang berjalan di O ( n ) dapat diterjemahkan untuk sebuah algoritma dalam Lisp murni yang berjalan dalam waktu O ( n log n ) (berdasarkan kerja oleh Ben-Amram dan Galil [1992] tentang simulasi memori akses acak menggunakan hanya pointer). Pippenger juga menetapkan bahwa ada algoritma yang merupakan yang terbaik yang dapat Anda lakukan; ada masalah yang O ( n ) dalam sistem tidak murni yang Ω ( n log n ) dalam sistem murni.
Ada beberapa peringatan tentang makalah ini. Yang paling penting adalah tidak membahas bahasa fungsional yang malas, seperti Haskell. Bird, Jones dan De Moor [1997] menunjukkan bahwa masalah yang dibangun oleh Pippenger dapat diselesaikan dalam bahasa fungsional yang malas dalam waktu O ( n ), tetapi mereka tidak membangun (dan sejauh yang saya tahu, tidak ada yang memiliki) apakah atau bukan bahasa fungsional yang malas dapat menyelesaikan semua masalah dalam waktu berjalan asimptotik yang sama dengan bahasa dengan mutasi.
Masalah yang dibangun oleh Pippenger membutuhkan Ω ( n log n ) secara khusus dibangun untuk mencapai hasil ini, dan tidak selalu mewakili masalah praktis, masalah dunia nyata. Ada beberapa batasan pada masalah yang sedikit tidak terduga, tetapi diperlukan agar bukti tersebut bekerja; khususnya, masalahnya mensyaratkan bahwa hasil dihitung secara on-line, tanpa dapat mengakses input di masa depan, dan bahwa input terdiri dari urutan atom dari sekumpulan atom yang mungkin tidak terikat, dan bukannya kumpulan ukuran tetap. Dan kertas hanya menetapkan (batas bawah) hasil untuk algoritma waktu berjalan linier yang tidak murni; untuk masalah yang membutuhkan waktu berjalan lebih besar, ada kemungkinan bahwa O ekstra (log n) faktor yang terlihat pada masalah linier mungkin dapat "diserap" dalam proses operasi tambahan yang diperlukan untuk algoritma dengan waktu operasi yang lebih besar. Klarifikasi dan pertanyaan terbuka ini dieksplorasi secara singkat oleh Ben-Amram [1996] .
Dalam praktiknya, banyak algoritma dapat diimplementasikan dalam bahasa fungsional murni dengan efisiensi yang sama seperti dalam bahasa dengan struktur data yang bisa berubah. Untuk referensi yang baik tentang teknik yang digunakan untuk menerapkan struktur data murni fungsional secara efisien, lihat "Struktur Data Murni Fungsional" dari Chris Okasaki [Okasaki 1998] (yang merupakan versi perluasan dari tesisnya [Okasaki 1996] ).
Siapa pun yang perlu menerapkan algoritma pada struktur data yang berfungsi murni harus membaca Okasaki. Anda selalu bisa mendapatkan paling buruk pelambatan O (log n ) per operasi dengan mensimulasikan memori yang bisa berubah dengan pohon biner seimbang, tetapi dalam banyak kasus Anda bisa melakukan jauh lebih baik dari itu, dan Okasaki menjelaskan banyak teknik yang berguna, dari teknik diamortisasi ke real waktu yang melakukan pekerjaan diamortisasi secara bertahap. Struktur data yang murni fungsional bisa agak sulit untuk dikerjakan dan dianalisis, tetapi mereka memberikan banyak manfaat seperti transparansi referensial yang membantu dalam optimasi kompiler, dalam komputasi paralel dan terdistribusi, dan dalam implementasi fitur seperti versi, undo, dan rollback.
Perhatikan juga bahwa semua ini hanya membahas waktu berjalan asimptotik. Banyak teknik untuk menerapkan struktur data yang berfungsi murni memberi Anda sejumlah faktor perlambatan konstan, karena pembukuan tambahan yang diperlukan agar berfungsi, dan detail implementasi bahasa yang bersangkutan. Manfaat dari struktur data yang murni fungsional mungkin lebih penting daripada perlambatan faktor konstan ini, jadi Anda biasanya perlu melakukan trade-off berdasarkan masalah yang dipermasalahkan.
Referensi
sumber
Memang ada beberapa algoritma dan struktur data yang tidak ada solusi murni fungsional asimptotik efisien (ti satu diterapkan dalam kalkulus lambda murni) diketahui, bahkan dengan kemalasan.
Namun, kami berasumsi bahwa dalam bahasa "imperatif" akses ke memori adalah O (1) sedangkan dalam teori yang tidak dapat begitu asimptotik (yaitu untuk ukuran masalah yang tidak terbatas) dan akses ke memori dalam set data besar selalu O (log n) , yang dapat ditiru dalam bahasa fungsional.
Juga, kita harus ingat bahwa sebenarnya semua bahasa fungsional modern menyediakan data yang dapat berubah, dan Haskell bahkan menyediakannya tanpa mengorbankan kemurnian (monad ST).
sumber
Artikel ini mengklaim bahwa implementasi yang murni fungsional dari algoritma union-find semuanya memiliki kompleksitas asimptotik yang lebih buruk daripada yang mereka terbitkan, yang memiliki antarmuka murni fungsional tetapi menggunakan data yang dapat diubah secara internal.
Fakta bahwa jawaban lain mengklaim bahwa tidak akan pernah ada perbedaan dan bahwa misalnya, satu-satunya "kelemahan" dari kode fungsional murni adalah dapat diparalelkan memberi Anda gambaran tentang informasi / objektivitas dari komunitas pemrograman fungsional mengenai masalah ini. .
EDIT:
Komentar di bawah menunjukkan bahwa diskusi yang bias tentang pro dan kontra pemrograman fungsional murni mungkin tidak datang dari "komunitas pemrograman fungsional". Poin yang bagus. Mungkin para advokat yang saya lihat hanya, mengutip komentar, "buta huruf".
Sebagai contoh, saya berpikir bahwa posting blog ini ditulis oleh seseorang yang bisa dikatakan mewakili komunitas pemrograman fungsional, dan karena ini adalah daftar "poin untuk evaluasi malas", itu akan menjadi tempat yang baik untuk menyebutkan segala kekurangan yang mungkin pemrograman malas dan murni fungsional. Tempat yang baik akan menggantikan pemecatan berikut (benar secara teknis, tetapi bias sampai tidak lucu):
sumber
Dengan batas atas yang tetap pada penggunaan memori, seharusnya tidak ada perbedaan.
Sketsa bukti: Diberi batasan tetap pada penggunaan memori, seseorang harus dapat menulis mesin virtual yang mengeksekusi set instruksi imperatif dengan kompleksitas asimptotik yang sama seolah-olah Anda benar-benar mengeksekusi pada mesin itu. Ini karena Anda dapat mengelola memori yang dapat berubah sebagai struktur data yang persisten, membuat O (log (n)) membaca dan menulis, tetapi dengan batas atas yang tetap pada penggunaan memori, Anda dapat memiliki jumlah memori yang tetap, menyebabkan ini untuk pembusukan ke O (1). Dengan demikian implementasi fungsional dapat menjadi versi imperatif yang berjalan dalam implementasi fungsional VM, dan karenanya keduanya harus memiliki kompleksitas asimptotik yang sama.
sumber
Saya sarankan membaca tentang kinerja Haskell , dan kemudian melihat benchmark kinerja permainan untuk bahasa fungsional vs yang prosedural / OO.
sumber