Схема проти Common Lisp: Які характеристики змінили ваш проект? [зачинено]


155

Як і StackOverflow, так і на цьому веб-сайті, не вистачає нечітких питань "Схеми проти Common Lisp", тому я хочу зробити це більш зосередженим. Питання стосується людей, які кодували обома мовами:

Під час кодування в Scheme, які конкретні елементи вашого кодування Common Lisp ви найбільше пропустили? Або, навпаки, під час кодування в Common Lisp, що ви пропустили з кодування в Scheme?

Я не обов'язково маю на увазі лише мовні особливості. Нижче перелічено всі дійсні речі, що стосуються питання:

  • Конкретні бібліотеки.
  • Специфічні особливості середовищ розробки, такі як SLIME, DrRacket тощо.
  • Особливості конкретних реалізацій, такі як здатність Gambit записувати блоки коду С безпосередньо у джерело схеми.
  • І звичайно, мовні особливості.

Приклади такого роду відповідей, на які я сподіваюся:

  • "Я намагався реалізувати X у Common Lisp, і якби у мене були схеми першокласного продовження, я б повністю зробив Y, але натомість мені довелося зробити Z, що більше постраждало".
  • "Процедура складання сценарію в моєму проекті Scheme ставала все більш болючою, коли моє дерево-джерело зростало, і я з'єднувався в більшій кількості бібліотек C. Для наступного проекту я повернувся до Common Lisp."
  • "У мене є велика існуюча база даних C ++, і для мене можливість вбудовувати C ++ дзвінки безпосередньо в мій код Gambit Scheme цілком вартує будь-яких недоліків, які може мати схема у порівнянні з Common Lisp, навіть у тому числі відсутність підтримки SWIG".

Отже, я сподіваюся на історії війни, а не на загальні настрої на зразок "Схема - простіша мова" тощо.


25
Відмінне, чітке питання. Мені цікаво про це самому; сподіваємось, що там є люди, які мають досвід обох мов, які бажають дати деяку інформацію.
Роберт Харві

1
@Josh K - це однозначно відповідально, але не обов'язково є однозначна відповідь. За винятком того, що я ставлю на облік, що він знайдеться, тому що хтось вийде з такою приголомшливою відповіддю, що всі схожі на ваа!
Гленатрон

4
@Josh: Тоді, можливо, ти не знайомий із Scheme та Common Lisp. Обидві мови є дуже потужними самі по собі, але жодна з них не сприймає мейнстріму. Чому це? Це може бути тому, що діалектів так багато; який ви обираєте? Таке порівняння може бути дуже яскравим, і ОП ретельно сформулювало питання, щоб обмежити сферу відповідей, які, на мою думку, є дуже конкретними та відповідальними.
Роберт Харві

13
Люди, не закривайте це питання лише тому, що вам це не подобається чи не можете з ним пов’язатись. Це явно "справжнє" питання; якщо ви не можете знайти кращої причини закрити його, ви не повинні голосувати за закриття.
Роберт Харві

4
Ви можете надіслати електронною поштою Річард Сталлман за його відповідь.
wassimans

Відповіді:


100

Моя ступінь здобула ступінь когнітивної науки та штучного інтелекту. З цього моменту я мав вступ в один курс в Лісп. Я подумав, що мова цікава (як у "елегантній"), але я не дуже думав про неї, поки я не натрапив на Десяте правило Грінспуна набагато пізніше:

Будь-яка достатньо складна програма C або Fortran містить спеціальну, неофіційну, неофіційну, помилку, повільну реалізацію половини Common Lisp.

Теза Грінспуна (частково) полягала в тому, що у багатьох складних програмах є вбудовані перекладачі. Замість того, щоб перекладати інтерпретатора на мову, він припустив, що це може мати більше сенсу використовувати мову на зразок Lisp, яка вже має вбудований інтерпретатор (або компілятор).

У той час я працював над досить великим додатком, який виконував визначені користувачем обчислення, використовуючи спеціальний інтерпретатор для власної мови. Я вирішив спробувати переписати його ядро ​​в Лісп як масштабний експеримент.

