Kritik OCaml: apakah masih valid?

15

Saya seorang pemula yang lengkap dengan OCaml. Baru-baru ini saya menemukan halaman ini dengan daftar sejumlah kritik terhadap OCaml.

Melihat bahwa halaman itu sudah cukup tua (2007): manakah dari poin-poin yang tercantum yang masih benar hingga hari ini? Misalnya: apakah masih benar bahwa tidak mungkin untuk mencetak objek generik?

Saya ingin menjelaskan bahwa saya tidak mencari diskusi tentang pendapat yang diungkapkan di dalamnya. Saya bertanya apakah informasi yang tercantum, seperti fakta bahwa integer overflow tanpa peringatan, masih benar untuk versi OCaml yang lebih baru

Andrea
sumber
5
Saya memberikan suara untuk menutup pertanyaan ini sebagai di luar topik karena meta.programmers.stackexchange.com/questions/6417/…
Philipp
3
Ada garpu di mana mereka mungkin sudah diperbaiki: tryfsharp.org
Den
7
Tentu saja pendapat dalam esai yang Anda tautkan itu valid, tetapi apakah kritik ini relevan bagi Anda adalah masalah yang sama sekali berbeda. Perhatikan bahwa penulis berasal dari latar belakang Common Lisp dan karenanya memiliki nilai Lispish. Jika Anda mengambil pendekatan lain untuk OCaml daripada membandingkannya dengan Lisp (mis. "OCaml adalah Haskell hanya untuk manusia biasa" atau "Jika C adalah bahasa fungsional, Anda akan memiliki OCaml") Anda akan merasa jauh lebih memuaskan. Untuk semua kekurangannya, OCaml adalah bahasa yang hebat dan saya mendorong Anda untuk mencoba-coba di dalamnya.
amon
5
Sejauh yang saya tahu tidak ada cara untuk mendeteksi integer overflow di perangkat keras , jadi Anda harus memasukkan pemeriksaan runtime di semua tempat untuk mendeteksinya; tetapi penulis menolak menggunakan "bignum" atas dasar kinerja! Keluhan tentang jumlah pengetikan statis untuk mengatakan sabuk pengaman itu buruk karena Anda mungkin berpikir Anda tidak bisa mati dalam kecelakaan mobil. Keluhan tentang ketidakmampuan modul mengatakan dia ingin melakukan monke-hal-hal - praktik anti-modular dan rawan kesalahan. "Kebun binatang tipe kecil" tidak ada hubungannya dengan inferensi tipe. Sudah jelas letak biasnya .
Doval
2
@Doval: Tentu saja Anda dapat mendeteksi kelebihan pada perangkat keras. Namun, berurusan dengan itu adalah masalah perangkat lunak.
Mason Wheeler

Jawaban:

13

Artikel ini dibahas di beberapa tempat:

Untuk meringkas: ya, OCaml bukan Lisp, dan tidak, itu tidak sempurna (apa artinya itu?). Saya tidak berpikir poin yang disebutkan dalam posting blog relevan untuk programmer O'Caml sehari-hari.

Setelah mempelajari O'Caml, saya pikir itu adalah bahasa yang menarik yang dapat membantu Anda membangun program yang bahkan tidak berani Anda tulis, katakanlah, C / C ++ / Java: misalnya, lihat Frama-C .

Untuk deskripsi terbaru O'Caml, saya mendorong Anda untuk membaca tentang fitur-fiturnya : bahasa ini mempromosikan teknik pemeriksaan tipe statis yang kuat yang memungkinkan implementasi untuk fokus pada menghasilkan runtime yang performant, namun aman.

Penting : Saya bukan ahli OCaml: jika Anda salah satu dari mereka dan melihat saya menulis sesuatu yang sangat salah, mohon perbaiki saya. Saya akan mengedit posting ini sesuai.

