Salah satu hal yang membuat Ruby bersinar adalah kemampuan untuk membuat Bahasa Khusus Domain menjadi lebih baik
Meskipun orang dapat menduplikasi perpustakaan ini di LISP melalui makro, saya pikir implementasi Ruby lebih elegan. Meskipun demikian, saya pikir ada kasus bahwa makro LISP bisa lebih baik daripada Ruby, meskipun saya tidak bisa memikirkan satu pun.
Jadi, di bidang apa makro LISP lebih baik daripada "kemampuan" Ruby untuk membuat DSL, jika ada?
memperbarui
Saya sudah menanyakan hal ini karena bahasa pemrograman modern mendekati singularitas LISP , seperti
- C mendapat preprocessor ekspansi makro , meskipun sangat primitif dan rentan terhadap kesalahan
- C # memiliki atribut, meskipun ini hanya baca, diekspos melalui refleksi
- Python menambahkan dekorator, yang dapat memodifikasi perilaku fungsi (dan kelas untuk v 3.0), meskipun terasa sangat terbatas.
- Ruby TMTOWTDI yang membuat DSL elegan, jika perawatan diterapkan, tetapi dengan cara Ruby.
Saya bertanya-tanya apakah makro LISP hanya berlaku untuk kasus khusus dan bahwa fitur bahasa pemrograman lainnya cukup kuat untuk meningkatkan abstraksi untuk memenuhi tantangan saat ini dalam pengembangan perangkat lunak.
Jawaban:
Baca On Lisp dan putuskan sendiri.
Ringkasan saya adalah bahwa Ruby lebih baik dalam menyediakan sintaks yang nyaman. Tetapi Lisp menang, dengan tangan ke bawah, pada kemampuan untuk membuat abstraksi baru, dan kemudian untuk melapisi abstraksi pada abstraksi. Tetapi Anda perlu melihat Lisp dalam praktik untuk memahami hal itu. Karenanya buku ini merekomendasikan.
sumber
But Lisp wins, hands down, at the ability to create new abstractions, and then to layer abstraction on abstraction.
Sekarang saya tahu kenapa. . .Fasilitas Ruby untuk pembuatan DSL tidak mengubah sifat bahasa. Fasilitas metaprogramming Ruby secara inheren terkait dengan sintaksis dan semantik Ruby, dan apa pun yang Anda tulis harus dimasukkan ke dalam model objek Ruby.
Bandingkan dengan Lisp (dan Skema, yang fasilitas makronya berbeda ), di mana makro beroperasi pada program abstrak itu sendiri. Karena program Lisp adalah nilai Lisp, makro adalah fungsi yang memetakan satu sintaksis sewenang-wenang yang lain.
Secara efektif, Ruby DSL masih terasa seperti Ruby, tetapi DSL Lisp tidak harus terasa seperti Lisp.
sumber
DSL Ruby sama sekali bukan DSL, dan saya benar-benar benci menggunakannya karena dokumentasi mereka benar-benar terletak pada bagaimana mereka bekerja. Mari kita ambil ActiveRecord sebagai contoh. Hal ini memungkinkan Anda untuk "menyatakan" asosiasi antara Model:
Tetapi deklaratif "DSL" ini (seperti deklaratif
class
sintaksis Ruby itu sendiri) adalah kebohongan mengerikan yang dapat diungkapkan oleh siapa pun yang memahami bagaimana Ruby "DSL" sebenarnya bekerja:(Coba lakukan sesuatu yang dekat dengan itu dalam tubuh
defclass
bentuk Lisp !)Segera setelah Anda memiliki kode seperti di atas dalam basis kode Anda, setiap pengembang pada proyek harus sepenuhnya memahami bagaimana Ruby DSL sebenarnya bekerja (bukan hanya ilusi yang mereka buat) sebelum mereka dapat mempertahankan kode. Dokumentasi yang tersedia akan sama sekali tidak berguna, karena mereka hanya mendokumentasikan penggunaan idiomatik , yang mempertahankan ilusi deklaratif.
RSpec bahkan lebih buruk daripada yang di atas, karena memiliki kasus tepi yang aneh yang membutuhkan rekayasa balik yang ekstensif untuk debug. (Saya menghabiskan sepanjang hari mencoba mencari tahu mengapa salah satu kasus pengujian saya dilewati. Ternyata RSpec mengeksekusi semua kasus pengujian yang memiliki konteks setelah kasus pengujian tanpa konteks, terlepas dari urutan kemunculannya di sumber. , karena
context
metode ini menempatkan blok Anda dalam struktur data yang berbeda dari biasanya.)Lisp DSL diimplementasikan oleh makro, yang merupakan kompiler kecil. DSL yang dapat Anda buat dengan cara ini bukan hanya penyalahgunaan sintaksis Lisp yang ada. Mereka adalah mini-bahasa aktual yang dapat ditulis agar benar-benar mulus, karena mereka dapat memiliki tata bahasa mereka sendiri. Sebagai contoh,
LOOP
makro Lisp jauh lebih kuat daripadaeach
metode Ruby .(Saya tahu Anda sudah menerima jawaban, tetapi tidak semua orang yang membaca ini ingin membaca keseluruhan On Lisp .)
sumber