Минуло приблизно шість тижнів. Початковий код складав ~ 100 000 рядків Delphi (варіант Паскаля). У Ліспі це було скорочено до ~ 10000 рядків. Ще більш дивовижним було те, що двигун Lisp був у 3-6 разів швидшим. І майте на увазі, що це була робота неофіта Ліса! Весь цей досвід був для мене досить відкритим для очей; вперше я побачив можливість поєднання продуктивності та виразності однією мовою.

Через деякий час, коли я почав працювати над веб-проектом, я прослухав декілька мов. Я включив Lisp і Scheme в суміш. Врешті-решт я вибрав реалізацію схеми - Chez Scheme . Я був дуже задоволений результатами.

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

Тепер я можу відповісти на ваше запитання (принаймні частково).

Під час прослуховування ми розглянули різноманітні реалізації Lisp та Scheme. З боку Lisp ми розглянули (я вважаю) Allegro CL, CMUCL, SBCL та LispWorks. З боку схеми ми розглянули (я вважаю) Біглу, Курку, Шез, Гамбіт. (Вибір мови був давно; тому я трохи туманний. Я можу викопати нотатки, якщо це важливо.)

Одразу ж ми шукали: а) рідні теми та б) підтримку Linux, Mac та Windows. Ці дві комбіновані умови вибили всіх, але (я думаю) Аллегро та Шез - тому, щоб продовжити оцінку, нам довелося послабити вимогу багаторізкових ниток.

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

Для наших потреб лише три комерційні реалізації - Allegro, Chez та Lispworks - пройшли наші основні тести. З трьох лише Chez пройшов усі випробування літаючими фарбами. На той час я думаю, що Lispworks не мав натільних потоків на будь-якій платформі (я думаю, що вони зараз є), і я думаю, що в Allegro були лише рідні теми на деяких платформах. Крім того, компанія Allegro мала плату за ліцензію на час "зателефонуйте нам", що мені не дуже сподобалось. Я вважаю, що у Lispworks не було плати за час роботи, і Chez мав прямий (і дуже розумний) домовленість (і він запускався лише тоді, коли ви використовували компілятор під час виконання).

Отримавши кілька значних фрагментів коду як у Lisp, так і в Scheme, ось деякі порівняльні та контрастні точки:

  • Середовища Lisp набагато зріліші. Ви отримаєте набагато більше грошей на долар. (Сказавши це, більше коду також прирівнюється до більшої кількості помилок.)

  • Середовища Lisp набагато складніше вивчити. Вам потрібно набагато більше часу, щоб стати досвідченим; Звичайний Lisp - це величезна мова - і це ще до того, як потрапити до бібліотек, які комерційні реалізації додають поверх нього. (Сказавши це, синтаксисний випадок схеми набагато тонкіший і складніший, ніж будь-яка річ у Ліспі.)

  • У середовищах Lisp може бути дещо складніше виробляти бінарні файли. Вам потрібно "струсити" зображення, щоб видалити непотрібні біти, і якщо ви не будете правильно виконувати програму під час цього процесу, ви згодом можете отримати помилки під час виконання. . Навпаки, з Chez ми складаємо файл верхнього рівня, який включає всі інші необхідні йому файли, і ми закінчили.

Я говорив перед тим, що ми закінчилися використовувати схему в ряді місць, в яких ми спочатку не мали наміру. Чому? Я можу придумати три причини з верху голови.

По-перше, ми навчилися довіряти Chez (та його розробнику, Cadence). Ми багато просили у інструменту, і він послідовно постачав. Наприклад, Chez історично мав тривіально малу кількість дефектів, і його менеджер пам'яті був дуже, дуже хорошим.

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

По-третє, ми навчилися любити схему абстрагування, яку може надати. Я маю на увазі не просто макроси; Я маю на увазі такі речі, як закриття, лямбдахи, виклики хвостів тощо. Після того, як ви почнете думати в цих термінах, інші мови здаються досить обмеженими порівняно.

