LINUX.ORG.RU

Лисперы, что я делаю не так? - II


2

3

Я понял что я делал не так — я просто не использовал лисп.

Вощем, может кому полезно будет, человек пишет как дошел до жизни такой http://www.defmacro.org/ Честно говоря это мой уже не первый подход к снаряду. До этого раза поташнивало, сейчас думаю зашел. Действительно лисп оказался прост как грабли.

Без матов осознание того на сколько оно кульно описать тяжко.

Есть вопросы:

1) Кто-нибудь есть кто пользует vim, при этом пишет на лиспе?

2) Ясен хобот емакс мощнее, но как то оно не то. Есть кто пересел? Как ощущения вообще?

3) Practical Common Lisp ослилил. Что есть еще для просветления?

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

>(defmacro macro (test x) `(aif test it x))

лавсан, это ты так пишешь?

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

> он должен указать, что его макро «объявляет и использует» символ 'it, дабы вложенный в его макросы код не переопределял его «по ошибке»

а его макрос не определяет и не использует символ «it», его определяет и использует макрос aif. Вот в чем засада-то.

при том, что ты пытаешься гигиеной зафиксировать скоп, а возможность переопределить «всё и вся» в CL именуется «фичей», а не «багом», т.е. вопрос опять-же в «правильном использовании инструмента»

С гигиеной можно фиксировать скоп, а можно не фиксировать. Без гигиены фиксировать скоп нельзя. То есть ни о какой «фиче» тут речи нет, как минимум, речь идет об отсутствии «фичи». Является ли он фиксированным/не фиксированным по умолчанию - это вообще другой разговор, он к делу не относится. важно то, что в CL зафиксировать скоп нельзя в принципе. А значит невозможно написать целый класс макросов, который можно написать с гигиеной, те макросы, которые требуют фиксированного скопа.

т.е. вопрос опять-же в «правильном использовании инструмента»

Ок. Мы имеем инструмент - макросистема общелиспа. Правильное ее использование заключается в следующем: «нельзя использовать макрос, если не знаешь подробно детали его реализации и результат экспанда». Все верно? То есть, прежде чем использовать некоторый макрос следует прошерстить исходники (и исходники всех зависимостей, конечно же), чтобы проверить наличие всяких аифов. Мы ведь не станем полагаться на «мамой клянусь» человека, писавшего документацию к библиотеке? Нам ведь никто не гарантирует, что этот человек упомянет все подводные камни.

А вот это уже никоим хером не касается «правил использования инструмента». А то получается, что ты возмущаешься наличием 3-й педали в автомобиле с МКПП.

Сравнение некорректно. МКПП дает бОльшие возможности по управлению автомобилем по сравнению с автоматом. возможности же негигиенической макросистемы строго меньше, чем возможности гигиенической.

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

Некоторое пояснение - я говорю не про то, что гигиена должна быть обязательной, я говорю о том, что должна существовать возможность ее ввести. Вот в CL нет такой возможности. Следует ли делать гигиену по умолчанию - это уже в большей степени дело вкуса, мне больше нравится гигиена по умолчанию по двум причинам:

1. вводить гигигену надо чаше, чем выводить из-под нее => экономия.

2. если забыть ввести гигиену, получим непонятную ошибку в рантайме, если забыть вывести из-под гигиены - макрос просто не раскроется, сразу даст эррор => упрощение отладки.

но это уже, повторяю, дело вкуса, у кого-то может быть другой стиль программирования, для такого человека предпочтительно будет отсутствие гигиены по умолчанию. Претензии к CL в том, что ее вообще нет и ввести никак нельзя - вот была бы какая-нибудь форма, аналогичная defmacro, но в которой можно было бы перечислить символы, которые надо замкнуть на скоп определения макроса - и никаких проблем. Но этого нет.

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

>его макрос не определяет и не использует символ «it», его определяет и использует макрос aif...

...который ты «выставляешь наружу» - х... тот-же, вид «в профиль»

То есть ни о какой «фиче» тут речи нет, как минимум, речь идет об отсутствии «фичи».


это обратная сторона: возможность переопределить всё и вся не оставляет возможности зафиксировать «скоуп», кроме как передачи его отдельно

нельзя использовать макрос, если не знаешь подробно детали его реализации и результат экспанда


нет, нельзя использовать инструмент, не ознакомившись с документацией к нему

Мы ведь не станем полагаться на «мамой клянусь» человека, писавшего документацию к библиотеке?


чтоб ты всю жизнь использовал только либы без документации, или с неполной документацией, или с [преднамеренно]искажённой. И только закрытые - никаких исходников!

Сравнение некорректно. МКПП дает бОльшие возможности по управлению автомобилем по сравнению с автоматом.


МКПП на формуле? на большегрузах? на последних внедорожниках? ох lol!..

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

>Претензии к CL в том, что ее вообще нет и ввести никак нельзя - вот была бы какая-нибудь форма, аналогичная defmacro, но в которой можно было бы перечислить символы, которые надо замкнуть на скоп определения макроса - и никаких проблем.

мля!... т.е. конечная претензия таки к невозможности зафиксировать скоп, а не к отсутствию гигиены?

yyk ★★★★★
()

The main problem with Common Lisp's macro system (and with other define-macro systems) is that instead of syntax objects you're dealing with raw s-expressions. This becomes very ugly when using the macro in a different context than it was defined in: instead of dealing with identifiers, you're dealing with these plain data (called “symbols” in this case) that are essentially an identifier stripped of anything but their name, including the lexical scope for its source. In several define-macro systems this is the only difference from hygienic macros, but in the Common Lisp case this combines with its terrible module system (called “packages”) and lack of phasing (eval-when considered harmful to your mental health) to create a system which is only held together by duct tape and prayer.

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

мля!... т.е. конечная претензия таки к невозможности зафиксировать скоп, а не к отсутствию гигиены?

Гигиена именно за тем, чтобы можно было фиксировать скоп, и нужна. То есть фактически «возможность фиксации скопа» = «гигиена». r5rs:

All macros defined using the pattern language are ``hygienic" and ``referentially transparent" and thus preserve Scheme's lexical scoping

то есть макрос скопается как обычная ф-я, замыкаясь на скоп определения.

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

>Гигиена именно за тем, чтобы можно было фиксировать скоп, и нужна.

ну ок - гигиена в CL невозможна не из-за кривых макросов, а «по определению». Что на счёт «правильного использования инструмента»?

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

> ...который ты «выставляешь наружу» - х... тот-же, вид «в профиль»

Так в том все и дело! Я, когда пишу макрос macro, наружу этот it выставлять не хочу! Я хочу его только внутри macro использовать, и никакого введения биндингов семантика macro изначально не предполагает! Но CL мне не дает его «не выставить» наружу, мне придется, как минимум, переписать этот aif с блекджеком и шлюхами - сделать в нем явную передачу анафоры, например, и в макросе подставить туда генсим. После чего этот aif перестанет быть анафорическим, что характерно. То есть правило «не используйте анафорические макросы»?

это обратная сторона: возможность переопределить всё и вся не оставляет возможности зафиксировать «скоуп», кроме как передачи его отдельно

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

чтоб ты всю жизнь использовал только либы без документации, или с неполной документацией, или с [преднамеренно]искажённой. И только закрытые - никаких исходников!

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

нет, нельзя использовать инструмент, не ознакомившись с документацией к нему

с каких пор в доках описывают детали реализации?

МКПП на формуле? на большегрузах? на последних внедорожниках? ох lol!..

Это ты кривую аналогию придумал.

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

> ну ок - гигиена в CL невозможна не из-за кривых макросов, а «по определению».

Ну да, как раз по определению кривых общелисповых макросов она и невозможна.

Что на счёт «правильного использования инструмента»?

Ну правильно использование инструмента, в данном случае:

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

2. не писать анафорических макросов

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

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

Кстати, надо заметить, что проблема повторяет сравнения динамического/лексического скопинга. С гиигеной мы можем выбирать, какой скопинг хотим - лексический или динамический. если гигиены нет - то у нас есть только динамический и лексический мы использовать не можем. Если тут есть какие-то глубоко философские проблемы, связанные с «динамичностью» и «переопределением всего», то почему вообще в общелиспе не запретили лексический скопинг? Пусть был бы просто динамический, а?

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

Теперь кто-то третий использует библиотеку с макросом macro, сам aif он не использует (или даже использует - например? как-то так (aif test (macro (print it)))). Следуя твоей логике тот, кто делал макрос macro обязан в доках указать на то, что где-то там в недрах его макроса используется aif (потому что вдруг)? То есть для того, чтобы пользоваться макросом, необходимо знать детали его реализации и результат макроэкспанда? Хороший, годный подход.

Приведи код на схеме. С анафорическими if и макроэкспандом. Уж больно любопытно.

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

>Я, когда пишу макрос macro, наружу этот it выставлять не хочу!

его не ты, его aif выставляет. ну он так написан...

То есть правило «не используйте анафорические макросы»?


не используйте костыли, «биндящие» конкретные символы, а не результат генсим - правильно пользуйтесь инструментом

я легко могу вывести все тело макроса из-под гигиены, и в нем можно будет переопределять все и вся, ежели мне захочется


а если не захочется, то не выведешь, и я не смогу переопределить? Теперь читай ещё раз: в CL можно переопределить (почти) всё и вся, если ты специально не озаботился невозможностью сего через пэкеджи и проч. - но речь не об этом: локальный скоп можно переопределить полностью. Это «фича». Твои анафорические макросы - кривой костыль (для CL). Мы вернулись к правильному использованию инструмента...

в документации принято указывать, как работает макрос/функция, то есть семантика.


ну вот и указывай, что 'it тобою занят для «собственных нужд»

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

>Ну да, как раз по определению кривых общелисповых макросов она и невозможна.

ты вообще не можешь зафиксировать скоп (за редчайшим исключением - лучше не вспоминать), следовательно не можешь и макросами

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


это можно отнести к любому коду, «правильность» которого нельзя доказать «автоматически». А так, обычно, пока результат использования не противоречит документации, достаточно её.

зачем использовать такой странный инструмент, если есть другой, в котором больше возможностей


зачем использовать один инструмент вместо другого? инструменты разные и для разных задач. Если тебе без гигиены никак - используй схему - я не против. Если мне на гигиену насрать, но нужны возможности CL (или даже какой-то определённой реализации) - куда мне засунуть твои схемы с их гигиеной?

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

Красота-тред, один(!) гигиенический анонимус долбит в темечко ораву коммонлисперов. Причем, доводы и аргументы понятны любому, даже очень далёкому от лиспа, программисту. А ответные отмазки нелепы и совсем неубедительны. Браво! Мы с тобой.

Даже захотелось всерьез попользоваться схемой.

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

ты ещё доколупайся почему в CL call/сс нет

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

>Даже захотелось всерьез попользоваться схемой.

ха-ха, ещё один дебил выносит мнение из срача на лоре!... :D Позанимайся - я только за, может поумнеешь ;)

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

> Приведи код на схеме. С анафорическими if и макроэкспандом. Уж больно любопытно.

Ну например так:

[code] #lang racket (require syntax/parse/define) (provide aif)

(define-simple-macro (aif test then else) #:with it (datum->syntax #`aif `it) (let ([it test]) (if it then else))) [/code] [code] #lang racket (require «aif.rkt») (provide macro)

(define-syntax-rule (macro test x) (aif test it x)) [/code] [code] #lang racket (require «aif.rkt» «macro.rkt»)

(aif 10 (macro (> 1 2) (display it)) 15) [/code] выводит 10

вот экспанд: http://imageshack.us/photo/my-images/715/84994351.jpg/

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

aif.rkt:

#lang racket
(require syntax/parse/define)
(provide aif)

(define-simple-macro (aif test then else)
  #:with it (datum->syntax #`aif `it)
  (let ([it test])
    (if it then else)))
macro.rkt:
#lang racket
(require "aif.rkt")
(provide macro)

(define-syntax-rule (macro test x) (aif test it x))
test.rkt:
#lang racket
(require "aif.rkt"
         "macro.rkt")

(aif 10
     (macro (> 1 2) (display it))      
     15)
выводит 10

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

> его не ты, его aif выставляет. ну он так написан...

Я хочу сам решать, будут мои макросы что-то там вставлять или нет.

не используйте костыли, «биндящие» конкретные символы, а не результат генсим - правильно пользуйтесь инструментом

То есть таки анафорические макросы использовать нельзя - я верно понял?

а если не захочется, то не выведешь, и я не смогу переопределить?

Конечно. Ни разу об инкапсуляции не слыхал? Если я пишу макрос и говорю, что вот этот символ переопределять нельзя - значит нельзя. или, например, если я пишу класс и говорю, что это поле должно приватным - то оно должно быть приватным. И не тяни к нему свои шаловливые ручки.

Теперь читай ещё раз: в CL можно переопределить (почти) всё и вся

Почему я не могу переопределить переменную, на которая замкнута ф-я, но могу переопределить переменную в макросе? Другими словами - с какой стати ф-и скопаются лексически а макросы динамически? что за бред? Явно тут дело не в какой-то идеологической мишуре типа «все должно быть динамическим».

Это «фича».

Ты так и не объяснил, в чем заключается эта «фича». Что она дает? Она вводит лишние ограничения и делает невозможным написание ряда макросов - это мы уже выяснили. Что еще?

Твои анафорические макросы - кривой костыль (для CL).

Почему мои? традиционно как раз коммон лисперы надрачивают на анафоры :)

Мы вернулись к правильному использованию инструмента...

Ну так правильное - это какое? Два пункта (полностью разбираться в исходниках либ и не писать анафорических макросов) мы уже выяснили, еще что-то есть? Я так полагаю, следует быть последовательным и вообще отказаться от использования кода, написанного не самим собой. Так?

ну вот и указывай, что 'it тобою занят для «собственных нужд»

Я it не занимал и занимать не собирался. Его зачем-то занял aif.

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

> ты вообще не можешь зафиксировать скоп (за редчайшим исключением - лучше не вспоминать), следовательно не можешь и макросами

эгхм?

(let ((x 1)) (defun f () (incf x)))

а это что я сделал? «фиксированный скоп» - это просто-напросто лексический.

это можно отнести к любому коду, «правильность» которого нельзя доказать «автоматически».

То есть все-таки в данном случае введение биндинга в aif, когда он не предполагался - это ошибка. и значит вместо того, чтобы ее документировать (делать из ошибки «фичу») надо ее исправлять - так?

Если тебе без гигиены никак - используй схему - я не против. Если мне на гигиену насрать, но нужны возможности CL (или даже какой-то определённой реализации) - куда мне засунуть твои схемы с их гигиеной?

Давай так - мы говорим не о схеме или общелиспе, а об их макросистемах.

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

Да, это проблема в cl, и да, в рэките правильнее сделали. Но рэкит неудобный, громоздкий и неконсистентный, в отличии от cl. На последнем писать - одно удовольствие, на первом - просто ёбанный ад: тысячи функций-«однодневок», тысячи частных случаев, тонны мусора, многие из часто-используемых функций и макросов находятся чёрт-знает-где, в модулях с именами в стиле #%comp10core-x3o, slime нет, полезных метаданных нет, describe нет, вытащить имена аргументов функции, на которой сейчас стоит курсор можно только распарсив сорцы модуля и т.д.

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

> тысячи функций-«однодневок», тысячи частных случаев, тонны мусора, многие из часто-используемых функций и макросов находятся чёрт-знает-где, в модулях с именами в стиле #%comp10core-x3o, slime нет, полезных метаданных нет, describe нет, вытащить имена аргументов функции, на которой сейчас стоит курсор можно только распарсив сорцы модуля и т.д.

фантазии какие-то

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

Опровергни хотя-бы что-нибудь из этого:

slime нет, полезных метаданных нет, describe нет, вытащить имена аргументов функции, на которой сейчас стоит курсор можно только распарсив сорцы модуля

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

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

>Я хочу сам решать, будут мои макросы что-то там вставлять или нет.

Ты можешь хотеть всё что угодно. Но когда начинаешь делать - может ознакомишься с возможностями инструмента?

То есть таки анафорические макросы использовать нельзя - я верно понял?


можно, помня об 'it и предупреждая об этом пользователей твоих макр

Если я пишу макрос и говорю, что вот этот символ переопределять нельзя - значит нельзя. или, например, если я пишу класс и говорю, что это поле должно приватным - то оно должно быть приватным. И не тяни к нему свои шаловливые ручки.


А если ты _не можешь_ сказать, что символ переопределить нельзя, а поле нельзя сделать приватным? Ну инструменты такие...

Другими словами - с какой стати ф-и скопаются лексически а макросы динамически?


макросы возвращают обычный список - что ты в него вставишь, то и будет. Вставь локальные _значения_ (простых типов) - их и получишь. Вставь символы - получишь их значения из скопа вызова макроса. Это ПРОСТО. У схемы больше возможностей в этом плане? Возможно - я не отрицаю. Я не понимаю, почему ты от CL требуешь поведения схемы? Почему «макросы скопаются динамически»? Может кто-то долго ломал голову как это сделать - не знаю :) Но это естественным образом вытекает из принципа их работы. Из очень простого принципа.

Ты так и не объяснил, в чем заключается эта «фича».


Как ещё проще объяснить? Я уже теряюсь...

Почему мои? традиционно как раз коммон лисперы надрачивают на анафоры :)


ну они («коммон лисперы») все очень разные... Я надеюсь ты сейчас не «за всех» говрил? :)

Ну так правильное - это какое?


согласно документации...

Два пункта (полностью разбираться в исходниках либ и не писать анафорических макросов) мы уже выяснили


не-не-не, это ты сам тут кирпичную стенку выср... выложил, я не при чём

Я it не занимал и занимать не собирался. Его зачем-то занял aif.


ну вот aif такой кривой. не используй или используй другой aif с указанием какой символ забиндить и используй генсим, но не требуй от трактора умения летать и плавать...

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

> Опровергни хотя-бы что-нибудь из этого:

Ну вот эта часть чуть похожа на правду, а до этого были чистые фантазии.

slime нет

heiser например?

полезных метаданных нет

конкретнее?

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

Документация на ф-ю открывается по райтклику.

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

Ты можешь хотеть всё что угодно. Но когда начинаешь делать - может ознакомишься с возможностями инструмента?

Да, да, я уже понял, общелисп этого не умеет. Но зачем этот факт выдавать за «фичу»?

можно, помня об 'it и предупреждая об этом пользователей твоих макр

Которые в свою очередь должны предупреждать пользователей своих макр, которые в свою очередь... самому не смешно?

А если ты _не можешь_ сказать, что символ переопределить нельзя, а поле нельзя сделать приватным? Ну инструменты такие...

Ну кривые, значит, инструменты. Но, опять же, зачем это выдавать за фичу? Очевидный недостаток.

макросы возвращают обычный список

И это главный недостаток макросистемы. Вместо того, чтобы работать с АСТ, работают с его огрызком.

Я не понимаю, почему ты от CL требуешь поведения схемы?

Я не требую поведения схемы, я просто указываю на очевидные недостатки макросистемы CL. Если нет никакого способа ввести гигиену - это недостаток. Способы могут быть разные, не обязательно, как в схеме. но они быть должны. Иначе это не макросистема, а протухшее говно мамонта из 70-х годов.

Но это естественным образом вытекает из принципа их работы. Из очень простого принципа.

Ну так в схемке принцип не сложнее, просто надо понять, что там не списки, а синтаксические объекты и любой идентификатор имеет биндинг во время макроэкспанда. То есть пишешь ты х или #`x - это все трактуется как идентификатор с биндингами текущего лексического окружения, просто под #` это идентификатор не будет вычисляться.

Как ещё проще объяснить? Я уже теряюсь...

Я, может, неверно выразился. В чем профит этой «фичи»? То есть недостатки мы выяснили, теперь давай выясним, какова польза. Ну?

Я надеюсь ты сейчас не «за всех» говрил? :)

