LINUX.ORG.RU

Чем так хороши макросы в Lisp?

 


4

7

Уже много всякого прочитал про лисп(в том числе Practical Common Lisp и уже даже освоился с Clojure), но никак не могу понять, чем же на самом деле являются макросы в этом языке. И этот вопрос не дает мне покоя т.к. лисп сильно повлиял на мое мышление и я вижу, что лисп (а особенно, common lisp для своего времени), действительно, лучше и удобней других языков (ну, за исключением странного скобочного синтаксиса ^^) ... Если бы его преимущества заключались в динамической типизации, сборке мусора и интерактивном цикле разработки, то их в полной мере имели бы питон, javascript и даже php.

Обычно пишут, что макросы - сильная сторона лиспа, которая отличает его от других языков и в качестве аргументов приводят неудачные примеры, которые довольно просто реализовать в других языках. Может кто-нибудь объяснить более-менее формально, что такое макросы? В чем их преимущества?

Для себя мне удалось выделить лишь два свойства макроса, отличающих его от функции:

макрос выполняется до исполнения кода; вычислением аргументов макроса управляет программист.

Первое мне видится ограничением, которое приводит к целому ряду неудобств, как, например, невозможность применить apply к макросу(особено часто хочится сделать (apply and ...) или (reduce and ...)).

А второе может быть легко реализовано посредством функций высшего порядка хоть в C и C++. Для примера, в весьма популярной книге «Приемы объектно-ориентированного проектирования. Паттерны проектирования» Э. Гамма, Р. Хелм, Р. Джонсон, Д.Влиссидес описываются пaттерны Command и Interpreter - в комбинации это в точности макросы времени выполнения...



Последнее исправление: CheKastro (всего исправлений: 1)

Ответ на: комментарий от anonymous
(defstruct thunk f)

(defun feval (x)
  (if (thunk-p x) (funcall (thunk-f x)) x))