Чи ідеальна схема? Немає; це компроміс. По-перше, це дозволяє окремим розробникам бути ефективнішими - але розробникам складніше копіювати код один одного, тому що в схемі відсутні покажчики більшості мов (наприклад, для циклів) (наприклад, мільйон способів зробити a для петлі). По-друге, існує набагато менший пул розробників, з якими можна поговорити, найняти, взяти позики тощо.

Підсумовуючи це, я думаю, що я б сказав: Lisp і Scheme пропонують деякі можливості, широко не доступні ніде. Ця здатність є компромісною, тому краще бути такою, яка має сенс у вашому конкретному випадку. У нашому випадку визначальні фактори між тим, чи потрібно переходити з Lisp чи Scheme, мали більше спільного з дуже фундаментальними особливостями (підтримка платформи, потоки платформи, компіляція часу, ліцензування виконання), ніж з мовою чи функціями бібліотеки. Знову ж таки, у нашому випадку це теж було компромісом: з Chez ми отримали основні функції, які ми хотіли, але ми втратили великі бібліотеки, котрі мали комерційні середовища Lisp.

Крім того, лише ще раз: ми давно розглядали різні Lisps та Schemes; всі вони розвивалися і вдосконалювалися з тих пір.


1
Нічого собі, це, мабуть, був якийсь справді жахливий код Delphi, якщо йому якось вдалося виконати 3-6 разів повільніше, ніж реалізація Lisp! :(
Мейсон Уілер

2
+1: Найцікавіше в цій публікації - це той факт, що ви перейшли з програми Lisp на схему після того, як у проекті було зроблено великий проект. (Або, можливо, я занадто довго ховаюся на comp.lang.lisp.)
Ларрі Коулман

25
"Нічого собі, це, мабуть, був якийсь жахливий код Delphi, якщо йому якось вдалося виконати 3-6 разів повільніше, ніж реалізація Lisp!" Правильно, я вважаю це своїм промахом у тому, щоб не пояснити це краще. Реалізація Lisp змогла перетворити вирази користувачів у вирази Lisp - тривіально простий процес - і потім скомпілювати вирази Lisp у рідний код (з повною оптимізацією). Ось в чому полягає Десяте правило Грінспуна.
Майкл Ленаган

1
Фантастична відповідь! Я виберу його, принаймні, поки не з’явиться кращий :) Одне питання: ти кажеш, що ти прийняв рішення піти зі схемою Chez на основі стану поля "давно". Не могли б ви вказати рік?
SuperElectric

11
Цей пункт про те, що реалізація LISP вільна складати щось до машинного коду, а не покладатися на інтерпретатора, є тонким і досить корисним. У книзі "Let over Lambda" вказується саме на те, що портативний загальний пакет LISP regexp, який клонує синтаксис PERL regexp, перевершує PERL за значним фактором. У PERL, внизу, є перекладач повторної експресії. Загальний пакет LISP компілює зворотні коди до коду.
Джон Р. Стром

37

Зазвичай я не люблю вставляти посилання як відповідь, але я написав статтю в блозі саме на цьому. Це не є вичерпним, але воно отримує деякі основні моменти.

http://symbo1ics.com/blog/?p=729