Конечно, не про всех :)

согласно документации...

Э... И где в доках CL описано, как его «правильно» использовать?

не-не-не, это ты сам тут кирпичную стенку выср... выложил, я не при чём

Стоп-стоп, разве не ты говорил о том, что анафорические макросы - это костыли, которые в CL не нужны и потом использовать их не надо? Что до чтения исходников - ну тут два варианта. Либо полагаемся на добропорядочность писавших либу, либо шерстим исходники. Но я, честно, не думаю, что кто-то заморачивается описанием в документации подобных моментов.

не используй или используй другой aif с указанием какой символ забиндить и используй генсим

Если там есть указание какой символ забиндить - макрос уже не анафорический. я потому и говорю - получается анафорические макросы не использовать :)

но не требуй от трактора умения летать и плавать...

А почему бы и нет? Вот другой трактор умеет. Почему в CL так не сделали?

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

>(let ((x 1)) (defun f () (incf x)))

обычное замыкание. Можешь налепить геттеров/сеттеров - получишь почти «объект». До самого x не добраться - хоть застрелись. Ты наружу выставил функцию, а не сам скоп с иксом.

То есть все-таки в данном случае введение биндинга в aif, когда он не предполагался - это ошибка. и значит вместо того, чтобы ее документировать (делать из ошибки «фичу») надо ее исправлять - так?


