Clojure vs Lisps lainnya [tertutup]

94

Maksud dari pertanyaan saya bukanlah untuk memulai perang api, melainkan untuk menentukan dalam situasi apa setiap bahasa adalah "alat terbaik untuk pekerjaan itu".

Saya telah membaca beberapa buku tentang Clojure ( Programming Clojure , Practical Clojure , The Joy of Clojure , dan Manning Early Access edisi Clojure in Action ), dan menurut saya itu adalah bahasa yang fantastis. Saat ini saya membaca Let Over Lambda yang sebagian besar berhubungan dengan makro Common Lisp, dan, itu juga, merupakan bahasa yang sangat menarik.

Saya bukan ahli Lisp (lebih dari seorang pemula), tetapi keluarga bahasa ini membuat saya terpesona, seperti halnya pemrograman fungsional, pada umumnya.

Keuntungan dari Clojure (dan kerugian dari "orang lain"):

  • Berjalan di JVM.

    • JVM adalah lingkungan bahasa berperforma tinggi yang sangat stabil yang memenuhi impian Sun tentang "Menulis sekali, jalankan [hampir] di mana saja". Saya dapat menulis kode di Macbook Pro saya, mengkompilasinya menjadi file JAR yang dapat dieksekusi, dan kemudian menjalankannya di Linux dan Microsoft Windows dengan sedikit pengujian tambahan.

    • JVM (Hotspot, dan lainnya) mendukung pengumpulan sampah berkualitas tinggi serta kompilasi dan pengoptimalan just-in-time yang sangat baik. Dimana hanya beberapa tahun yang lalu, saya menulis semua yang harus berjalan cepat di C, sekarang saya tidak ragu melakukannya di Java.

    • Model standar, sederhana, multithreading. Apakah Common Lisp memiliki paket multithreading standar?

    • Hancurkan monoton dari semua tanda kurung itu dengan [],, {}dan #{}, meskipun pakar Common Lisp mungkin akan memberi tahu saya bahwa dengan makro pembaca, Anda dapat menambahkannya ke CL.

Kerugian dari Clojure :

  • Berjalan di JVM.
    • Tidak ada rekursi atau kelanjutan ekor. Apakah Common Lisp mendukung kelanjutan? Skema membutuhkan dukungan untuk keduanya, saya yakin.

Keuntungan Orang Lain (Lisp Umum, khususnya) (dan kerugian Clojure):

  • Makro pembaca yang dapat ditentukan pengguna.

  • Keunggulan lainnya?

Pikiran? Perbedaan lainnya?

Ralph
sumber
15
pribadi saya suka satu jenis tanda kurung;) terlihat seperti kode "pembersih"
Moe
3
Dari apa yang saya baca di daftar Keuntungan Anda, saya pikir Anda mungkin juga menyukai Erlang www.erlang.org
Peer Stritzinger
4
Clojure mendukung rekursi ekor eksplisit melalui bentuk khusus "berulang". Hal ini memungkinkan Anda untuk mendapatkan semua manfaat dari rekursi ekor asalkan Anda secara eksplisit memintanya (satu-satunya pengecualian adalah bahwa saat ini ia tidak mendukung rekursi ekor timbal balik antara beberapa fungsi).
mikera
1
Clojure juga mendukung kelanjutan, setidaknya dalam arti "gaya pengoperan lanjutan". Anda benar bahwa tidak ada kelanjutan kelas satu. lihat stackoverflow.com/questions/1173133/continuations-in-clojure
mikera
@ Mikera: Rekursi-ekor pada satu fungsi. Dua fungsi memanggil satu sama lain harus dilakukan dengan "trampolining", yang semacam kludgy (tapi elegan dengan caranya sendiri :-)).
Ralph

Jawaban:

52

