Как зайти в Даркнет?!
25th January, 01:11
8
0
Как в tkinter из поля ввода Entry получить значение в одну переменную и обновить строку кнопкой, затем получить ещё одно введённое значение и затем сложить их. Ниже пример кода
21st July, 19:00
899
0
Программа, которая создает фейковые сервера в поиске игровых серверов CS 1.6 Steam
21st March, 17:43
952
0
Очень долго работает Update запрос Oracle
27th January, 09:58
916
0
не могу запустить сервер на tomcat HTTP Status 404 – Not Found
21st January, 18:02
907
0
Где можно найти фрилансера для выполнения поступающих задач, на постоянной основе?
2nd December, 09:48
942
0
Разработка мобильной кроссплатформенной военной игры
16th July, 17:57
1727
0
период по дням
25th October, 10:44
3957
0
Пишу скрипты для BAS только на запросах
16th September, 02:42
3722
0
Некорректный скрипт для закрытия блока
14th April, 18:33
4614
0
прокидывать exception в блоках try-catch JAVA
11th March, 21:11
4382
0
Помогите пожалуйста решить задачи
24th November, 23:53
6088
0
Не понимаю почему не открывается детальное описание продукта
11th November, 11:51
4352
0
Нужно решить задачу по программированию на массивы
27th October, 18:01
4400
0
Метода Крамера С++
23rd October, 11:55
4309
0
помогите решить задачу на C++
22nd October, 17:31
4002
0
Помогите решить задачу на python с codeforces
22nd October, 11:11
4492
0
Python с нуля: полное руководство для начинающих
18th June, 13:58
2599
0
Как далеко может зайти LISP macros?
Я много читал, что LISP может переопределить синтаксис на лету, предположительно с помощью macros. Мне интересно, как далеко это на самом деле заходит? Можно ли переопределить структуру языка настолько, чтобы он стал пограничным компилятором для другого языка? Например, не могли бы вы изменить функциональную природу LISP на более объектно-ориентированный синтаксис и семантику, скажем, приблизив синтаксис к чему-то вроде Ruby?
В частности, можно ли избавиться от скобки hell, используя macros? Я узнал достаточно (Emacs-)LISP, чтобы настроить Emacs с помощью моих собственных микро-функций, но мне очень любопытно, как далеко может зайти macros в настройке языка.
Это действительно хороший вопрос.
Я думаю, что это нюансы, но определенно можно ответить:
Macros не застревают в s-выражениях. Смотрите макрос LOOP для очень сложного языка, написанного с использованием ключевых слов (символов). Таким образом, хотя вы можете начинать и заканчивать цикл скобками, внутри него есть свой собственный синтаксис.
Пример:
(loop for x from 0 below 100
when (even x)
collect x)
При этом большинство простых macros просто используют s-выражения. И вы будете "stuck" использовать их.
Но с-выражения, как ответил Серхио, начинают казаться правильными. Синтаксис выходит из-под контроля, и вы начинаете кодировать в синтаксическом дереве.
Что касается reader macros, да, вы вполне могли бы написать что-то вроде этого:
#R{
ruby.code.goes.here
}
Но вам нужно будет написать свой собственный синтаксический анализатор Ruby.
Вы также можете имитировать некоторые из конструкций Ruby, например блоки, с помощью macros, которые компилируются в существующие конструкции Lisp.
#B(some lisp (code goes here))
бы перевести на
(lambda () (some lisp (code goes here)))
Смотрите эту страницу , чтобы узнать, как это сделать.
Да, вы можете переопределить синтаксис так, чтобы Lisp стал компилятором. Вы делаете это с помощью "Reader Macros,", которые отличаются от обычных "Compiler Macros", о которых вы, вероятно, думаете.
Common Lisp имеет встроенное средство для определения нового синтаксиса для читателя и reader macros для обработки этого синтаксиса. Эта обработка выполняется во время чтения (которое происходит перед компиляцией или эвал-временем). Чтобы узнать больше об определении reader macros в Common Lisp, см. раздел Common Lisp Hyperspec - вы захотите прочитать Ch. 2, "Syntax" и гл. 23, "Reader" . (Я полагаю, что Scheme имеет тот же самый объект, но я не так хорошо знаком с ним-см. источники схемы для языка программирования Arc ).
В качестве простого примера предположим, что вы хотите, чтобы Lisp использовал фигурные скобки, а не скобки. Для этого требуется что-то вроде следующих определений читателя:
;; { and } become list delimiters, along with ( and ).
(set-syntax-from-char #\{ #\( )
(defun lcurly-brace-reader (stream inchar) ; this was way too easy to do.
(declare (ignore inchar))
(read-delimited-list #\} stream t))
(set-macro-character #\{ #'lcurly-brace-reader)
(set-macro-character #\} (get-macro-character #\) ))
(set-syntax-from-char #\} #\) )
;; un-lisp -- make parens meaningless
(set-syntax-from-char #\) #\] ) ; ( and ) become normal braces
(set-syntax-from-char #\( #\[ )
Ты говоришь Lisp, что { как ( и } как ). Затем вы создаете функцию (lcurly-brace-reader), которую читатель будет вызывать всякий раз, когда он видит {, и вы используете set-macro-character , чтобы назначить эту функцию {. Затем вы говорите Lisp, что ( и ) похожи на [ и ] (то есть не имеют смысла синтаксис).
Другие вещи, которые вы могли бы сделать, включают, например, создание нового синтаксиса строки или использование [ and ] для включения нотации in-fix и обработки ее в S-выражения.
Вы также можете пойти далеко за пределы этого, переопределив весь синтаксис своими собственными макроссимволами, которые будут вызывать действия в читателе, так что небо действительно является пределом. Это лишь одна из причин, почему Пол Грэм и другие продолжают говорить, что Lisp-хороший язык для написания компилятора.
Я не специалист по Lisp, черт возьми, я даже не программист Lisp, но после небольшого эксперимента с языком я пришел к выводу, что через некоторое время скобки начинают становиться 'invisible', и вы начинаете видеть код таким, каким хотите его видеть. Вы начинаете уделять больше внимания синтаксическим конструкциям, которые вы создаете с помощью s-exprs и macros, и меньше внимания лексической форме текста списков и скобок.
Это особенно верно, если вы пользуетесь хорошим редактором, который помогает с отступом и синтаксической раскраской (попробуйте установить скобку в цвет, очень похожий на фон).
Возможно, вы не сможете полностью заменить язык и получить синтаксис 'Ruby', но вам это не нужно. Благодаря гибкости языка вы можете в конечном итоге иметь диалект, который чувствует, что вы следуете "стилю программирования Ruby", если хотите, что бы это ни значило для вас.
Я знаю, что это всего лишь эмпирическое наблюдение, но я думаю, что у меня был один из тех моментов просветления, когда я осознал это.
Снова и снова новички в Lisp хотят, чтобы "get rid of all the parenthesis." это продолжалось в течение нескольких недель. Ни один проект по созданию серьезного синтаксиса программирования общего назначения поверх обычного синтаксического анализатора S-expression никогда никуда не попадает, потому что программисты неизменно предпочитают то, что вы сейчас воспринимаете как "parenthesis hell.", к чему нужно немного привыкнуть, но не так уж много! Как только вы привыкнете к нему, и вы действительно сможете оценить пластичность синтаксиса по умолчанию, возвращение к языкам, где есть только один способ выразить какую-либо конкретную программную конструкцию, действительно раздражает.
Тем не менее, Lisp-отличный субстрат для построения предметно-ориентированных языков. Так же хорошо, как и XML, если не лучше.
Удачи вам!
Самое лучшее объяснение Lisp macros, которое я когда-либо видел, - это
https://www.youtube.com/watch?v=4NO83wZVT0A
начиная примерно с 55 минут. Это видео выступления Питера Зайбеля, автора книги "практическое общее Lisp", которая является лучшим учебником Lisp.
Мотивацию для Lisp macros обычно трудно объяснить, потому что они действительно вступают в свои права в ситуациях, которые слишком длинны, чтобы представить их в простом учебнике. Петр приводит замечательный пример; вы можете полностью понять его, и он делает хорошее, правильное использование Lisp macros.
Вы спросили:"не могли бы вы изменить функциональную природу LISP на более объектно-ориентированный синтаксис и семантику". Ответ-да. На самом деле, Lisp изначально вообще не имел никакого объектно-ориентированного программирования, что неудивительно, поскольку Lisp существует еще задолго до объектно-ориентированного программирования! Но когда мы впервые узнали о OOP в 1978 году, мы смогли легко добавить его к Lisp, используя, среди прочего, macros. В конце концов была разработана общая объектная система Lisp (CLOS), очень мощная объектно-ориентированная система программирования, которая элегантно вписывается в Lisp. Все это может быть загружено как расширение - ничего не встроено! Все это делается с помощью macros.
Lisp имеет совершенно другую функцию, называемую "reader macros", которая может быть использована для расширения поверхностного синтаксиса языка. Используя читателя macros, вы можете сделать подъязыков, которые C или Ruby-подобным синтаксисом. Они преобразуют текст в Lisp, внутренне. Они не используются широко большинством реальных программистов Lisp, главным образом потому, что трудно расширить интерактивную среду разработки, чтобы понять новый синтаксис. Например, команды отступа Emacs будут сбиты с толку новым синтаксисом. Однако если вы энергичны, Emacs тоже расширяется, и вы можете научить его своему новому лексическому синтаксису.
Регулярные macros работают со списками объектов. Чаще всего эти объекты представляют собой другие списки (образующие таким образом деревья) и символы, но они могут быть и другими объектами, такими как строки, хэш-таблицы, пользовательские объекты и т. д. Эти структуры называются s-exps .
Таким образом, когда вы загружаете исходный файл, ваш компилятор Lisp будет анализировать текст и производить s-exps. Macros действуйте на них. Это прекрасно работает, и это чудесный способ расширить язык в духе s-exps.
Кроме того, вышеупомянутый процесс синтаксического анализа может быть расширен через "reader macros", что позволит вам настроить способ, которым ваш компилятор превращает текст в s-exps. Я предлагаю, однако, чтобы вы приняли синтаксис Lisp вместо того, чтобы сгибать его во что-то другое.
Вы немного смущаетесь, когда упоминаете Lisp-е "functional nature" и Ruby-е "object-oriented syntax". Я не знаю, что такое "object-oriented syntax", но Lisp-это многопарадигмальный язык, и он очень хорошо поддерживает объектно-ориентированное программирование .
BTW, когда я говорю Lisp, я имею в виду обычный Lisp .
Я предлагаю вам отбросить свои предрассудки и дать Lisp честный ход .
Да, вы можете принципиально изменить синтаксис и даже escape "the parentheses hell". Для этого вам нужно будет определить новый синтаксис считывателя. Посмотри на читателя macros.
Однако я подозреваю, что для достижения уровня Lisp опыта программирования такого macros вам нужно будет погрузиться в язык до такой степени, что вы больше не будете рассматривать скобки "hell". I.e. к тому времени, когда вы научитесь избегать их, вы начнете воспринимать их как нечто хорошее.
смотрите этот пример того, как reader macros может расширить читателя lisp с помощью сложных задач, таких как XML templating:
http://common-lisp.net/project/cl-quasi-quote/present-class.html
эта пользовательская библиотека компилирует статические части XML в UTF-8 кодированных литеральных байтовых массивов во время компиляции, которые готовы быть записанными в сетевой поток. и они годны к употреблению в нормальном lisp macros, они ортогональны... расположение символа запятой влияет на то, какие части являются постоянными и какие должны быть оценены во время выполнения.
более подробная информация доступна по адресу: http://common-lisp.net/project/cl-quasi-quote/
еще один проект, который для общих расширений синтаксиса Lisp: http://common-lisp.net/project/cl-syntax-sugar/
Это очень сложный вопрос. Поскольку lisp уже структурно настолько близок к дереву синтаксического анализа, разница между большим количеством macros и реализацией вашего собственного мини-языка в генераторе синтаксического анализа не очень ясна. Но, за исключением открытия и закрытия парен, вы можете очень легко закончить с чем-то, что выглядит совсем не так, как lisp.
Одно из применений macros, которое поразило меня, было проверкой во время компиляции SQL запросов против DB.
Как только вы поймете, что у вас есть полный язык под рукой во время компиляции, это откроет новые интересные перспективы. Это также означает, что вы можете выстрелить себе в ногу новыми интересными способами (например, рендеринг компиляции не воспроизводится, что очень легко может превратиться в кошмар отладки).