что ты там куришь?

мы говорим не о схеме или общелиспе, а об их макросистемах


давай. куда уж проще: вызов макроса в лиспе - это вызов макрофункции с передачей ей «отквоченных» параметров, которая возвращает список, которым и заменяется вызов макроса. Впихнуть в возвращаемый список _значения_ из локального скопа определения макроса - можешь. Сослаться непосредственно на скоп определения - нет. Налепить «геттеров/сеттеров» и загнать в возвращаемый список - да. Просто - до безобразия. Вот впереть в неё «автогигиену» - это получится уже не CL. Или опять будешь требовать «хочу как в схеме»?

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

обычное замыкание.

Ну да. Вот и в:

(define x 5)
(define-syntax-rule (macro) (display x))
macro - обычное замыкание.

Сослаться непосредственно на скоп определения - нет.

Да не хочу я никуда ссылаться, просто я хочу использовать идентификатор из скопа определения а не из скопа вызова.

Вот впереть в неё «автогигиену» - это получится уже не CL. Или опять будешь требовать «хочу как в схеме»?

Я уже об этом говорил. При чем тут «как в схеме»? Я только хочу, чтобы можно было контролировать в макросе скоп символа. Как это будет реализовано пофиг. В общелиспе это не реализовано никак - боженька нам дают скоп вызова и все тут. Вот и претензия исключительно к тому, что не реализовано никак.

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