Daftar pribadi saya alasan untuk memilih Clojure daripada Lisps lain (ps Saya masih berpikir semua Lisps bagus!):

  • Berjalan di JVM - karenanya mendapat akses otomatis ke teknik fantastis di JVM itu sendiri (algoritme pengumpulan sampah tingkat lanjut, pengoptimalan HotSpot JIT, dll.)

  • Interoperabilitas Java yang sangat baik - menyediakan kompatibilitas dengan sejumlah besar library di ekosistem bahasa Java / JVM. Saya telah menggunakan Clojure sebagai bahasa "perekat" untuk menghubungkan perpustakaan Java yang berbeda dengan efek yang bagus. Karena saya juga mengembangkan banyak kode Java, sangat membantu bagi saya bahwa Clojure terintegrasi dengan baik dengan tooling Java (misalnya saya menggunakan Maven, Eclipse dengan plugin Counterclockwise untuk pengembangan Clojure saya)

  • Sintaks yang bagus untuk vektor [1 2 3], peta, {:bob 10, :jane 15}dan set #{"a" "b" "c"}- Saya menganggap alat yang cukup penting ini untuk pemrograman modern (selain daftar tentu saja!)

  • Saya pribadi menyukai penggunaan tanda kurung siku untuk formulir penjilidan: misalnya (defn foo [a b] (+ a b))- Saya pikir itu membuat kode sedikit lebih jelas untuk dibaca.

  • Penekanan pada pemrograman yang malas dan fungsional dengan struktur data yang persisten dan tidak dapat diubah - khususnya semua pustaka inti Clojure dirancang untuk mendukung ini secara default

  • Implementasi STM yang sangat baik untuk konkurensi multi-core. Saya yakin Clojure memiliki kisah konkurensi terbaik dari bahasa apa pun saat ini (lihat video ini untuk penjelasan lebih lanjut oleh Rich Hickey sendiri )

  • Ini adalah Lisp-1 (seperti Skema), yang secara pribadi saya lebih suka (menurut saya dalam bahasa fungsional, masuk akal untuk menyimpan fungsi dan data dalam namespace yang sama)

mikera
sumber
2
1 untuk STM. Ini, dengan sendirinya, cukup untuk membenarkan penggunaan Clojure.
André Caron
2
Anda masih bisa mendapatkan STM menggunakan pustaka CL-STM.
Mike Manilone
2
@ AndréCaron hanya jika Anda membutuhkannya.
kanan pada
Jika Anda ingin membuat apl web sederhana, dan menghostingnya di, katakanlah, host murah $ 5 / bulan, itu jelas tidak mungkin dilakukan dengan Clojure karena JVM, benar?
Hexatonic
@Hexatonic Saya tidak terlalu berpengalaman tapi sulit untuk percaya mesin yang digunakan hari ini tidak akan memiliki JVM.
MasterMastic
25

Perlu diingat bahwa Clojure adalah bahasa dan implementasi (biasanya di JVM). Common Lisp adalah bahasa dengan lebih dari sepuluh implementasi berbeda. Jadi kami memiliki ketidakcocokan kategori di sini. Anda dapat misalnya membandingkan Clojure dengan SBCL.

Umumnya:

  • versi Common Lisp berjalan di JVM: ABCL

  • kebanyakan implementasi Lisp Umum lainnya tidak

  • sebagian besar implementasi CL memiliki kemampuan multitasking, perpustakaan menyediakan antarmuka yang umum

  • Lisp umum memiliki sintaks untuk array. Sintaks untuk tipe data lain dapat ditulis oleh pengguna dan disediakan oleh berbagai pustaka.

  • Common Lisp tidak mendukung pengoptimalan atau kelanjutan panggilan ekor. Implementasi menyediakan TCO dan perpustakaan menyediakan beberapa bentuk kelanjutan.

Rainer Joswig
sumber
24

Perbedaan penting antara Clojure dan Common Lisp adalah bahwa Clojure lebih bersifat preskriptif tentang pemrograman fungsional. Filsafat Clojure, idiom, dan sampai taraf tertentu bahasa / perpustakaan sangat mendorong dan kadang-kadang bersikeras bahwa Anda memprogram secara fungsional (tanpa efek samping, tidak ada keadaan yang bisa berubah).

Common Lisp pasti mendukung pemrograman fungsional, tetapi juga memungkinkan status yang bisa berubah dan pemrograman imperatif.

