DSL-адреси Ruby взагалі не є DSL, і я абсолютно не люблю їх використовувати, оскільки їх документація не відповідає тому, як вони насправді працюють. Візьмемо для прикладу ActiveRecord. Це дозволяє "оголошувати" асоціації між Моделями:
class Foo < ActiveRecord::Base
has_one :bar
has_one :baz
end
Але декларативність цього "DSL" (як і декларативність самого class
синтаксису Рубі ) - це жахлива брехня, яку може викрити кожен, хто розуміє, як насправді працюють "DSLs" Ruby:
class Foo < ActiveRecord::Base
[:bar,:baz,:qux,:quux].each do |table|
has_one table if i_feel_like_it?(table)
end
puts "Just for shits and giggles, and to show"
puts "just how fucked up Ruby really is, we're gonna ask you"
puts "which SQL table you want the Foo model to have an"
puts "association with.\n"
puts "Type the name of a table here: "
has_one gets.chomp.to_sym
end
(Просто спробуйте зробити все, що є близьким до цього в тілі форми Lisp defclass
!)
Як тільки у вашій кодовій базі з'явиться такий код, як зазначено вище, кожен розробник проекту повинен повністю зрозуміти, як насправді працюють DSL-файли Ruby (не лише ілюзія, яку вони створюють), перш ніж вони зможуть підтримувати код. Доступна документація буде абсолютно марною, оскільки вони документують лише ідіоматичне використання, що зберігає декларативну ілюзію.
RSpec навіть гірший за вищезазначене, оскільки він має химерні крайові випадки, які потребують великої зворотної інженерії для налагодження. (Я провів цілий день, намагаючись з’ясувати, чому пропускається один із моїх тестових випадків. Виявилося, що RSpec виконує всі тестові випадки, які мають контексти після тестових випадків, без контексту, незалежно від порядку, в якому вони з’являються у джерелі , тому що context
метод розміщує ваш блок у іншій структурі даних, ніж зазвичай він використовується.)
DSL-файли Lisp реалізовані макросами, які є невеликими компіляторами. DSL, які ви можете створити таким чином, не є простими зловживаннями існуючого синтаксису Lisp. Це фактичні міні-мови, які можна записати абсолютно безшовно, оскільки вони можуть мати власну граматику. Наприклад, LOOP
макрос Lisp набагато потужніший, ніж each
метод Рубі .
(Я знаю, що ви вже прийняли відповідь, але не кожен, хто це прочитає, захоче прочитати всю програму On Lisp .)