>Но зачем этот факт выдавать за «фичу»?

ну если обозвать не фичей, а особенностью - тебе легче станет? :)

Которые в свою очередь должны предупреждать пользователей своих макр, которые в свою очередь... самому не смешно?


смешно - так нах писать такие кривые макросы?

Но, опять же, зачем это выдавать за фичу?


Опять... feature - особенность, что не так?

И это главный недостаток макросистемы.


кому как - это не схема, выяснили уже, не?

Иначе это не макросистема, а протухшее говно мамонта из 70-х годов.


Вы имеете право на «собственное IMHO» :)

То есть недостатки мы выяснили, теперь давай выясним, какова польза. Ну?


простота

разве не ты говорил о том, что анафорические макросы - это костыли, которые в CL не нужны и потом использовать их не надо?


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

Но я, честно, не думаю, что кто-то заморачивается описанием в документации подобных моментов.


да просто считается «моветоном» хардкодить «служебные имена»

я потому и говорю - получается анафорические макросы не использовать


угу, молотком шурупы не заворачивать - логично

Вот другой трактор умеет. Почему в CL так не сделали?


у другого трактора свои недостатки - выбирай наиболее подходящий

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

>macro - обычное замыкание.

да, но в let - лексическое, а с define какое - хз, давно схему не мучал...

