У якій області макрос LISP краще, ніж "здатність" Рубі створювати DSL


21

Одна з речей, завдяки якій Ruby сяє - це можливість створювати мови, що відповідають конкретним доменам, як-небудь краще

Хоча можна дублювати ці бібліотеки в LISP через макрос, я думаю, що реалізація Ruby є більш елегантною. Тим не менш, я думаю, що є випадки, що макрос LISP може бути кращим, ніж Рубі, хоча я не міг придумати його.

Отже, в якій області макрос LISP кращий за "здатність" Рубі створити DSL, якщо така є?

оновлення

Я запитав це, тому що сучасні мови програмування наближаються до особливості LISP , як

  • C отримав препроцесор макророзширення , хоча і дуже примітивний і схильний до помилок
  • C # має атрибути, хоча це лише для читання, відкриті через рефлексію
  • Python додав декоратор, який може змінювати поведінку функції (і класу для v 3.0), хоча відчуває себе досить обмеженим.
  • Ruby TMTOWTDI, який робить елегантний DSL, якщо доглядати, але в Ruby.

Мені було цікаво, чи макрос LISP застосовний лише до спеціальних випадків і що інші функції мови програмування є достатньо потужними, щоб підняти абстракцію для вирішення сьогоднішніх проблем у розробці програмного забезпечення.


4
Я не зовсім впевнений, чому на цьому є близькі голоси. Я хоч це питання, якого ми хочемо ? Цікаво, що провокує думку та сферу застосування досить чітко визначено.
Tim Post

Спробуйте реалізувати щось подібне в Ruby: meta-alternative.net/pfront.pdf
SK-logic

@Tim Post: Одна проблема полягає в тому, що на це насправді непросто відповісти, якщо ви добре не знаєте і Common Lisp, і Ruby. Інша - досить необізнані посилання на інші мови, які можуть дратувати пуристів: не існує мови під назвою C / C ++, і значна частина C ++ - це система шаблонів, і припущення про те, що макросистема Common Lisp застосовується лише в особливих випадках. По суті, це гарне запитання, але написане погано і важко відповісти.
Девід Торнлі

@David Thornley, я оновив публікацію, особливо на C \ C ++, і акцентую увагу на C. Що стосується звичайного Lisp, я відчував, що оскільки інші мови програмування мають більш високу абстракцію, це особливість макросуцінки для особливих випадків. Я розмістив питання, сподіваючись, що інші покажуть мені, що макрос CL не для особливих випадків все ще є потужною особливістю.
OnesimusUnbound

@OnesimusUnbound: Я дійсно включав би шаблони C ++ у свій список мовних прикладів, оскільки вони принаймні теоретично здатні до будь-яких обчислень, які може зробити макросистема Lisp. Що стосується макросів Lisp, знайдіть якийсь хороший загальний код Lisp (там є багато F / OS Lisp-коду) та знайдіть "defmacro" (можливо, ви захочете зробити нечутливий до обліку рейтинг). Ви, мабуть, знайдете їх чимало. Вважайте, що макроси складніше, ніж функції писати та отримувати правильно, і ви зрозумієте, що вони мають бути загалом корисними.
Девід Торнлі

Відповіді:


23

Читайте на Lisp, а потім вирішуйте самі.

Моє резюме полягає в тому, що Рубі краще надавати зручний синтаксис. Але Лісп виграє, опустивши руки, при здатності створювати нові абстракції, а потім нашаровувати абстракцію. Але вам потрібно побачити Лісп на практиці, щоб зрозуміти цей момент. Тому книга рекомендую.


1
"Let Over Lambda" охоплює набагато подібний грунт. Також рекомендується читати.
John R. Strohm

But Lisp wins, hands down, at the ability to create new abstractions, and then to layer abstraction on abstraction.Тепер я знаю, чому. . .
OnesimusUnbound

Не дуже важливо надавати будь-який синтаксис на вершині Lisp. Насправді, набагато простіше, ніж з Рубі, завдяки читацьким макросам.
SK-логіка

1
@ SK-логіка: Правда. Однак Лісперс ухиляється від макросів читачів, тому що, коли ви спускаєтесь цим маршрутом, він більше не відчуває себе Lisp. Насправді деякі варіанти Lisp, такі як Clojure, резервні макроси читачів для мовного дизайнера.
btilly

14

Засоби Ruby для створення DSL не змінюють характеру мови. Засоби метапрограмування Ruby по суті пов'язані з синтаксисом та семантикою Ruby, і все, що ви пишете, повинно бути об'єднано в об'єктну модель Ruby.

Порівнюйте це з Lisp (та схемою, макрооб'єкти якої відрізняються ), де макроси працюють над самою абстрактною програмою. Оскільки програма Lisp - це значення Lisp, макрос - це функція, яка відображає один по суті довільний синтаксис до іншого.

Ефективно, Ruby DSL все ще відчуває себе як Ruby, але Lisp DSL не повинен відчувати себе Lisp.


6
+1: LOOP не дуже відчуває себе Lispy, як приклад DSL.
Френк Ширар

2

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 .)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.