Редагувати : Ось принципові моменти:

  1. ІСНУВАННЯ : Обидва лепече прийшов після того, як купу інших Ліспі. Схема брала мінімальний, аксіоматичний маршрут. CL пройшов шлях бароко.
  2. СЛУЧАЙ : Зазвичай схема відрізняється від регістру. CL немає (хоча це може бути). Іноді це не вистачає, але його практичність обговорюється (мною).
  3. ІМЕНИ : Назви символів у CL багато разів непарні та заплутані. TERPRI, PROGNі т. д. Схема зазвичай має дуже розумні назви. Це щось пропущено в CL.
  4. ФУНКЦІЇ : CL має окремий простір імен функцій. Це не пропущено в Схемі. Наявність єдиного простору імен, як правило, дозволяє робити дуже чисте функціональне програмування, що часто є важким або незручним в CL. Але це коштує --- вам іноді доводиться приховувати імена типу " list" до " lst" в Scheme.
  5. МАКРОС : Я найбільше пропускаю брудні макроси низького рівня в схемі. Так, syntax-rulesвсе гаразд і денді, поки ви не захочете справді виламати деякі речі. З іншого боку, гігієнічні макроси іноді пропускаються в CL. Не маючи стандартного способу це зробити, означає переосмислити колесо.
  6. ПОРТИВНІСТЬ : Часто трапляється, що CL є більш портативним, незважаючи на те, що обидві мови стандартизовані. CL більше, і тому є більш стандартні функції, які можна використовувати без зовнішніх бібліотек. Це також означає, що більше залежних від реалізації речей можна зробити портативно. Також у схеми є трильйон реалізацій, більшість з яких є дещо несумісними. Це робить CL дуже бажаним.
  7. БІБЛІОТЕКИ : Дуже стосується мого останнього моменту. Схема має SRFI, але вони не є загальновизнаними. Немає портативного способу роботи з бібліотеками. З іншого боку, CL має способи. І Quicklisp - це подарунок від бога (Xach) --- свого роду сховище бібліотек для використання.
  8. ВПРОВАДЖЕННЯ : Схема страждає від такої кількості реалізацій. Реального канонічного втілення немає. З іншого боку, CL має дуже приємні високопродуктивні або конкретні варіанти реалізації (висока продуктивність: SBCL, комерційна: Allegro, вбудована: ECL, портативна: CLISP, Java: ABCL, ...).

Хоча я говорив лише від першої особи трохи вище, повинно бути зрозуміло, що я сумую, а що ні.

[Я вибачаюся, якщо вони занадто загальні. Здається, вам можуть знадобитися набагато більш конкретні деталі. У публікації є певна специфіка.]


що про (справді) короткий підсумок тизера? ^^
Дейв О.

2
Будь ласка, підкресліть основні моменти. Відповіді повинні бути самостійними.

1
@Dave O. та @ Thorbjørn Ravn Andersen: Додано резюме за запитом. Дякую.
Квадресценція

2
«Маршрут бароко»! Який чудовий спосіб це поставити.
Марк C

Звичайний Lisp залежить від регістру, але перетворює його в великі регістри, перш ніж оцінювати його. Ви можете отримати малі літери в символах, цитуючи їх. Проблема з іменем пов’язана з тим, що Схема позбулася поганих старих імен, а CL не стала.
Девід Торнлі

25

Нещодавно я розпочав домашній проект, використовуючи бібліотеку, яка має версію С та версію Java. Я хотів використати Lisp для проекту, і я витратив близько місяця на коливання між використанням Common Lisp, Scheme або Clojure. Я маю певний досвід роботи з усіма трьома, але тільки іграшковими проектами. Я розповім вам трохи про мій досвід роботи з кожним із них, перш ніж розповісти, яку саме з них я обрав.

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

Моя загальна реалізація Lisp (SBCL) не має IDE, однак у звичайних реалізаціях CL з відкритим кодом використовується Emacs та SLIME. Це поєднання може бути дуже ефективним. Поряд із можливістю оцінювати вирази під час введення їх у вихідний файл, є також REPL, у якому є всі команди редагування emacs, тому копіювання коду може йти ефективно обома способами. Навіть об'єкти, відображені в буфері REPL, можна скопіювати та вставити. Alt+(і Alt+)є ефективними для боротьби зі збігнутими дужками та відступами.

Усі перераховані вище функції Emacs також доступні для Clojure. Мій досвід редагування Clojure схожий на досвід Lisp. Інтероп Java працював чудово, і я хотів би зробити проект Clojure, як тільки він дозріє.

Мені вдалося отримати доступ до бібліотеки за допомогою всіх трьох (Common Lisp, Racket та Clojure), але я нарешті вибрав Common Lisp для проекту. Вирішальним фактором було те, що FFI було набагато простіше використовувати в Common Lisp. CFFI має дуже хороший посібник із прикладом коду та детальними поясненнями кожного методу. Мені вдалося завернути 20 градусів у другій половині дня, і з того часу мені не доводилося торкатися коду.