Да не хочу я никуда ссылаться, просто я хочу использовать идентификатор из скопа определения а не из скопа вызова.


ссылка на идинтификатор локального скопа за пределами скопа не предусмотрена - аминь

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


ещё раз: при формировании результата работы макроса (списка) вставить в него значение (а не идентификатор) из локального скопа - можно. А идентификатор (а следовательно и сам скоп) - нельзя, ибо просто нельзя достучаться до чужого локального скопа. Вот такая «особенность», наравне с отсутствием call/cc

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

> ну если обозвать не фичей, а особенностью - тебе легче станет? :)

Особенностью, которая по совместительству является недостатком ;)

смешно - так нах писать такие кривые макросы?

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

кому как - это не схема, выяснили уже, не?

То, что это не схема - не недостаток. То, что нету средств контроля скопа символов в макросах - недостаток.

Вы имеете право на «собственное IMHO» :)

Ну это не мнение, это факт. Все годы развития макропрограммирования прошли мимо CL.

простота

То, что приходится следовать каким-то искусственным «правилам» и все время одергивать себя - не воткнул ли чего лишнего, это простота? Простота простоте рознь. Вот ассемблер - очень прост, проще любого высокоуровневого ЯП. Но на практике проще писать именно на высокоуровневых ЯП, чем на ассемблере. То есть эту «простоту» следует правильно назвать «примитивностью». Макросистема общелиспа не проста - она примитивна. Но ассемблер хотя бы дает больше контроля, чем высокоуровневый ЯП, а вот «особенности» макросистемы CL никаких возможностей не дают.

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