(defun fand (&rest args)
  (cond
   ((null args) t)
   ((feval (car args)) t)
   (t (apply #'fand (cdr args)))))

(defmacro thunk (&body body)
  `(make-thunk :f (lambda () ,@body)))

(defun sum (x y) (+ x y))
(defun sum2 (x y) (+ (feval x) (feval y)))

(defun wrap (f1 f2 f3 data)
    (mapcar #'apply (list f1 f2 f3) (list data data data)))

(defvar lst '(1 2))

(print (wrap #'sum #'sum2 #'fand lst))
monk ★★★★★
()
Последнее исправление: monk (всего исправлений: 1)
Ответ на: комментарий от anonymous

Это сарказм

спасибо, кэп, но картинка забавная

wota ★★
()
Ответ на: комментарий от anonymous

Бред, s-выражения и макросы по всех лиспах одинаковые

Кроме s-выражений ещё есть правильные замыкания, которые называются «продолжения». В CL их нет :-(

monk ★★★★★
()
Ответ на: комментарий от ilammy

Чем препроцессор на Лиспе, выдающий код на Лиспе для использования в программе на Лиспе не угодил?

Тем, что неочевидно, от какого внешнего файла зависит компиляция. В отличие от строки в Makefile. Или явного указания в системе ASDF.

monk ★★★★★
()
Ответ на: комментарий от anonymous

То, что они использовали racket для одного из многих скриптовых язычков для модописцев, в надежде привлечь хипстеров-борщевиков, еще не делает эту игру «продуктом на лиспе».

Чушь, никаких модописцев. У них вся игра на лиспе писана - геймплей, анимация, эффекты, звук.

anonymous
()
Ответ на: комментарий от anonymous

Чушь. У них весь игровой движок на C++ написан, а на лишпике только некоторые из скриптиков в контенте.

anonymous
()
Ответ на: комментарий от monk

Ну, может, я неправильно помню. Ладно, не суть.

feofan ★★★★★
()
Ответ на: комментарий от anonymous

У них весь игровой движок на C++ написан

Ясень пень, кто же будет низкоуровневый игровой движок на Лиспе писать.

а на лишпике только некоторые из скриптиков в контенте.

А на Лиспе - весь геймплей, вся анимация, все эффекты и весь звук - что игру и составляет.

anonymous
()
Ответ на: комментарий от monk

Я честно скажу, CL не знаю. Но подозреваю, что ты надо мной издеваешься. Где у тебя в wrap настоящий макрос в качестве аргумента? Костыли то ты настрочил, но расширять такой код безкостыльно не сможешь. Объем кода, сложности и костыльности будет расти экспонцеально.

anonymous
()
Ответ на: комментарий от anonymous

Ололо, лишпик догнал Quake C и отсосал у Луа. Серьезно, это все, чем борщехлебы могут похвастаться?!?

anonymous
()

Кстати, если кто из анонимусов готов к нормальной дискуссии - прошу зарегистрироваться, т.к. анонимус у меня с форума Development вырезается. Весь. Очень много информационного шума от одного представителя было.

naryl ★★★★★
()
Ответ на: комментарий от anonymous

По теме есть, что сказать, или засчитываем слив?

anonymous
()
Ответ на: комментарий от naryl

А вот и рваные пердаки пролетели.

anonymous
()
Ответ на: комментарий от anonymous

Не поленился и загуглил. Нашел небольшое АМА одного из их программистов на реддите.

В самой игре нет ни строчки на рекете. Он используется для утилит, в частности генератор компиляторов различных скриптов

anonymous
()
Ответ на: комментарий от anonymous

Повторяю специально для тормозов: на Лиспе написан весь геймплей, вся анимация, все эффекты и весь звук.

anonymous
()
Ответ на: комментарий от anonymous

Где у тебя в wrap настоящий макрос в качестве аргумента?

А кто говорит про wrap? Ты просил fexpr как в newlisp.

Настоящий макрос существует только на этапе компиляции, так как является функцией из узла AST в узел AST. В скомпилированном коде его быть не может.

monk ★★★★★
()
Ответ на: комментарий от anonymous

Повторяю для рваных пердаков: от того, сколько раз ты повторишь свое вранье, правдой оно не станет.

anonymous
()
Ответ на: комментарий от anonymous

от того, сколько раз ты повторишь свое вранье, правдой оно не станет.

Обоснуй, что это вранье.

anonymous
()
Ответ на: комментарий от anonymous

Слайды:

«In games, programmers create code; artists, designers, animators, sound designers create data.

We often want to create data like we create code Effect definitions, animation states & blend trees, event & gameplay scripting/tuning, sound metadata.

We want powerful abstractions, flexible syntax, and language well matched to each domain

Domain Specific Languages to the rescue!»

Подтверждаются мои слова.

anonymous
()
Ответ на: комментарий от anonymous

Пост отвечающий на вопросы, начинающиеся с what kind of tools

«We would use it to create compilers for a wide range of data, including effects, animation, dialogue, sound, and gameplay scripting»

Опять подтверждаются мои слова.

anonymous
()
Ответ на: комментарий от anonymous

А почему это замыкания? И в чем их правильность?

Замыкание является обобщением функции. То есть его можно передать туда, куда можно передать функцию, но замыкание может хранить состояние.

Продолжение является обобщением замыкания. В отличие от замыкания, продолжение позволяет указать куда впоследствии передать управление.

И в чем их правильность?

В том, что генераторы, кооперативная многопоточность, сопрограммы, поиск по произвольным множествам при помощи функций высшего порядка делаются легко и непринуждённо.

В CL делается только с огромным костылём в виде cl-cont.

monk ★★★★★
()
Последнее исправление: monk (всего исправлений: 1)
Ответ на: комментарий от anonymous

Если брать конкретно Racket, то там ещё есть возможность прицеплять к каждому фрэйму произвольные данные: http://docs.racket-lang.org/reference/eval-model.html#(part._mark-model)

Очень удобная штука для трассировки, отладки, профилирования. Жаль, в scheme отладчики не в почёте (на фоне SBCL в DrRacket отладчик выглядит игрушкой). И нету сохранения образа, разве что внешними утилитами. Соответственно, нету поддержки image-based разработки.

monk ★★★★★
()
Ответ на: комментарий от monk

на фоне SBCL в DrRacket отладчик выглядит игрушкой

Если гуй для вас слабоват, тогда отлаживайте в репле. Но лучше пишите юнит тесты.

И нету сохранения образа, разве что внешними утилитами.

Вам никто не запрещает компилировать модули в рантайме, т.к. компилятор выполнен в виде библиотеки.

Соответственно, нету поддержки image-based разработки.

А как вы туда запихнете модули написанные на C/C++? Конечно, можно создать бигфасл, но опять же модули написанные на C/C++, тогда придется грузить в рантайме.

anonymous
()
Ответ на: комментарий от naryl

'Patterns mean «I have run out of language.»' — Rich Hickey

Рич Хикки - мерзкий говнюк. Само его существование является оскорблением наследия Лиспа, гения МакКарти и всех тех трудов, которые Лисперы вкладывали в дело за последние годы. Тот факт, что Clojure работает на JVM - это мелочь по сравнению с прочими смертными грехами, каковых настолько много (и которые так меня бесят), что я здесь даже половины не перечислю.

Ну что, начнем со сваливания в кучу функций и значений? В нормальном Лиспе головные формы распознаются моментально, потому что они, блядь, идут в начале списка. Когда с этим облажались в Scheme, было уже довольно хреново; еще хуже стало, когда на те же грабли наступил Пол «Поглядите-я-даже-не-знаю-что-такое-интерактивная-разработка» Грэм. И что, никто ничему не научился на их ошибках? Ах, ну да, в Scheme попытались это вылечить так называемыми «гигиеническими макросами», которые были хотя бы юзабельны, несмотря на убогость. В Clojure даже того нет - это просто смешно.

Но это еще не самое плохое. В Clojure слишком много синтаксиса! Похоже, что Хикки в качестве модели выбирал Haskell. Я не припомню другого языка, в котором было бы столько синтаксиса. В виде Кложуры мы получили самый синтаксически тяжеловесный лисп-подобный язык на сегодняшний день. («Лисп-подобный» - потому что, за исключением самых поверхностных моментов, на самом деле в Кложуре нет ничего от Лиспа.) Самые обычные вещи, которые тривиально реализуются в терминах головных форм, в Clojure превращаются в мешанину из скобок и разделителей, даже в элементарнейших случаях. [foo] вместо (list foo), {:foo bar} вместо (dict :foo bar)...

Лямбда. Это слово пишется как «lambda», а не «fn». Не так уж и сложно набрать, правда, мистер Хикки? Что, руку вывихнул, пока дрочил на собственное дутое ЧСВ? Надеюсь, руки у тебя отсохнут и отвалятся, а сам ты сдохнешь. Потому что ты угробил Лисп для огромного количества людей. Ты даже не можешь напечатать «lambda»? Серьезно? Не верю.

И да, к слову об ABCL. Он уже есть и прекрасно работает на JVM. Нет никаких причин плодить еще один диалект.

anonymous
()
Ответ на: комментарий от monk

Попробуй, напиши на макросах C++:
чтобы во время компиляции это разворачиовалось в вызовы Gtk.
А на макросах Лиспа такое можно!

В этом нет необходимости. Для GTK+ существует GtkBuilder.

Вот в этом-то и есть основная разница между разработчиками и лисперами. Разработчик выбирает инструмент под задачу, а лиспер вприсядку велосипедит костыль на анафорических макросах, «потому что на макросах Лиспа такое можно».

anonymous
()
Ответ на: комментарий от anonymous

Компиляторы eDSL нужны и мейнстримны. Только к лишпику они никакого отношения не имеют, а пишутся на C++ template metaprogramming.

Ещё есть кошерный ANTLR (с поддержкой Java, C++ и C# в качестве таргетов), не говоря уже о flex и bison.

Короче, нормальных инструментов дофига. И да, лишпик тут никому нах не встрялся.

anonymous
()
Ответ на: комментарий от anonymous

«We would use it to create compilers for a wide range of data, including effects, animation, dialogue, sound, and gameplay scripting»

Условие 1. Last Of Us — игра исключительно для PS3.
Условие 2. PS3 — это процессор Cell и самописная ОС.
Условие 3. Racket поддерживается под Windows, Mac OS X и Linux на платформах Intel 32 и Intel 64.

Следствие 1. Racket не работает на PS3.
Следствие 2. Ни строчки на Racket в коде Last Of Us нет. Racket использовался исключительно для генерации бойлерплейта.

Что и требовалось доказать. Слив засчитан.

anonymous
()
Ответ на: комментарий от naryl

Кстати, если кто из анонимусов готов к нормальной дискуссии - прошу зарегистрироваться, т.к. анонимус у меня с форума Development вырезается. Весь. Очень много информационного шума от одного представителя было.

Ну да, разумеется, гораздо проще засунуть голову в песок и сделать вид, что в мире лишпика всё идеально и проблем нет. Какая удобная позиция.

Очень много информационного шума от одного представителя было.

Если для тебя аргументированная критика — «информационный шум», то, может, проблема в тебе?

anonymous
()
Ответ на: комментарий от anonymous

Ещё есть кошерный ANTLR (с поддержкой Java, C++ и C# в качестве таргетов), не говоря уже о flex и bison.

Это всё уже для полноценных standalone DSL, у которых, конечно же, практических применений намного больше чем у eDSL.

anonymous
()
Ответ на: комментарий от anonymous

Так-с, три предыдущих слива засчитываем.

Теперь повторяю в последний раз клинических дебилов: на Лиспе написан весь геймплей, вся анимация, все эффекты, весь звук и все диалоги.

anonymous
()
Ответ на: комментарий от anonymous

на Лиспе написан весь геймплей, вся анимация, все эффекты, весь звук и все диалоги.

Тогда, может, пояснишь, как это работает на PS3? Время пошло.

anonymous
()
Ответ на: комментарий от anonymous

Ты паталогически невменяемый. Повторю еще раз, для совсем уж рваных пердаков: на лишпике написаны тулзы для генерации некоторых из файлов для описания геймплея, анимации, эффектов, звука и диалогов. Самого лишпика в игре в рантайме нет и быть не может, и разработчики это подтверждают.

anonymous
()
Ответ на: комментарий от anonymous

Срочно сходи к врачу, у тебя серьезное психическое заболевание. В тех ссылках, что тут приводились, как раз и сказано, что на лишпике написаны утилитки для генерации всякого говна, а не само говно.

anonymous
()

Лол, эпично размазали борщевика-ракетчика. Озалуп прямо образцовый. Два арманьяка вам, канальи! Побольше бы таких анонимусов.

Кстати, тем, кто брызгал слюной, что, дескать, тут всего один анонимус — вы что, всерьез думаете, что на ЛОРе есть только один здравомыслящий лисп-скептик? По-моему, это оскорбительно для ЛОРа.

anonymous
()
Ответ на: комментарий от anonymous

Эту ламерскую чушь мы уже слышали - ламеры слились. Ссылки и цитаты, подтверждающие мои слова, смотри выше. Есть что обоснованное сказать, или тоже слив засчитываем?

anonymous
()
Ответ на: комментарий от anonymous

Вообще-то выше исключительно ссылки и цитаты, подтверждающие МОИ слова. Ты вообще читать не умеешь? Или читаешь вовсе не то, что написано?

anonymous
()
Ответ на: комментарий от anonymous

Т.е. ты так и не можешь объяснить, как написанный на Racket код работает на PS3?

Слив засчитан.

anonymous
()
Ответ на: комментарий от anonymous

Вообще-то выше исключительно ссылки и цитаты, подтверждающие МОИ слова.

Твои слова и пруфы рядом в студию.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.