Pengecekan tipe statis

  • Rasa Keamanan Palsu

    Ini benar, tetapi jelas.

    Pengetikan statis memberi Anda bukti yang dapat Anda percayai tentang subset properti program Anda. Kecuali Anda menerima semua formal, program rata-rata (non-mainan) akan dikenakan bug kesalahan pemrograman yang hanya dapat disaksikan saat runtime.

    Saat itulah teknik pemeriksaan dinamis dapat diterapkan: kompiler OCaml memiliki tanda untuk menghasilkan file yang dapat dieksekusi dengan informasi debug, dan seterusnya ... Atau, ia dapat menghasilkan kode yang secara membabi buta mempercayai programmer dan menghapus informasi jenis sebanyak mungkin. Programmer yang menginginkan program yang kuat harus mengimplementasikan pemeriksaan dinamis secara eksplisit.

    Hal yang sama berlaku untuk misalnya Common Lisp, tetapi terbalik: tipe dinamis pertama, dengan deklarasi tipe opsional dan arahan kompilator kedua.

  • Beberapa Tipe Dasar

    Masih berlaku: bahasa inti tidak berubah (atau tidak secara dramatis).

  • Overflow Integer Diam

    Ini adalah norma di sebagian besar bahasa bahwa integer overflow diperiksa dengan tangan. Saya tidak tahu ada perpustakaan yang akan mengetik-periksa operasi untuk memverifikasi apakah overflow dapat terjadi.

  • Modul Ketidakmampuan

    1. Penulis menyebutkan Functors tetapi saya gagal melihat bagaimana contohnya tidak dapat diimplementasikan. Membaca bab Modul Kelas Pertama https://realworldocaml.org , tampaknya modul dapat digunakan untuk membuat dan membangun modul baru. Tentu saja, memodifikasi modul yang ada memerlukan modifikasi kode sumber, tetapi sekali lagi, ini tidak biasa di antara bahasa pemrograman.

    2. "Secara semantik , fungsi dikompilasi INLINE"

    Utas reddit di atas tidak setuju, mengatakan bahwa pengikatan diselesaikan pada waktu tautan. Namun, ini adalah detail implementasi dan saya pikir Semantically yang ditekankan berkaitan dengan cara fungsi diselesaikan. Contoh:

     let f x y = x + y ;;
     let g a b = f b a ;;
     let f x y = x * y ;;
     exit (g 2 3) ;;
    

    Program di atas mengkompilasi, dan ketika dieksekusi, mengembalikan 5, karena gdidefinisikan dengan versi pertama f, sama seperti jika fungsi panggilan ginline panggilan ke f. Ini bukan "buruk", omong-omong, itu hanya konsisten dengan aturan bayangan nama O'Caml.

    Untuk meringkas : ya, modul tidak dapat diubah . Tetapi mereka juga komposer .

  • Polimorfisme Menyebabkan Kesalahan Tipe Run-time

    Saya tidak dapat mereproduksi kesalahan yang disebutkan. Saya menduga itu adalah kesalahan kompiler.

Tidak ada makro

Memang, tidak ada makro selain preprosesor (OcamlP4, OcamlP5, ...).

Kesuksesan Bahasa Minor

  • Rekam neraka penamaan bidang

    Benar, tetapi Anda harus menggunakan modul:

    1. Dua bidang dari dua catatan memiliki label yang sama di OCaml
    2. Mengatasi nama bidang
  • Sintaksis

    Masih berlaku (tapi sungguh, ini hanya sintaks).

  • Tidak Ada Polimorfisme

    Masih berlaku, tapi entah bagaimana ada orang yang lebih suka itu daripada menara numerik Lisp (saya tidak tahu mengapa). Saya kira ini membantu dengan jenis inferensi.

  • Set fungsi yang tidak konsisten

    Lihat proyek Termasuk Baterai OCaml . Secara khusus, BatArray , untuk contoh map2array.

  • Tidak ada variabel dinamis

    Dapat diimplementasikan:

    1. http://okmij.org/ftp/ML/dynvar.txt
    2. http://okmij.org/ftp/ML/index.html#dynvar
  • Opsional ~ menghisap argumen

    Dengan pembatasan bahasa, Anda tidak dapat mencampur argumen opsional dan kata kunci dalam Common Lisp. Apakah ini berarti itu menyebalkan? (tentu saja, ini dapat diubah dengan makro (lihat misalnya jawaban saya )). Lihat dokumentasi O'Caml untuk argumen opsional dan bernama dalam O'Caml.

  • Inkonsistensi aplikasi argumen parsial

    Saya tidak berpikir ini benar-benar menjengkelkan dalam praktek.

  • Keterbacaan Aritmatika

    Itu berlaku, tetapi Anda dapat menggunakan R atau Python untuk masalah numerik jika Anda mau.

  • Resolusi konflik nama diam

    Masih berlaku, tetapi perhatikan bahwa ini didokumentasikan dengan baik.

  • Tidak ada input / output objek

    Masih berlaku.