Это и есть определение анафорических макросов.

да просто считается «моветоном» хардкодить «служебные имена»

Ну так они могут быть не только служебными.

угу, молотком шурупы не заворачивать - логично

Так дело ведь не в том, что анафорические макросы плохи - они хороши и удобны. Проблема в том, что CL их не поддерживает :)

у другого трактора свои недостатки - выбирай наиболее подходящий

понимая под «трактором» макросистемы - какие недостатки у макросистемы Racket по сравнению с макросистемой CL?

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

> да, но в let - лексическое, а с define какое - хз, давно схему не мучал...

Ну такое же лексическое :) С точки зрения реализации - там некоторая разница в обработке виртуальной машиной таких замыканий есть, с точки зрения семантики - нет. Вообще, можно и с let пример повторить, но просто в схемке все локальные объявления (внутри let-формы) действительны исключительно в скопе этой формы, так что придется налепить костыль. В этом случае (если сделать замыкание с let) при вызове макроса вне let-контекста будет unbound variable (т.к. «х» вне let-a не определен).

ссылка на идинтификатор локального скопа за пределами скопа не предусмотрена - аминь

ну нам из локального и не надо на практике, обычно речь о скопе модуля.

Вот такая «особенность»

недостаток, недостаток :)

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

> То, что нету средств контроля скопа символов в макросах - недостаток.

Да нет же. Можно говорить о том, что отсутствие стандартизованных средств работы с лексическим окружением - это плохо. И это действительно может быть недостаток. Но только не макросов, а CL как такового.

анафорических макросов


Лично я такими вообще никогда не пользуюсь. И видел реально мало кода, где бы они использовались (вот в parenscript есть, недавно обнаружил). Я бы их вообще запретил.

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

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

> Просто пойми, что проблема не в макросах, а отсутствии стандартных удобных средств для работы с лексическим окружением.

Так дело в том, что их нет в силу особенностей макросистемы. То есть вот возьмем те же паттерны - их можно без проблем в CL сделать. А гигиену нормально не сделаешь никак. Там экспандер переписывать надо, это как минимум. То есть поинт не в том, что таких средств нет, а в том, что нету никакой возможности эти средства реализовать.

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

> Лично я такими вообще никогда не пользуюсь. И видел реально мало кода, где бы они использовались (вот в parenscript есть, недавно обнаружил). Я бы их вообще запретил.

Ну ты бы вообще макросы запретил :) тут вообще дело даже не в самих анафорических макросах типа aif, а вообще в этом приеме - вводим некоторую лексическую единицу и контролируем ее значение при помощи окружающего контекста. Естественно, если нету способа сделать такое надежно и безопасно - лучше даже не рыпаться, потому что это сразу превратится в неподдерживаемое говно.

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

> Ну ты бы вообще макросы запретил :)

Да нет же, я использую достаточно широко, просто я против раздувания роли макросов. Я ещё сильно против проектов типа dwim.hu. С макросами в CL, как и везде, нужна мера.

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

> С макросами в CL, как и везде, нужна мера.

Зависит от стиля программирования. Ну и возможностей макросистемы, конечно.

Я ещё сильно против проектов типа dwim.hu.

А чего там не так?

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

>То, что нету средств контроля скопа символов в макросах - недостаток.

его вообще нет в CL, поэтому нет и в макросах - ну сколько можно повторять

Все годы развития макропрограммирования прошли мимо CL.


...в результате получилась схема :) А без глобальной переделки всего CL не добиться того, что ты хочешь

Макросистема общелиспа не проста - она примитивна.


согласен

«особенности» макросистемы CL никаких возможностей не дают


они не дают ничего, чего не мог бы CL. Доступа к именам локального скопа за пределами скопа нет в CL, это ограничение не маросистемы, а самого CL. Но мало-ли где чего нет...

Это и есть определение анафорических макросов.