Tentu saja, ada sejumlah manfaat untuk pemrograman fungsional, di bidang konkurensi dan lainnya. Tetapi semua hal lainnya sama, ada baiknya juga untuk memiliki pilihan pendekatan mana yang ingin Anda gunakan untuk setiap situasi. Clojure tidak sepenuhnya melarang pemrograman imperatif, tetapi kurang mengakomodasi gaya itu daripada Common Lisp.

Charlie Flowers
sumber
3
@Charlie Flowers: Saya percaya bahwa di Common Lisp dimungkinkan untuk memprogram dalam gaya "murni fungsional" (dukungan struktur data persisten, dll.), Tetapi membutuhkan disiplin. Benar?
Ralph
2
Hanya klarifikasi tentang "tanpa efek samping, tidak ada status yang dapat berubah" - Clojure memang memiliki status yang dapat berubah (referensi, atom, agen, dll. Semuanya dapat berubah) tetapi mengharuskan Anda mengaksesnya dengan cara yang terkontrol (yaitu melalui mekanisme STM dan transaksional terkait update semantik)
mikera
5
@mikera: kecuali bahwa Clojure mengandalkan penggunaan pustaka Java agar dapat digunakan, dan semua pustaka tersebut memerlukan gaya imperatif dan penuh dengan efek samping. Saya telah menemukan binding dengan Java menjadi hadiah beracun ...
André Caron
1
@Andre - tentu, jika Anda memutuskan untuk menggunakan pustaka yang membutuhkan status yang bisa berubah dan semantik imperatif maka Anda harus mengelolanya. Ini tidak berbeda dengan jika Anda mengakses perpustakaan semacam itu dari bahasa lain. Tetapi Anda memiliki dua opsi yang layak: a) Jangan gunakan pustaka semacam itu - Anda dapat menulis kode yang sangat bagus dalam Clojure murni atau b) membungkus kerumitan antarmuka dengan pustaka ini dalam antarmuka fungsional bergaya Clojure yang bagus, yang biasanya mudah digunakan. makro atau agen, dll. Secara keseluruhan, saya telah menemukan kemampuan untuk memanfaatkan perpustakaan Java sebagai manfaat yang jauh lebih besar daripada masalahnya.
mikera
4
@mikera: perpustakaan memiliki manfaat. Saya hanya menunjukkan bahwa menggunakan perpustakaan Java (ini adalah salah satu tujuan utama Rich Hickey untuk bahasa) benar-benar bertentangan dengan aspek Clojure "lebih fungsional daripada lisps lainnya". Komentar saya dimaksudkan untuk berarti: "kecuali jika Anda menulis ulang / membungkus perpustakaan ini, Anda akan mendapatkan kode yang tampak penting dan tidak akan mendapatkan keuntungan dari bagian-bagian yang lebih baik dari Clojure".
André Caron
10

Berikut adalah video yang bagus dengan perbandingan Scheme (Racket kebanyakan) dan Clojure .

Agar adil, Racket memiliki gula sintaks (barang pembaca tambahan) untuk tipe data juga (#hash, #, tanda kurung siku, dll.)

Plus, satu-satunya cara Clojure untuk membuat panggilan ekor yang tepat adalah dengan menggunakan recur, itulah sisi negatif dari kompilasi ke JVM.

Perhatikan bahwa recurini adalah satu-satunya konstruksi perulangan yang tidak memakan banyak waktu di Clojure. Tidak ada pengoptimalan tail-call dan penggunaan panggilan mandiri untuk perulangan batas yang tidak diketahui tidak disarankan. recurberfungsi dan penggunaannya dalam posisi ekor diverifikasi oleh penyusun. ( Formulir Khusus ).

Daniil
sumber
Link sudah mati kurasa.
nawfal
1
@nawfal Saya pikir saya memperbaikinya
Daniil
6
Link sudah mati (lagi?)
Buang Akun
1
Sepertinya video di tautan itu dapat ditemukan di sini: vimeo.com/22675078 .
PDB2
Ada juga trampolineuntuk panggilan ekor.
HappyFace