Implementasi, perpustakaan

Ini terus berubah setiap hari: tidak ada jawaban pasti.

Akhirnya,

"Anda harus mencoba OCaml (atau, lebih baik lagi, Haskell) bahkan jika Anda pikir itu menyebalkan dan Anda tidak berencana untuk menggunakannya. Tanpa itu, pendidikan Ilmu Komputer Anda tidak lengkap, sama seperti itu tidak lengkap tanpa beberapa Lisp dan C (atau , lebih baik lagi, Majelis) paparan. "

... masih berlaku.

coredump
sumber
Terima kasih, saya akan melihat tautannya, tetapi saya tidak benar-benar bertanya apakah pendapat itu benar. Saya bertanya apakah faktanya masih berlaku. Misalnya: apakah ada cara untuk mencetak semua tipe data aljabar? Apakah masih akurat bahwa bilangan bulat meluap tanpa peringatan? Apakah saat ini ada cara untuk beroperasi pada file dan membuangnya tanpa harus menulis setiap kali boilerplate untuk berurusan dengan menutup file pada kesalahan?
Andrea
@Andrea saya mengedit jawaban saya.
coredump
1
"... ada orang yang lebih suka itu daripada menara numerik Lisp (saya tidak tahu mengapa). Saya kira itu membantu dengan inferensi tipe." Bingo. Sistem tipe SML dan OCaml mengharuskan setiap ekspresi hanya memiliki satu jenis. Overloading operator matematika SML adalah pengecualian yang ada dalam bahasa tersebut. Ini juga berlaku untuk Haskell; memungkinkan overloading semacam itu adalah motivasi di balik kelas tipe. Tangkapannya adalah Anda hanya dapat memiliki satu instance kelas tipe per tipe. Anda juga tidak dapat mengubah bilangan bulat menjadi pelampung dengan ukuran yang sama - pelampung 64-bit hanya memiliki ketelitian 54 bit.
Doval
@Doval Bagaimana dengan sesuatu seperti Mengetik menara numerik untuk Racket? Bisakah kita bayangkan perpustakaan OCaml yang akan mengeksploitasi kelas tipe atau Generalized Algebraic Data Type (GADT) untuk menyediakan operator matematika polimorfik? Mengenai konversi: tidak semua operasi dimungkinkan, tetapi ada beberapa yang dapat diketik.
coredump
2
@Doval: "Re: operator matematika polimorfik, saya tidak berpikir ada cara tanpa menerapkan kelas tipe Haskell". F # memiliki operator matematika polimorfik tanpa kelas tipe.
Jon Harrop
7