Что делать со вложенными «анафориками»? Как разделять «где чей it»? Большинство макросов в CL вида (foo (bar body) bla-bla-bla... `(... ,body)) Во что превратиться код, в котором в результате будет несколько вложенных «анафориков» - я не могу себе представить

Так дело ведь не в том, что анафорические макросы плохи - они хороши и удобны.


они хороши и удобны в самых примитивных случаях - иначе ад будет пострашнее ,@,,@,@@

Проблема в том, что CL их не поддерживает :)


Если принять ограничения на использование - то кое как можно пользоваться

какие недостатки у макросистемы Racket по сравнению с макросистемой CL?


субъективно - мне проще писать/читать `,@, нежели пачку функций, преобразующих datum<->syntax, и мне больше нравится самому контролировать - где предварительная обработка данных, а где ` - формирование выходного списка

объективно - макросистема прибита к Racket, и не учитывать недостатки (или отсутствие определённых фич) Racket при оценке макросистемы у меня не получается

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

>ну нам из локального и не надо на практике, обычно речь о скопе модуля.

«кучеряво девки пляшут...» Т.е. мы не о локальном скопе, а о скопе модуля... Что мешает писать foo:bar?

недостаток, недостаток :)


я уж почти согласился, но оказывается, что мы играли не по тем нотам... Пошли на следующий круг :)

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

> Так дело в том, что их нет в силу особенностей макросистемы.

Да каких особенностей? Ведь макросистема в CL это просто функции, которые вызываются на этапе компиляции и результат просто подставляется в место вызова макроса. Это довольно удобно для всяких кодевалкеров, а ещё это предельно просто для понимания и реализации. Эта простота даёт возможность «последующим поколениям» строить любые навороты вокруг этого. Например, взять и определить новый макрос define-syntax-rule, который бы обеспечивал гигиену и всё такое. Это было бы очень в стиле CL. Т.е. по хорошему define-syntax-rule должно определяться на уровне библиотеки. Но вот, загвоздка, для этого нужна средства для работы с лексическим окружением, а их нет.

А почему нет? Ну наверное в 94 году это не казалось актуальным, а может оставили для следующего стандарта, тока вот деньги кончились и стандарта нового уже не будет. А при этом у нас есть множество различных реализаций, которые за пределами стандарта плохо между собой совместимы.

Т.е. макросы в том виде, в котором они есть в CL - это хороший и годный низкоуровневый инструмент. Построить на его базе новые, более высокоуровневые инструменты сейчас не представляется особо реалистичным из-за того, что стандарт не предусматривает соответствующих средств. Вот может как-нибудь сообщество CL как-нибудь вдохновится примером Racet, объявит, например, что SBCL это не реализация, а такой новый язык программирования и введёт в него необходимые средства. Но пока этого не произошло приходиться довольствоваться тем, что есть. Но нельзя изменить изначальные CL-овские макросы, без изменения дизайна всего языка. Но ведь язык это не только макросы, это намного больше. И нельзя рассматривать одну из подсистем языка без учёта общего дизайна.

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

> его вообще нет в CL

Ну вот и плохо.

они не дают ничего, чего не мог бы CL. Доступа к именам локального скопа за пределами скопа нет в CL, это ограничение не маросистемы, а самого CL. Но мало-ли где чего нет...

Да не бывает никакого такого «доступа» :) Короче, реализуется это так - когда синтаксический объект (форма вызова макроса целиком) идет на вход макроса, на этот объект и его подобъекты навешивается уникальная syntax mark (на каждый вызов каждого макроса генерируется своя). Потом та же марка навешивается на объект, который возвращается из макроса (и его подобъекты), 2 одинаковые марки взаимно уничтожаются в результате для тех символов, что пришли к макросу на вход ничего не меняется, а вот те символы, которые изнутри макроса появились - на них 1 марка остается (которая клеится на выходе), потому что на входе марку на них не вешали. В результате там обычный лексический скоп, просто за счет этих марок получается гибкий шадовинг - символы считаются bounded только тогда, когда биндинги появились _до_ наложения различающихся марок (то есть марки во время появления биндинга должны совпадать). В результате символы с разными марками «как бы» разные. Чтобы вывести из-под гигиены символ - достаточно руками эту марку наложить: (syntax-local-introduce #`sym). И никаких там чудесных «доступов» на самом деле нет, все элементарно.

Что делать со вложенными «анафориками»? Как разделять «где чей it»?

В CL? не знаю :)

они хороши и удобны в самых примитивных случаях - иначе ад будет пострашнее ,@,,@,@@

Ну да. Вообще это делается так - вводим какую-то анафору, потом вводим ряд форм, которые внутри себя ее переопределяют. А дальше начинается самое веселое - делаем сами эти формы такими же анафорами, т.о. то, как они переопределят первую, зависит от их контекста. Как такое писать в CL (учитывая, что все формы могут быть вложены друг в друга, находиться в макросах и т.п.) - я без понятия, по-моему, это вообще нереально. По-этому гигиена и нужна - когда она есть об этом просто вообще не надо думать, все работает само по себе. С тем «чей it» - классический вариант, он принадлежит ближайшей явно введенной форме (ну как мой пример aif), то есть если макрос в эту форму раскрывается, то он игнорируется (если только семантикой этого макроса явно не предполагается иного).

субъективно - мне проще писать/читать `,@, нежели пачку функций, преобразующих datum<->syntax

Ну так не надо путать, datum<->syntax вобщем-то ортогонален `,@,, все, что делается в общемакросах при помощи `,`,@ и явных ф-й над списками в схемке делается на паттернах.