Іншим фактором було те, що я більше знайомий із Common Lisp, ніж зі схемою Clojure або R6RS. Я прочитав більшість книг Практичного загального Ліса і Грема, і мені дуже комфортно з Гіперспеком. Це ще не дуже "ліпистий" код, але я впевнений, що це зміниться, коли я набуватиму більше досвіду.


Дякую за деталі! Я правильно вас розумію, що ви думали, що FFI SBCL простіший у використанні, ніж Clojure? Якщо це так, я був би дуже здивований цим, враховуючи, що ви можете просто викликати методи Java безпосередньо з Clojure, не потребуючи їх обгортати. (Або вам також потрібно було подзвонити на рідний код?)
SuperElectric

6
@SuperElectric: Виклик "вбудованих" методів Java з Clojure тривіальний; виклик методів Java, які є у завантаженій бібліотеці: не так багато. Я дійсно витрачав більше часу на те, щоб правильно прокласти класний шлях та імпорт ліній, ніж мені знадобилось перший метод C, що працює з SBCL з CFFI. Але я не експерт по Java, тому Ваш Пробіг може варіюватися.
Ларрі Коулман

21

Я програмую як в CL, так і в ракетці.

Зараз я розробляю веб-сайт у Common Lisp, і я написав набір внутрішніх програм для свого попереднього роботодавця в Racket.

Для внутрішнього коду я вибрав Ракетку (тоді відому як PLT-схема), оскільки роботодавець був магазином Windows, і я не міг змусити їх платити за LispWorks. Єдиною гарною реалізацією CL з відкритим кодом для Windows була (і досі є) CCL, яка потребує підтримки SSE в процесорі. Роботодавець, будучи дешевим, використовував техніку Stone Stone. Навіть якщо роботодавець мав пристойне обладнання, єдиною бібліотекою GUI у Common Lisp є McCLIM, яка працює тільки на Unix. Ракетка має хорошу бібліотеку графічного інтерфейсу, яка працює як на Unix, так і на Windows, що було критично важливим для успіху мого проекту.

Я витратив більше року, мирившись з примітивним редактором DrRacket. EMACS не міг перетворити GUI-версію Ракетки, тоді відому як MrEd, на неповноцінне для Windows. Мені довелося це зробити, не маючи змоги оцінити вираз курсором одним натисканням клавіші. Натомість мені довелося вручну вибрати S-вираз, скопіювати його, натиснути на вікно REPL (оскільки немає перемикання клавіш для перемикання на нього), а потім вставити S-вираз. Я також повинен був обійтися без редактора, який міг би показати мені очікувані аргументи функції або макросу, який я використовував. DrRacket не замінює SLIME.

Роботодавець використовував власну базу даних зі складним API XML, яка вимагала навантаження, здавалося б, непотрібної інформації, щоб мати можливість відповідати на свою версію запиту SELECT. Я вирішив використовувати HTMLPrag і для передачі XML в цей API, і для аналізу відповідей. Це спрацювало чудово.

Мені довелося вивчити надскладну макросистему "Синтаксис-випадок" Ракетка, щоб написати макрос, який дозволив би мені взаємодіяти з надскладним API XML, набравши форми, схожі на SQL. Ця частина була б набагато легшою, якби я мав DEFMACRO в своєму розпорядженні. Однак кінцевий результат все ще був безперебійним, хоча для його досягнення було потрібно більше зусиль.

Крім того, мені довелося обійтися без макроса LOOP Common Lisp. Ракетка почала надавати альтернативу лише після того, як я написав більшу частину коду, і альтернатива все-таки висмоктується порівняно з LOOP (навіть якщо команда з розробки Racket наполягає на тому, що краще - вони просто помиляються). Я закінчив писати багато іменованих форм LET, які використовували "car" та "cdr" для перегляду списків.