Melihat bahwa halaman itu sudah cukup tua (2007): manakah dari poin-poin yang tercantum yang masih benar hingga hari ini?

  • Rasa Keamanan Palsu . Ini tidak masuk akal.

  • Beberapa Tipe Dasar . OCaml sekarang memiliki byte dan byte array tetapi tidak ada string unicode bawaan, integer 16-bit, integer unsigned, float 32-bit, vektor atau matriks. Perpustakaan pihak ketiga menyediakan beberapa di antaranya.

  • Overflow Integer Diam . Tidak berubah tetapi itu tidak pernah menjadi masalah.

  • Modul Ketidakmampuan . Rekomendasinya bahwa fungsi dan modul harus bisa berubah adalah kemunduran suram untuk Lisp dan ide yang sangat buruk. Anda dapat menggantikan modul menggunakan includejika Anda mau, tetapi Anda tidak dapat memutasinya, tentu saja.

  • Polimorfisme Menyebabkan Kesalahan Tipe Run-time . Ini adalah masalah besar dengan OCaml dan belum diperbaiki. Saat tipe Anda mengembangkan kesetaraan polimorfik, perbandingan dan hashing akan mulai gagal ketika mereka menemukan tipe seperti fungsi dan men-debug masalahnya sangat sulit. F # memiliki solusi hebat untuk masalah ini.

  • Tidak ada Macro . Ironisnya, ketika dia menulis OCaml ini sebenarnya memiliki dukungan penuh untuk makro tetapi mereka sekarang telah memutuskan untuk mengeluarkan fitur ini.

  • Pembungkus . Ini adalah masalah nyata dan belum diperbaiki. Masih belum ada try ... finallykonstruk dalam bahasa OCaml dan tidak ada wrapper yang mengimplementasikannya di stdlib.

  • Tempat . Tidak berubah tetapi tidak menjadi masalah.

  • Rekam neraka penamaan bidang . Struktur kode Anda dengan benar menggunakan modul.

  • Sintaks . Tidak berubah tetapi tidak menjadi masalah.

  • Tidak Ada Polimorfisme . Ini sebagian besar omong kosong ketika dia menulisnya dan tidak ada yang berubah.

  • Set fungsi yang tidak konsisten . OCaml masih tidak memiliki consfungsi. Tidak apa-apa. Saya tidak ingin hal-hal Lisp dalam bahasa saya, terima kasih.

  • Tidak ada variabel dinamis . Adalah hal yang baik tentang OCaml. Masih bagus tentang OCaml.

  • Opsional ~ menghisap argumen . Argumen opsional mengguncang. Saya mendesak Microsoft untuk meminta mereka menambahkan argumen opsional ke F #.

  • Inkonsistensi aplikasi argumen parsial . Eh?

  • Keterbacaan Aritmatika . Ini telah berubah sejak saya berhenti menggunakan OCaml ~ 8 tahun yang lalu. Ternyata sekarang bisa Anda lakukan Int64.((q * n - s * s) / (n - 1L)).

  • Resolusi konflik nama diam . Dia mencoba melakukan pengembangan perangkat lunak penuh di REPL seperti yang Anda lakukan di Lisp. Jangan lakukan itu di OCaml. Gunakan file dan kompilasi batch yang beralih ke REPL hanya untuk pengujian, menjalankan kode sekali pakai, dan komputasi teknis interaktif.

  • Urutan evaluasi . Ini salah ketika dia menulisnya. Urutan evaluasi tidak ditentukan dalam OCaml.

  • Tidak ada input / output objek . Dia mengutip perpustakaan pihak ketiga yang sudah memecahkan "masalah" ini.

  • Compiler berhenti setelah kesalahan pertama . Eh?

  • Tidak ada jejak stack untuk executable yang dikompilasi secara asli . Tetap.

  • Debugger menyebalkan . Saya tidak pernah menggunakan debugger. Pengecekan tipe statis menangkap hampir semua bug saya.

  • GC menyebalkan . Saya menemukan GC OCaml luar biasa kecuali untuk satu masalah utama: kunci global mencegah pemrograman paralel.

  • Tidak ada deklarasi maju tersirat . Rekursi timbal balik secara eksplisit dirancang oleh semua ML. Satu-satunya keanehan adalah bahwa typedefinisi bersifat rekursif secara default sedangkan letbinding adalah non-rekursif secara default.

  • Fungsi putaran tidak ada . OCaml masih memiliki stdlib, tetapi perpustakaan pihak ketiga seperti Jane St's Core menyediakan rounddan teman-teman.

  • Daftar . List.mapmasih belum ekor rekursif. Saya mengirimkan tambalan untuk memperbaiki bug serius seperti ini dan harus menunggu bertahun-tahun sebelum muncul dalam rilis. Daftar masih tetap, tentu saja. Dan memang seharusnya begitu.

  • Kecepatan . Saya percaya waktu kompilasi untuk varian polimorfik besar telah diperbaiki.

  • Pencocokan pola . Kemenangan harapan atas kenyataan. Komunitas Lisp gagal melakukan ini. Oleh karena itu aturan ke-10 saya: program Lisp yang cukup rumit berisi implementasi ad-hoc, yang ditentukan secara tidak resmi dan dipenuhi bug dari setengah dari kompiler pencocokan pola OCaml.