мне больше нравится самому контролировать - где предварительная обработка данных, а где ` - формирование выходного списка

Ну так а в чем проблема? Контролируй. но вообще паттерны удобны тем, что можно выполнять два правила:

1. всегда писать наиболее подробные паттерны

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

Благодаря первому достаточно беглого взгляда на паттерн, чтобы понять, как макрос вызывается (и не надо гоадать, что это за rest и как должны выглядеть элементы этого rest'a - все сразу видно из паттерна), благодаря второму - достаточно такого же беглого взгляда, чтобы понять, как он раскрывается - не надо разбираться в логике работы всяких лупов map filter etc.

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

> «кучеряво девки пляшут...» Т.е. мы не о локальном скопе, а о скопе модуля... Что мешает писать foo:bar?

Ну, во-первых - неудобно везде это писать :) Во-вторых - многие вещи это все равно не покрывает, например те же macro-generated макросы, которые часто будут определяться именно внутри локального контекста. То есть в схемке на самом деле что скоп модуля, что локальный - все едино, главное, чтобы он был уровнем выше, тогда мы можем обратиться к нему из нижнего уровня, а гигиена зашадовит все, как надо. А вот в CL с топ-левелом все какбудто хорошо, но только завернем это дело в let/flet и понеслась.

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

> Да каких особенностей?

Ок, в силу представления АСТ, который выглядит просто списком, и в силу того, что экспандер не контролирует лексическую структуру программы.

Т.е. по хорошему define-syntax-rule должно определяться на уровне библиотеки. Но вот, загвоздка, для этого нужна средства для работы с лексическим окружением, а их нет.

Ну вот именно.

Но нельзя изменить изначальные CL-овские макросы, без изменения дизайна всего языка.

Ну на самом деле можно. Семантика не поменяется, все средства из стандарта CL в рамках новой системы можно будет выразить. То есть я вобщем-то никаких проблем не вижу. Из той же racket легко можно было бы сделать макросы в точности как в CL, там единственная разница - фазы, из-за них не получится. Но речь не о фазах, фазы - это уже скорее к семантике рантайма, а не к макросам. То есть если в CL сделать из символов синтаксические объекты, сделать гигиену, ввести те же средства - и потом выразить через них defmacro, то, вобщем-то, ничего не изменится с точки зрения совместимости со стандартом.

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

> То есть если в CL сделать из символов синтаксические объекты,

сделать гигиену, ввести те же средства


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

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

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

В символах CL и так содержится до*уя информации, почему бы не добавить еще немного? Конкретно - лексическую информацию. Не понимаю, почему это какое-то «крушение основ», может ты пояснишь? Важно ведь, что все стандартные формы тоже останутся и с той же семантикой (то есть с таким символом можно все еще будет работать точно так же, как с обычным символом но + выполнять еще ряд вещей).

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

>С тем «чей it» - классический вариант, он принадлежит ближайшей явно введенной форме (ну как мой пример aif), то есть если макрос в эту форму раскрывается, то он игнорируется (если только семантикой этого макроса явно не предполагается иного).

ну вот ты написал свой макрос с использованием aif (не сказав мне про it), а-ля (define-syntax-rule (macro test body) (aif test (... body)...)), а я загнал его «внутрь» aifa: (aif test (macro it (bla-bla-bla... it))), я-ж буду «в святой уверенности», что оба моих it-а - это одно и то-же - твоя гигиена разберётся, что я хотел? :)

все, что делается в общемакросах при помощи `,`,@ и явных ф-й над списками в схемке делается на паттернах.


ты погодь, не так шибко - в CL на `,`,@ делается «вообще всё» - я-ж нагенерю спецсимволов из различных частей переданных мне символов и списков, понаопределяю отдельных частей кода из этих спецсимволов, а потом начну заниматься комбинаторикой этих частей... а часть этих спецсимволов надо будет ещё лишить... нет, не девственности - гигиены. У меня уже волосы дыбом встали...

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


«заранее подготовленные переменные» - это такая тривиальщина, что за написание из-за неё макр archimag оторвёт все конечности и то, что он за них примет...

достаточно такого же беглого взгляда, чтобы понять, как он раскрывается - не надо разбираться в логике работы всяких лупов map filter etc


не-не-не, если мне надо будет паттерном описывать итоговое выражение (все их варианты!), вместо пачки rest map filter `@,@@,, etc - никакой памяти не хватит...

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

открой для себя once-only, и не еби мозг

anonymous
()

Блядь, вот чем отличаются нормальные программисты от ебантропов?

Нормальный программист, если тащится от ЯП, говорит - вот, посмотрите, какой охуенный язык, я на нем такую-то хуевину вот нахуячил, и вот так-то просто это было, поэтому язык охуенный, потому что на нем охуенно писать программы.

А у ебантропов как?
«Посмотрите, там же МОНАДЫ! Это, блять, так круто что пиздец, или там, ЧИСТОТА, или, эта, как её. ТИПИЗАЦИЯ! Вот так то! Или - ГИГИЕНА! Или вот, ПРОДОЛЖЕНИЯ! Это же так круто, охуеть не встать. А вот у вас МОНАД нету, и ГИГИЕНА хуевая».
Спрашиваешь - ну и зачем тебе все это, как это программы то писать помогает, где твой код? И молчание. Зато, блядь, монады, конечно, и гигиена. Нахуя надо? Что дает? Нихуя не дает. Нахуй не надо. Но, блядь, круто же, да, охуеть круто пиздец.

Заебали.

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