Якщо говорити про автомобіль та компакт-диск, то ніщо не засмучує трактування схеми (автомобіль '()) як помилку. Я скористався чутливістю до регістру і застосував CAR та CDR, які мають загальну семантику Ліспа. Однак розділення '() і #f робить набагато менш корисним повернення' () як значення за замовчуванням.

Я також закінчив повторну реалізацію UNWIND-PROTECT і створив власну систему перезапуску, щоб заповнити прогалину, залишену Racket. Спільнота Ракетки повинна дізнатися, що перезавантаження дуже корисні та прості у здійсненні.

Форма пускових значень ракетки була надмірно багатослівною, тому я реалізував MULTIPLE-VALUE-BIND. Це було абсолютно необхідно, тому що Ракетка вимагає від вас отримувати всі створені значення, незалежно від того, використовуєте ви їх чи ні.

Пізніше я спробував написати клієнт API eBay XML в Common Lisp, лише щоб виявити, що він не має нічого подібного до HTMLPrag. HTMLPrag корисно корисний. Я закінчив робити цей проект у Ракетці. Я експериментував з програмами грамотного програмування Ракетка, лише виявив, що я єдиний програміст на Землі, який вважає, що правильно написаний грамотний код важче редагувати, ніж звичайний код, або неправильно написаний грамотний код «надмірних коментарів».

Мій новий проект робиться в Common Lisp, що був правильним вибором, оскільки спільнота Ракет просто не вірить у паралелізм, що є важливим для цього проекту. Єдине, що я думав, що я міг пропустити з Ракетки, - це продовження. Однак я зміг зробити те, що мені потрібно, використовуючи перезавантаження, і, заднім числом, напевно, це можна було зробити з простим закриттям.


2
Я сам не пробував цього, але я бачив повідомлення в блогах від людей, які використовують програму ракетки командного рядка з Emacs. Наприклад: bc.tech.coop/scheme/scheme-emacs.htm
Ларрі Коулман

5
Справедливо кажучи, це виглядає так, що ви прийшли до схеми, бажаючи написати CL, а не намагатися наблизитись до ідіоматичної схеми POV. Наприклад, чи схема не заохочує рекурсію, а не використання циклів?
Санки

Схема @ArtB не просто заохочує рекурсію, вона вимагає цього, тому, звичайно, вищезгаданий проект використовував цілу масу рекурсій. І це тільки для додавання повторення (ви повинні включити копію рекурсивного дзвінка у кожну гілку condформи, наприклад) та помилок (чи правильно я написав тест на припинення циклу в той час?) Навіть сьогодні я створюю враження що Ракетка в основному призначена для студентів, а не професійних програмістів. Кожен раз, коли я чую, як хтось, окрім мене, його використовує, вони використовують підмову "Починаючи студент", і це для класу.
Викиньте рахунок

Якщо ви повторюєте код у COND, чи говорите ви, що вам просто потрібна інша функція?
Санки

@ArtB Функція викликати циклічну функцію з різними аргументами? Це було б безглуздо. Таке повторення ви бачите майже в будь-якому коді схеми. Є навіть приклади у власному вихідному коді Ракетки.
Викиньте рахунок

5

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

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

На щастя, є реалізації схеми (наприклад, Racket), які не мають такого обмеження.


1
Привіт, нещодавно я почав мочити ноги від схеми останнім часом за допомогою ракетки. Ви б не хотіли запропонувати короткий приклад використання негігієнічних макросів у Ракетці? Тип доступних макросів здається однією з найбільш гарячих дискусійних точок між CL та Scheme.
помаранчевий80

@ orange80, один із підходів полягає у використанні docs.racket-lang.org/mzlib/mzlib_defmacro.html І, звичайно, в режимі R6RS існує менш обмежувальний спосіб.
SK-логіка

@ SK-логіка, що ти робиш з такими антигенними макросами?
Санки

1
@ArtB, я реалізую eDSL як функції компілятора, які можуть зробити багато з їх джерелом AST. Гігієна є цілковитою неприємністю в рамках такого підходу. Ви можете подивитися, як це працює: github.com/combinatorylogic/mbase
SK-логіка
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.