Misalnya: apakah masih benar bahwa tidak mungkin untuk mencetak objek generik?

Ketika dia menulis bahwa Anda tidak bisa begitu saja melakukannya:

print value

tetapi Anda bisa memanggil printer cantik dari tingkat atas sebagai panggilan perpustakaan, memberikannya informasi jenis yang diperlukan. Dan ada makro yang dapat Anda gunakan untuk membubuhi keterangan struktur data agar printer cantik dibuat otomatis.

Jon Harrop
sumber
Pencocokan pola: Kode sumber OCaml dan optima keduanya merujuk pada makalah yang sama: "Mengoptimalkan Pencocokan Pola". Saya akan mengatakan bahwa "ad-hoc", "bug-ridden" atau "ditentukan secara informal" tidak dapat diterapkan secara realistis di sini. "F # memiliki solusi yang bagus untuk masalah ini": Saya benar-benar ingin melihat sedikit lebih detail tentang ini, jika memungkinkan. Jawabannya bagus tetapi mengutuk ketika berbicara consmemberikan nada yang buruk (artikel asli adalah kata-kata kasar, tetapi Anda tidak perlu menyalinnya dari itu).
coredump
2
@coredump: "Saya benar-benar ingin melihat sedikit lebih detail tentang ini, jika mungkin". F # memiliki polimorfisme ad-hoc yang ditentukan pengguna pada operator dan fungsi tertentu. Jadi Anda dapat menggunakan +int, float dan complexes tetapi Anda juga dapat mendefinisikan tipe Anda sendiri dan menambahkan kelebihan untuk +mengerjakan tipe Anda. Ini memberikan singkat dan mudah dibaca Lisp atau Haskell dengan kinerja SML atau OCaml yang dapat diprediksi baik, mencapai sesuatu yang tidak dilakukan oleh bahasa lain.
Jon Harrop
@coredump: "kode sumber OCaml dan optima keduanya merujuk ke kertas yang sama". Teknik yang dijelaskan dalam makalah itu dibangun sepenuhnya di atas sistem tipe ML. Jenis sistem yang tidak dimiliki Lisp. Optima tidak dan tidak bisa melakukan banyak hal yang dijelaskan dalam makalah itu. Lihat saja bagian 4.2 "Menggunakan informasi lengkap". Tidak ada informasi lengkap di Lisp karena tidak ada jenis varian. Misalnya, OCaml memilih antara lompatan bersarang atau tabel pengiriman berdasarkan jumlah daun tetapi informasi tersebut tidak diketahui dalam Lisp.
Jon Harrop
Lisp dan OCaml dirancang untuk hal-hal yang berbeda (misalnya dinamisme, pemrograman berbasis gambar). Tapi Lisp memiliki sistem jenis, berbeda dari Hindley-Milner, dan implementasi jangan memanfaatkannya selama kompilasi. Lihatlah sesi SBCL ini dengan contoh-contoh dari bagian 4.2 makalah ini. Kelengkapan sudah diperiksa oleh kompiler dari inferensi tipe dan deklarasi. Optima dapat menambahkan kode spesifik implementasi untuk ekspansi makro waktu kompilasi (atau SBCL VOP), untuk memiliki strategi lain, tetapi tidak ada cukup insentif untuk melakukannya.
coredump
Bagaimana hal itu berlaku untuk tipe data aljabar yang ditentukan pengguna?
Jon Harrop