Предыдущая страница Следующая страница [1] [2] > 3 < [4] [5] [6]

Автор Сообщение

misha

Moderators


Статус

1275 сообщений
http://racket-lang.org/
Где: Yemen
Род занятий:
Возраст:

#4493   2011-07-01 03:27 GMT+3 часа(ов)      
> В 2-3 раза разница, в данном случае это не много.
А у меня почти в 8 раз.

> А при чем тут +/- и т.д.? Смотрите выше пример с перекрытием переменной tmp.
У меня они являются операторами. Их можно перегружать!
Например,
> (infix: let ([+ string-append]) ("A" + " " + "B"))
"A B"

Вы же их рассматриваете как идентификаторы. Сточки зрения инфиксных операторов, к которым я привык, этот подход некорректен.

> Ваш пример вообще к делу отношения не имеет, что вы им хотели показать?
То что ваш код рассчитан на примитивы типа (infix 1 + 2 * n), а (infix let ([n 45]) (2 * n)) не обрабатывается. Т.к. экспанд у вас не предусмотрен.

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

> Там нет "чужих либ" - если таковой не считать стандартную библиотеку. Хотя, конечно, если предположить, что большую часть либ пишут так же как вы infix, то действительно стоит опасаться, а то мало ли что там унутре
Ну очень корректный код
(car (free-identifier-mapping-get infix-hash #`x (&&#35955; () #f)))


> Скажем так, ключевым плюсом Racket по отношению к другим фреймворкам.
А он для Схемы единственный фреймворк.

> Ну да. А что вас смущает.
См. выше.

misha

Moderators


Статус

1275 сообщений
http://racket-lang.org/
Где: Yemen
Род занятий:
Возраст:

#4494   2011-07-01 03:39 GMT+3 часа(ов)      
> Вы матчили списки, с таким же успехом можно было так же матчить синтаксические объекты (те же списки но с некоторым доп. набором информации)
В конце каждой syntax-case и др. присутствует макротрансформер, поэтому если бы вы добавили ручной экспанд, то ваш код стал бы как минимум в 5 раз задумчивее.

Kergan

Members


Статус

300 сообщений

Где: ---
Род занятий:
Возраст:

#4495   2011-07-01 04:36 GMT+3 часа(ов)      
Цитата
А у меня почти в 8 раз.

Как-то неправильно меряете. Вот аналог вашего кода:
 
(define-syntax (infix2 stx)
 
(define-syntax-class op
(pattern x:id
#:when (get-id-props #'x)
#:attr p (car (get-id-props #'x))))
 
(syntax-parse stx
[(_ e1 op1:op e2 op2:op e3 ...)
(if (>= (attribute op1.p) (attribute op2.p))
#`(infix2 (e1 op1 e2) op2 e3 ...)
#`(infix2 e1 op1 (e2 op2 e3 ...)))]
[(_ e1 op:op e2)
#`(op (infix2 e1) (infix2 e2))]
[(_ (e ...))
#`(infix2 e ...)]
[(_ e)
#`e]
[(_ e ...)
#`(e ...)]))
 

Разница в 2-3 раза.

Цитата
У меня они являются операторами. Их можно перегружать!

Да при чем тут +/-? Еще раз - смотрите пример с tmp, первый пункт. А вы говорите о втором. Второй пункт - это, вобщем-то, мелочь, зависит от семантики. Хотите - пусть перегружаются, хотите - не перегружаются, а вот то, что у вас нарушена гигиена и макрос использовать нельзя - вот это важно.

Цитата
То что ваш код рассчитан на примитивы типа (infix 1 + 2 * n), а (infix let ([n 45]) (2 * n)) не обрабатывается.

У меня обрабатывается любой код в любом контексте, о чем вы? Вот у вас, кстати, уже не будет работать (infix let ([n (45 * 2)]) (2 * n)).

Цитата
Мы с вами преследовали разные цели.

Ну, я преследовал цель показать, как следует писать простые, работающие макросы. Сразу пояснение - на мой взгляд, любой макрос либо работает, либо нет. Работает макрос тогда и только тогда, когда не бывает случая undefined behaivor - то есть никаких проблем с гигиеной, перекрытием биндингом, можно спокойно генерировать макрос из других макросов, использовать в произвольном контексте, делать local-expand - и все с гарантиями корректности. Если какая-то из упомянутых проблем есть - макрос не работает.

Цитата
Ну очень корректный код

Ааа, до меня дошло, наконец, о чем вы
Вы не обратили внимания, видимо, - этот код выполняется только для паттерна x:op - то есть х является оператором. А оператором он является только тогда, если мы уже проверили его наличие в таблице, так что исключения там быть не может.

> А он для Схемы единственный фреймворк.
Я имел в виду просто фреймворк, а не фреймворк для схемы.

Цитата
В конце каждой syntax-case и др. присутствует макротрансформер, поэтому если бы вы добавили ручной экспанд, то ваш код стал бы как минимум в 5 раз задумчивее.

Гм. Ну, во-превых, выбирая из работающего медленного и неработающего быстрого кода - очевидно, преимущество за первым вариантом
Толку от вашей скорости, если макрос работает с многочисленными ошибками и использовать его все равно нельзя? Это во-первых. Во-вторых - просадка по скорости минимальна, никаких 5 раз там нет. В-третьих - вы вообще о каком макротрансформере? почитайте уже мануал, налицо полное непонимание вами того, как в Racket работают макросы.

Kergan

Members


Статус

300 сообщений

Где: ---
Род занятий:
Возраст:

#4496   2011-07-01 04:51 GMT+3 часа(ов)      
Да, еще немаловажно, что мне не надо писать руками макрос infix - все работает автоматом, в любом точке программы. У меня там вообще еще карринг бинарных операций и автоматические лямбды в оригинале (только я этот кусок убрал из кода, чтобы не мешало), я это дело использую вот для таких вещей примерно:
 
(add1 $ * 2 $ 5) ; -> 11
 
(`(1 5 7 3 6 8) >> filter (5 <)
>> map $ add1 @ * 2) ; -> `(3 7)
 

отредактировал(а) Kergan: 2011-07-01 05:03 GMT+3 часа(ов)

misha

Moderators


Статус

1275 сообщений
http://racket-lang.org/
Где: Yemen
Род занятий:
Возраст:

#4497   2011-07-01 13:32 GMT+3 часа(ов)      
> Как-то неправильно меряете. Вот аналог вашего кода:
Прикалываетесь?

> Да при чем тут +/-? Еще раз - смотрите пример с tmp, первый пункт.
Вы снова о своем.

> Хотите - пусть перегружаются, хотите - не перегружаются, а вот то, что у вас нарушена гигиена и макрос использовать нельзя - вот это важно.
CL на вас нету

> У меня обрабатывается любой код в любом контексте, о чем вы? Вот у вас, кстати, уже не будет работать (infix let ([n (45 * 2)]) (2 * n)).
Исправил. А теперь и вы исправляйте. Почему внутри модуля я не могу использовать простейшие выражения типа (displayln (1 * 3 - 2))?

> Ну, я преследовал цель показать, как следует писать простые, работающие макросы.
Точнее как писать не переносимые(зависящие от реализации макросы). Переопределение #%app говорит, кстати, не в вашу пользу.

> Сразу пояснение - на мой взгляд, любой макрос либо работает, либо нет. Работает макрос тогда и только тогда, когда не бывает случая undefined behaivor - то есть никаких проблем с гигиеной, перекрытием биндингом, можно спокойно генерировать макрос из других макросов, использовать в произвольном контексте, делать local-expand - и все с гарантиями корректности. Если какая-то из упомянутых проблем есть - макрос не работает.
Каждый автор преследует свои цели. Хотите вы гигиены или нет - решать только вам.

> А оператором он является только тогда, если мы уже проверили его наличие в таблице, так что исключения там быть не может.
Копипаст рулит?

> Я имел в виду просто фреймворк, а не фреймворк для схемы.
Тогда что вы хотели этим сказать? Для CL достаточно хороших фреймворков.

> Гм. Ну, во-превых, выбирая из работающего медленного и неработающего быстрого кода - очевидно, преимущество за первым вариантом
Хватит ярлыки вешать. Я изначально писал не макрос, а транслятор, поэтому я его и назвал infix->sexp, а не infix language. При необходимости его можно доработать до чего угодно.

> Толку от вашей скорости, если макрос работает с многочисленными ошибками и использовать его все равно нельзя?
От вашего infix-language тоже никакого толка.

> Это во-первых. Во-вторых - просадка по скорости минимальна, никаких 5 раз там нет.
(define lst 
(do ([a '(0) `(1 + ,@a)]
[i 0 (add1 i)])
[(>= i 100) a]))
 
(define-namespace-anchor anchor)
 
(time (eval `(infix: ,@lst) (namespace-anchor->namespace anchor)))
;cpu time: 47 real time: 47 gc time: 0
(time (eval `(infix ,@lst) (namespace-anchor->namespace anchor)))
;cpu time: 8641 real time: 8657 gc time: 703

Более чем в 150 раз медленнее.

> В-третьих - вы вообще о каком макротрансформере? почитайте уже мануал, налицо полное непонимание вами того, как в Racket работают макросы.
apply-pattern-substitute - трансформирует синтаксический объект. В других реализациях присутствуют подобные трансформеры.

Kergan

Members


Статус

300 сообщений

Где: ---
Род занятий:
Возраст:

#4498   2011-07-01 14:57 GMT+3 часа(ов)      
Цитата
Прикалываетесь?

Нет, это действительно аналог вашего кода. Можете сами посмотреть и убедиться, что алгоритм матчинга совпадает.

Цитата
Вы снова о своем.

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

Цитата
CL на вас нету

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

Цитата
Исправил.

Что? Где?

Цитата
А теперь и вы исправляйте.

Что именно исправить?

Цитата
Почему внутри модуля я не могу использовать простейшие выражения типа (displayln (1 * 3 - 2))?

Почему не можете? Можете.

Цитата
Точнее как писать не переносимые(зависящие от реализации макросы).

От реализации чего, простите? Racket? Я знаю только одну реализацию Racket. Между чем и чем вы переносить собрались?

Цитата
Переопределение #%app говорит, кстати, не в вашу пользу.

#%app, если вы не знали, именно и введен для таких вещей - то есть чтобы можно было переопределять его в своих #lang-ах. Больше никакой функции он не выполняет.

Цитата
Каждый автор преследует свои цели. Хотите вы гигиены или нет - решать только вам.

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

Цитата
Копипаст рулит?

Какой копипаст? Наоборот же - у нас есть два синтаксических класса, в одном лежат операторы, в другом (параметризованном) операторы соответствующего приоритета. Очевидно, любой идентификатор из второго класса принадлежит первому - что мы и указываем декларативно в паттерне. _Избавляясь_ от копипаста, да, указать :op - это гораздо короче, чем лепить еще один free-identifier bla bla bla
Другое дело, что в данном случае без класса op можно обойтись - ну как я уже сказал, изначально у меня макрос был шире и там этот op использовался для реализации карринга. вот и остался он.

Цитата
Тогда что вы хотели этим сказать? Для CL достаточно хороших фреймворков.

Здесь "фреймворк" - всмысле программной платформы. Ну типа как .net или java.

Цитата
Хватит ярлыки вешать. Я изначально писал не макрос, а транслятор, поэтому я его и назвал infix->sexp, а не infix language.

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

Цитата
От вашего infix-language тоже никакого толка.

Толк обычный - удобство

Цитата
Более чем в 150 раз медленнее.

Еще раз - при сравнении парсинга синтаксических объектов с парсингом обычных списков разница в скорости 2-3 раза, вы сами можете сравнить скорость экспанда своего кода и предложенного мной аналога. Что у вас медленнее в 150 раз - мне вообще непонятно, просто в силу того, что вы не указали, что с чем сравниваете.

Цитата
apply-pattern-substitute - трансформирует синтаксический объект. В других реализациях присутствуют подобные трансформеры.

А, так вы про подстановку переменных в паттерн? Ну так вы не забывайте, что в вашем коде происходит точно такая же подстановка в паттерн. Только у вас, повторяю, матчатся списки, а у меня - синтаксические объекты. Скорость матчинга и подстановки фактически одинакова (syntax-object по сути тот же список), падение производительности идет в основном из-за дополнительной обработки (надо протаскивать лексический контекст, source location, применить марки и так далее). Отсюда и тот проигрыш в 2-3 раза.

Kergan

Members


Статус

300 сообщений

Где: ---
Род занятий:
Возраст:

#4499   2011-07-01 14:58 GMT+3 часа(ов)      
Кстати, в рамках оффтопика, вы использовали emacs + geiser?

misha

Moderators


Статус

1275 сообщений
http://racket-lang.org/
Где: Yemen
Род занятий:
Возраст:

#4500   2011-07-01 16:26 GMT+3 часа(ов)      
> Нет, это действительно аналог вашего кода. Можете сами посмотреть и убедиться, что алгоритм матчинга совпадает.
Зачем вы сравниваете аналог? (причем не точный)

> Ну макросистема CL вообще не предназначена для написания хоть сколько-нибудь сложных макросов - это факт общеизвестный, да. Отсутствие гигиены - как раз одна из главных причин. Вторая главная причина - необходимость писать кодеволкеры на каждый чих.
В большинстве случаев макросы предельно просты, поэтому gensym-а достаточно. А кодеволкеры должны присутствовать во всех реализациях DSL, да и проследить за работой сложного макроса во время отладки просто необходимо.

> Да ради бога, реализовали-то выего не в виде отдельной ф-и транслятора, а в виде макроса, что привело к ряду критических ошибок, на которые я и указал.
Ну, так он и был изначально реализован в виде функции. Мне просто захотелось её использовать как макрос.

> Толк обычный - удобство
Это с вашей точки зрения По мне так, если решили реализовать infix-language так идите до конца. А иначе какой толк от этой "надстройки".

> вы сами можете сравнить скорость экспанда своего кода и предложенного мной аналога.
А зачем?

> Что у вас медленнее в 150 раз - мне вообще непонятно, просто в силу того, что вы не указали, что с чем сравниваете.
Я сравнивал вашу изначальную реализацию и свою.

> Ну так вы не забывайте, что в вашем коде происходит точно такая же подстановка в паттерн.
Только в макросе, но так как он не рекурсивный, то её можно не учитывать.

> Скорость матчинга и подстановки фактически одинакова (syntax-object по сути тот же список), падение производительности идет в основном из-за дополнительной обработки (надо протаскивать лексический контекст, source location, применить марки и так далее). Отсюда и тот проигрыш в 2-3 раза.
Он гораздо больше.

отредактировал(а) misha: 2011-07-01 16:37 GMT+3 часа(ов)

misha

Moderators


Статус

1275 сообщений
http://racket-lang.org/
Где: Yemen
Род занятий:
Возраст:

#4501   2011-07-01 16:36 GMT+3 часа(ов)      
> Кстати, в рамках оффтопика, вы использовали emacs + geiser?
Я его использовал в линуксе, там проблем не возникло, но когда запустил DrRacket на XP, то туже получил странную ошибку при вычислении модуля с вашим языком, содержащего (displayln (1 * 3 - 2)).

misha

Moderators


Статус

1275 сообщений
http://racket-lang.org/
Где: Yemen
Род занятий:
Возраст:

#4502   2011-07-01 16:46 GMT+3 часа(ов)      
> От реализации чего, простите? Racket? Я знаю только одну реализацию Racket. Между чем и чем вы переносить собрались?
CL, r6rs.

> #%app, если вы не знали, именно и введен для таких вещей - то есть чтобы можно было переопределять его в своих #lang-ах. Больше никакой функции он не выполняет.
#%app может использоваться не только вами.

Kergan

Members


Статус

300 сообщений

Где: ---
Род занятий:
Возраст:

#4504   2011-07-02 09:26 GMT+3 часа(ов)      
Цитата
Зачем вы сравниваете аналог?

Мы хотели сравнить скоростью матчинга списков со скоростью матчинга syntax-object - логично сравнивать скорость работы аналогичных алгоритмов, нет? Или что по-вашему тогда следует с чем сравнивать?

Цитата
В большинстве случаев макросы предельно просты

Потому что для написания сложных макросов CL не предназначен.

Цитата
поэтому gensym-а достаточно.

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

Цитата
А кодеволкеры должны присутствовать во всех реализациях DSL,

Поправка - "кодеволкеры (низкоуровневые средства реализации дсл) нужны только тогда. когда отсутствуют высокоуровневые средства". Вот в CL высокоуровневых средств нет - приходится писать кодеволкеры, в результате чего получается всякое говно вроде, прости господи, loop. В Racket же я не представляю задачи, которая потребует написания кодеволкера. Даже Typed Racket реализован без него.

Цитата
да и проследить за работой сложного макроса во время отладки просто необходимо.

В syntax-parse вся обработка ошибок "вшита" автоматом. Была где-то статейка про реализацию loop на syntax-parse - руками (через #;fail-when) пришлось реализовывать менее 10% проверок (да и те выглядели гораздо лучше оригинальной реализации, т.к. были раскиданы по соответствующим синтаксическим классам), все остальное получилось "из коробки". Для отладки макросов есть такая замечательная вещь, как macro stepper - до которого, благодаря s-objects, любым cl-макро-дебаггерам как до Китая раком. Если же у вас что-то совсем нетривиальное - из макросов есть интерфейс к макростепперу. Так что следите хоть заследитесь

Цитата
По мне так, если решили реализовать infix-language так идите до конца. А иначе какой толк от этой "надстройки".

"до конца" - это что значит?

Цитата
А зачем?

Ну а что еще сравнивать?

Цитата
Я сравнивал вашу изначальную реализацию и свою.

А, ну там тоже разница далеко не 150, а где-то 20-30 раз. Но вообще какой смысл сравнивать реализацию _разных_ алгоритмов (тем более, что ваш некорректно обрабатывает приоритеты)? Это ничего не скажет о скорости работы матчинга.

Цитата
Только в макросе, но так как он не рекурсивный, то её можно не учитывать.


Вы, что, стебетесь что ли? Какая разница, где происходит матчинг - во время рекурсивного вызова или внутри функции? Как его можно не учитывать, если 90% времени макроэкспанда в обоих случаях и выполняется этот матчинг? Вообще:
 
(define-syntax (infix stx)
 
(define-syntax-class op
(pattern x:id
#:when (get-id-props #'x)
#:attr p (car (get-id-props #'x))))
 
(syntax-parse stx
[(_ e1 op1:op e2 op2:op e3 ...)
(if (>= (attribute op1.p) (attribute op2.p))
#`(infix (e1 op1 e2) op2 e3 ...)
#`(infix e1 op1 (e2 op2 e3 ...)))]
[(_ e1 op:op e2)
#`(op (infix e1) (infix e2))]
[(_ (e ...))
#`(infix e ...)]
[(_ e)
#`e]
[(_ e ...)
#`(e ...)]))
 
(define-for-syntax (i-helper stx)
 
(define-syntax-class op
(pattern x:id
#:when (get-id-props #'x)
#:attr p (car (get-id-props #'x))))
 
(syntax-parse stx
[(_ e1 op1:op e2 op2:op e3 ...)
(if (>= (attribute op1.p) (attribute op2.p))
(i-helper #`(infix (e1 op1 e2) op2 e3 ...))
(i-helper #`(infix e1 op1 (e2 op2 e3 ...))))]
[(_ e1 op:op e2)
(i-helper #`(op #,(i-helper #`(infix e1)) #,(i-helper #`(infix2 e2))))]
[(_ (e ...))
(i-helper #`(infix e ...))]
[(_ e)
#`e]
[(_ e ...)
#`(e ...)]))
 
(define-syntax (infix2 stx) (i-helper stx))
 

 
> (time (for ([i (in-range 1000)])
(expand #`(infix 1 * 2 + 3 * 4 + 5 * 6))))
cpu time: 1375 real time: 1501 gc time: 140
 
> (time (for ([i (in-range 1000)])
(expand #`(infix2 1 * 2 + 3 * 4 + 5 * 6))))
cpu time: 1047 real time: 1106 gc time: 79
 

Как видно, разница между рекурсивным макросом и рекурсивной функцией ~20%.
Ну и вот ваш инфикс за компанию:
 
> (time (for ([i (in-range 1000)])
(expand #`(infix: 1 * 2 + 3 * 4 + 5 * 6))))
cpu time: 328 real time: 344 gc time: 63
 


Цитата
Он гораздо больше.

Зачем вы врете?

Цитата
то туже получил странную ошибку при вычислении модуля с вашим языком, содержащего (displayln (1 * 3 - 2)).

Хм. Может я все-таки напортачил, когда переписал. Вот, поставьте исходные классы:
http://pastebin.com/kdnLG0f7
И добавьте две эти ф-и:
http://pastebin.com/xEjArBqV
Если опять выдаст ошибку - хоть скажите, какую.

А вообще вопрос касался запуска из-под geiser Gracket. Я просто сделал, чтобы по C-c <RET> C-e открывался макро-степпер с выделенным термом, но проблема в том, что в обычном racket (не gracket) ф-я expand/step почему-то при первом вызове ничего не делает (видимо, подгружается гуйня или еще что). В Gracket и Gracket-text, если запускать руками, все нормально, но из под geiser и в gracket остается то же самое. Оно конечно не проблема, но все равно интересно - почему.

Цитата
CL, r6rs.

Насколько я знаю, ни CL, ни r6rs не являются реализациями Racket. Да и вообще не являются реализациями чего бы то ни было. И ладно еще r6rs (все-таки это схема, на которую Racket очень похож), но "портирование из Racket в CL" звучит примерно как "портирование из c# в c". В том смысле, что общего между языка ровно столько же.

Цитата
#%app может использоваться не только вами.

конечно! В каждой #lang может быть свой собственный #%app. Более того - #%app вообще можно переопределять локально! А что вас в этом смущает?

Kergan

Members


Статус

300 сообщений

Где: ---
Род занятий:
Возраст:

#4505   2011-07-02 09:37 GMT+3 часа(ов)      
А вообще, спор о скорости выполнения макроэкспанда довольно-таки бессмысленен - ни рекурсивные макросы, ни матчинг s-objects на практике какого-то значимого падения поизводительности не дадут. А вот например такое:
 
(define-syntax (test stx)
#`(let-syntax ([foo (lambda (stx) body ...)])
body ...))
 

вместо:
 
(define-for-syntax (fun stx)
body ...)
 
(define-syntax (test stx)
#`(let-syntax ([foo fun])
body ...))
 

действительно может дать офигенную просадку. Так что не с тем вы боретесь

misha

Moderators


Статус

1275 сообщений
http://racket-lang.org/
Где: Yemen
Род занятий:
Возраст:

#4506   2011-07-02 13:27 GMT+3 часа(ов)      
Цитата
Мы хотели сравнить скоростью матчинга списков со скоростью матчинга syntax-object - логично сравнивать скорость работы аналогичных алгоритмов, нет? Или что по-вашему тогда следует с чем сравнивать?

Где тут логика? Сравнивать необходимо скорость работы алгоритмов при вычислении одинаковых, сравнительно больших объемов данных.

Цитата
Потому что для написания сложных макросов CL не предназначен.

Практики говорят об обратном.

Цитата
Гигиена не сводится к генсиму. То, что не нужно пользоваться генсимом - это лишь малая часть гигиены. Ее побочный эффект.

В большинстве случаев достаточно генсима.

Цитата
Поправка - "кодеволкеры (низкоуровневые средства реализации дсл) нужны только тогда. когда отсутствуют высокоуровневые средства". Вот в CL высокоуровневых средств нет - приходится писать кодеволкеры, в результате чего получается всякое говно вроде, прости господи, loop. В Racket же я не представляю задачи, которая потребует написания кодеволкера. Даже Typed Racket реализован без него.

1)Высокоуровневые средства обычно создают трудно читаемый код. "Вот в CL высокоуровневых средств нет" - типичная ошибка новичка. Большинство нормальных реализаций их предлагает, но у них таже проблема как и у Racket.
2)А что вы собственно реализовали(собираетесь реализовать) на Racket? Я думаю, не только мне это интересно. Имхо, нужна "централизация" всего, что уже на нем реализовано.

Цитата
"до конца" - это что значит?

Реализуйте полноценный диалект, например, с паскале подобным синтаксисом.

Цитата
А, ну там тоже разница далеко не 150, а где-то 20-30 раз. Но вообще какой смысл сравнивать реализацию _разных_ алгоритмов (тем более, что ваш некорректно обрабатывает приоритеты)? Это ничего не скажет о скорости работы матчинга.

1) Укажите код, который он некорректно обрабатывает. Я же вам указал на проблему, а вы зачем-то скрываете.
2) У меня как раз на тестах разница более чем в 150 раз. Как вы тестировали? Укажите характеристики процессора.

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

1) Я о матчинге в макросах, там приходит подстановка с последующей трансформацией результата. О каком именно макроэкспанде идет речь, внутреннем(внутри функции) или внешнем?
2) Проблема вашего алгоритма в том, чем длиннее обрабатываемый "список", тем чаще происходит вызов apply-pattern-substitute.

Цитата
Насколько я знаю, ни CL, ни r6rs не являются реализациями Racket. Да и вообще не являются реализациями чего бы то ни было. И ладно еще r6rs (все-таки это схема, на которую Racket очень похож), но "портирование из Racket в CL" звучит примерно как "портирование из c# в c". В том смысле, что общего между языка ровно столько же.

А вот я не вижу проблем

Цитата
конечно! В каждой #lang может быть свой собственный #%app. Более того - #%app вообще можно переопределять локально! А что вас в этом смущает?

А вы подводных камней не видите?

Цитата
действительно может дать офигенную просадку. Так что не с тем вы боретесь

Так не об этом шла речь

misha

Moderators


Статус

1275 сообщений
http://racket-lang.org/
Где: Yemen
Род занятий:
Возраст:

#4507   2011-07-02 13:47 GMT+3 часа(ов)      
> Если опять выдаст ошибку - хоть скажите, какую.
Лучше представьте полный исходник.

Kergan

Members


Статус

300 сообщений

Где: ---
Род занятий:
Возраст:

#4508   2011-07-02 16:30 GMT+3 часа(ов)      
Цитата
Где тут логика? Сравнивать необходимо скорость работы алгоритмов при вычислении одинаковых, сравнительно больших объемов данных.

Так я о том вам и говорю. Оригинальный мой вариант работает совершенно по другому алгоритму с другой сложностью, по-этому я и переписал ваш алгоритм матчинга, но для syntax-objects. Разница в работе одинаковых алгоритмов ~3 раза, как видно.

Цитата
Практики говорят об обратном.

Практики не пишут на CL сложные макросы
А когда пишут - получаются всякие loop.

Цитата
В большинстве случаев достаточно генсима.

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

Цитата
1)Высокоуровневые средства обычно создают трудно читаемый код.

Наоборот. Можете, кстати, сами сравнить две свои реализации инфикса - для r5rs и для Racket, где вы, почему-то, не погнушались вместо низкоуровневых car/cdr использовать высокоуровневый match

Цитата
"Вот в CL высокоуровневых средств нет" - типичная ошибка новичка. Большинство нормальных реализаций их предлагает

Вот если бы для CL существовали бы высокоуровневые средства макропрограммирования - вы бы мне их назвали и сразу, тем самым, утерли мне нос. Вместо этого вы занимаетесь пустобрехством, и если я вас попрошу эти средства назвать - вы уйдете от ответа. Потому что назвать вам нечего
Главная проблема макросистемы CL в том, что, макрос работает со списками вместо синтаксических объектов (ничего нового за последние 30 лет, ага). По-этому _поверх_ нее по-просту невозможно реализовать ничего высокоуровневого. Для начала вам потребуется переписать ридер, потом экспандер - ну а потом уже вы можете взяться за реализацию аналога syntax-parse, введение гигиены и других средств, необходимых для нормального метапрограммирования.

Цитата
Реализуйте полноценный диалект, например, с паскале подобным синтаксисом.

Эээ... зачем? И для этого придется ридер переписывать, нафига оно надо?

Цитата
1) Укажите код, который он некорректно обрабатывает.

Я же написал уже (infix: 1 + 2 * 4 < 3). Должно получаться:
(< (+ 1 (* 2 4)) 3) (в соответствии с выставленными приоритетами), а у вас там получается белиберда. Там очевидная ошибка в алгоритме, ее сразу видно.

Цитата
Я же вам указал на проблему, а вы зачем-то скрываете.

на какую?

Цитата
2) У меня как раз на тестах разница более чем в 150 раз.

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

Цитата
Как вы тестировали?

Запускал в Dr.Racket, код я привел. Сами (time ...) пускались из репла.

Цитата
Я о матчинге в макросах, там приходит подстановка с последующей трансформацией результата.

У вас в ф-и match тоже происходит подстановка с последующей трансформацией результата. ТОЧНО ТАКАЯ ЖЕ.

Цитата
1) О каком именно макроэкспанде идет речь, внутреннем(внутри функции) или внешнем?

Какая разница? Это одно и то же.

Цитата
2) Проблема вашего алгоритма в том, чем длиннее обрабатываемый "список", тем чаще происходит вызов apply-pattern-substitute.

У вас в match - тоже. Вы, кажется, абсолютно не понимаете, как вообще работают все эти формы вроде syntax-rules. Вот смотрите, есть у вас ф-я match - это макрос, который потом раскрывается в код, который представляет последовательность функций вроде cdr/list/null?/atom?/cons/etc. Теперь определим аналогичные ф-и на синтаксических объектах:
(define (syntax-car stx) (car (syntax-e stx)))
(define (syntax-cdr stx) (datum->syntax stx (cdr (syntax-e stx))))
(define (syntax-list?) (list? (syntax-e stx)))
ну и так далее. Теперь определим макрос syntax-match, который работает ТАК ЖЕ КАК match, но только вместо ф-й над списками использует syntax-аналоги. Так вот это и будет наш syntax-case/syntax-rules/syntax-parse. Все. Весь оверхед при работе с syntax-object - это вот как раз и есть те добавленные syntax->datum, datum->syntax, syntax-e, etc., больше никакого оверхеда нету, в макросе делается все то же самое, что и внутри ф-и матч. причем эти добавленные ф-и работают достаточно быстро - та же syntax-e - это просто операция доступа к полю структуры, например.

Цитата
А вот я не вижу проблем

Представил себе того бедного человека, который, портируя софтину с c# на с, наткнулся на использование linq-выражений. От такого ведь и повеситься можно

Цитата
А вы подводных камней не видите?

Давайте так - раз вы абсолютно не понимаете, как оно все работает, вы просто назовете свои предполагаемые подводные камни, а я объясню, почему они ими не являются. Ок?

Цитата
Так не об этом шла речь

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

Кстати, вот еще смотрите, как забавно навернется ваш макрос:
 
(module m racket
(require "infix.rkt")
(provide my-macro)
 
(define-syntax-rule (my-macro x)
(infix: x + x)))
 
 
(module m2 racket
(require 'm)
(define f add1)
(my-macro (f 4)) ; reference to an identifier before its definition: f
)


Цитата
Лучше представьте полный исходник.

Нет, ну могли бы уж написать в чем ошибка
Вот, переписал грамматику, теперь работает за линейное время:
http://pastebin.com/smJ6siiB

отредактировал(а) Kergan: 2011-07-02 16:54 GMT+3 часа(ов)

misha

Moderators


Статус

1275 сообщений
http://racket-lang.org/
Где: Yemen
Род занятий:
Возраст:

#4510   2011-07-03 17:46 GMT+3 часа(ов)      
Цитата
Так я о том вам и говорю. Оригинальный мой вариант работает совершенно по другому алгоритму с другой сложностью, по-этому я и переписал ваш алгоритм матчинга, но для syntax-objects. Разница в работе одинаковых алгоритмов ~3 раза, как видно.

Так я же оценивал не сложность, а скорость обработки данных.
Цитата
Практики не пишут на CL сложные макросы
А когда пишут - получаются всякие loop.

Как раз loop является полезным макросом. Вы лучше посмотрите на сырца большинства пакетов, почти везде используется with-gensyms и т.п. как альтернатива гигиены. Хотя для CL существуют подобия difine-syntax, syntax-rules, let-syntax, но они используются крайне редко(если вообще используются).
Цитата
Наоборот. Можете, кстати, сами сравнить две свои реализации инфикса - для r5rs и для Racket, где вы, почему-то, не погнушались вместо низкоуровневых car/cdr использовать высокоуровневый match

Вы мне предлагаете вручную реализовать конечный автомат? Что это даст?
Цитата
Вот если бы для CL существовали бы высокоуровневые средства макропрограммирования - вы бы мне их назвали и сразу, тем самым, утерли мне нос. Вместо этого вы занимаетесь пустобрехством, и если я вас попрошу эти средства назвать - вы уйдете от ответа. Потому что назвать вам нечего

В них нет особой необходимости, т.к. нет синтаксического объекта, да и environment не подвергся стандартизации.
Цитата
Для начала вам потребуется переписать ридер, потом экспандер - ну а потом уже вы можете взяться за реализацию аналога syntax-parse, введение гигиены и других средств, необходимых для нормального метапрограммирования.

А лисперы, однако, молчат
Цитата
Эээ... зачем? И для этого придется ридер переписывать, нафига оно надо?

А зачем кому-то недодиалект? Разве что для маленьких модулей сойдет.
Цитата
Я же написал уже (infix: 1 + 2 * 4 < 3). Должно получаться:
(< (+ 1 (* 2 4)) 3) (в соответствии с выставленными приоритетами), а у вас там получается белиберда. Там очевидная ошибка в алгоритме, ее сразу видно.

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

Это единственный способ получить чистый результат.
Цитата
Запускал в Dr.Racket, код я привел. Сами (time ...) пускались из репла.

Сборку мусора проводили после каждого теста?
Цитата
Какая разница? Это одно и то же.

Тогда шла речь о вашем тесте с аналогом моего кода? Сдается мне я вас ранее не понял.
Цитата
У вас в match - тоже. Вы, кажется, абсолютно не понимаете, как вообще работают все эти формы вроде syntax-rules.


Да знаю я, как они работают. Гигиена требует трансформации конечного синтаксического объекта.
Например,
(syntax-case stx ()
[(_ a b)
#'(list a b)])

Если есть соответствие, тогда необходимо в #'(list a b) подставить переменные a и b. Т.к. синтаксический объект содержит АСД, по сути требуется подстановка в список.
А match устроен проще, там переменные даже подставлять не нужно, они автоматически попадают в область видимости выражения.

misha

Moderators


Статус

1275 сообщений
http://racket-lang.org/
Где: Yemen
Род занятий:
Возраст:

#4511   2011-07-03 18:28 GMT+3 часа(ов)      
Цитата
Давайте так - раз вы абсолютно не понимаете, как оно все работает, вы просто назовете свои предполагаемые подводные камни, а я объясню, почему они ими не являются. Ок?

Вы привязаны к #%app. Лучше перегрузите, например, фигурные скобки.
Цитата
Кстати, вот еще смотрите, как забавно навернется ваш макрос:

Вы его неправильно используете.
(module m racket
(require "infix-to-sexp.scm")
(provide my-macro infix:)
(define-syntax (my-macro s)
(syntax-case s ()
[(_ x)
(datum->syntax s (syntax->datum #'(infix: x + x)))])))
 
(module m2 racket
(require 'm)
(define f add1)
(my-macro [ #t ? f([1]) : 0]))

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

(1 + 2 * (3 - 4)) возвращает при запуске модуля в DrRacket
module-path-index-resolve: "self" index has no resolution: #<module-path-index>
(1 + 3 > (2 + 3)) - вообще не работает.

Kergan

Members


Статус

300 сообщений

Где: ---
Род занятий:
Возраст:

#4512   2011-07-03 19:28 GMT+3 часа(ов)      
Цитата
Так я же оценивал не сложность, а скорость обработки данных.

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

Цитата
Как раз loop является полезным макросом.

Он, конечно, полезен, вот только глючный, кривой, и реализация значительно переусложнена. А все - потому что кодеволкер. Без кодеволкера реализация loop будет впятеро короче, понятнее, причем еще и без глюков.

Цитата
почти везде используется with-gensyms и т.п. как альтернатива гигиены.

Не понял, какая связь у генсима и гигиены? И как with-gensyms может быть альтернативой гигиены? Гигиена - это замыкание используемых в макросе символов на область определения макроса. with-gensym делает это? Нет. В CL вообще невозможно реализовать подобное (без переписывания ридера и экспандер).

Цитата
Хотя для CL существуют подобия difine-syntax, syntax-rules, let-syntax

Вот именно, что "подобия" - ключевые особенности реальных define-syntax/rules/case в них не реализованы.

Цитата
Вы мне предлагаете вручную реализовать конечный автомат? Что это даст?

Легко читаемый код. Вы же сами сказали, что чем более высокоуровневые средства - тем более код трудночитаем.

Цитата
В них нет особой необходимости, т.к. нет синтаксического объекта, да и environment не подвергся стандартизации.

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

Цитата
А лисперы, однако, молчат

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

Цитата
А зачем кому-то недодиалект? Разве что для маленьких модулей сойдет.

Какой недодиалект? Я не пытался изначально делать какой-то "диалект" или "недодиалект". Просто иногда встречаются места, где код выглядит из-за скобочек как говно, вот я и сделал для себя способ легко и просто в этих местах переписать код в нормальном виде. Например, надо применить к аргументы поочередно с пяток ф-й с длинными названиями, получается длинная неразбиваемая строка типа:
 
(one-long-function (another-long-name-function (third-long-name-function x)))
 

и еще в экран не поместится.
я переписываю как-нибудь так:
 
(x >> third-long-name-function
>> another-long-name-function
>> one-long-name-function)
 

+ еще немного авто-карринга для всяких filter/map (чтобы можно было писать нормально конвееры) и синтаксис для лямбд ((<> + 5) раскрывается в (lambda (x) (x + 5))). Ну а, собственно, возможность писать инфиксную арифметику - просто приятный бонус

Цитата
Это единственный способ получить чистый результат.

А чем ваш не устраивает чистый результат, соответствующий практике? Например - 1000 раз делаем экспанд выражения какой-нибудь разумной длины (10-20 операторов).

Сборку мусора проводили после каждого теста?


Нет, у меня под семеркой она странно себя ведет (иногда после нее в time опять запускается major collect). Но там написано время сборки мусора - оно в данном случае мало и ничего не решает.

Цитата
Да знаю я, как они работают. Гигиена требует трансформации конечного синтаксического объекта.
Например,

Вот и видно, что не знаете
никакие syntax-case/syntax-rules/syntax-parse и прочие ф-и гигиены в себе не содержат, эти ф-и работают так же как матч - матчат синтаксический объект и подставляют в результирующий паттерн переменные (так же как вы делаете, например `(,a ,b), так тут #`(a b), где a, b - забинденные переменные). Да, там вызывается apply-pattern-substitute, но он так и реализован - объект собирается из кусочков при помощи cons/list/append + вызовы datum->syntax на результат. И если бы вы дали себе труд потестить производительность подстановки в паттерн (например так: (with-syntax ([x #`1] [(y ...) #`(2 3 4)]) #`(5 6 y ... x)) и запускаете эдак сотню тысяч раз), то вы бы поняли, что он занимает считанные проценты всего времени выполнения макроса. теперь о том, ка реализуется гигиена. Когда вы определили (define-syntax name ...), то name - макро-трансформер. Неважно как вы его определили, хоть так: (define-syntax (name stx) stx). При каждом вызове каждого макротрансформера генерируется уникальная syntax-mark. Любой синтаксический объект имеет набор этих марок, причем если применить одну и ту же марку к одному объекту дважды - обе марки взаимоуничтожаются. Далее, если два идентификатора имеют разные марки и биндинги идентификаторов появились _после_ того, как марки стали разными, то эти биндинги "не считаются", то есть переменные трактуются как разные. Когда макро-трансформер вызывается, то сгенерированная им марка применяется к объекту, который подан на вход трансформера (применяется рекурсивно - на объект и все подобъекты). Когда трансформер возвращает результат, то эта марка применяется к результату вновь. Таким образом все, на всЕ, что подано на вход макросу марка применяется дважды - и взаимоуничтожается на всех входных идентификаторах. Идентификаторы же, которые сгенерированы внутри макроса, получают марку только один раз, на выходе. По-этому:
(define tmp 10)
(define-syntax-rule (test arg) (begin (displayln tmp) (let ([tmp 5]) (displayln arg))))
(test tmp) ; -> 10 10
результат экспанда: (let ([tmp 5]) (display tmp))
в третей строке tmp имеет тот же биндинг, что tmp первой строки, далее tmp уходит в макрос, на нее дважды применяется марка и в (display arg) внутри let мы имеем исходную tmp. на tmp в ([tmp 5]) марка применяется только однажды, далее при обработке let-формы (уже после экспанда и после применения марки) появляется соответствующий биндинг между tmp в ([tmp 5]) и tmp в (displayln arg), но т.к. биндинг появился уже после расхождения марок идентификаторы считаются различными. Т.о. выводится 10, а не 5. В (displayln tmp) на tmp так же применяется марка лишь один раз, но биндинг tmp появляется при обработке формы (define tmp 10), то есть до макроэкспанда (и даже до определения макроса) и, естествено, до наложения марки, т.о. это считается одним идентификатором и выводится опять-таки 10 (вместо unbound variable). Правда тут еще есть один забавный момент:
 
(define tmp 10)
(define-for-syntax tmp 20)
 
(define-syntax test
(lambda (stx) #`tmp))
 
(test) ; -> 10
 


Но:
 
(define tmp 10)
 
(define-syntax test
(lambda (stx) (let ([tmp 20])
#`tmp)))
 
(test) ; -> identifier used out of context in: tmp
 

В первом случае tmp имеет два раздельных биндинга - 10 в 0 фазе и 20 в 1 фазе. Далее к ней применяется марка, но поскольку биндинг существует до марки он остается, и мы выводим нашу 10. Во втором же случае после раскрытия let-формы в 1 фазе tmp становится в 1 фазе лексической. Но если переменная лексическая в какой-то фазе, то она во всех фазах лексическая - то есть любая tmp внутри let уже будет лексической в первой фазе, и у нее не будет введенного ранее биндинга (у лексической переменной нет module-level биндингов). По-этому имеем out of context (то есть лексическая переменная используется в контексте, в котором соответствующего лексического биндинга не существует - что и логично, этот биндинг остался в первой фазе).

Цитата
А match устроен проще, там переменные даже подставлять не нужно, они автоматически попадают в область видимости выражения.

Ну в syntax-case тоже. Там есть макрос типа map-identifier или как-то так, в общем он делает что-то наподобие того, что выдирает нужный кусок аргумента (при помощи car/cdr) и подставляет его на место аргумента в apply-pattern-substitute, которая уже из этих кусков и соберет окончательный syntax-object. Короче говоря, (with-syntax ([x #`1] [y #`2]) #`(x . y)) трансформируется в нечто вроде:
 
(apply-pattern-substitute `(_pat1 . _pat2)
`(_pat1 _pat2)
#`1
#`2)
 

первый аргумент - шаблон, по которому будет делаться подстановка, второй - список аргументов паттерна, дальше rest - сами аргументы. Сама apply-pattern-substitute в данном случае просто сделает (datum->syntax #'here (cons (get-arg `_pat1 `(_pat1 _pat2) `(,#`1 ,#`2)) (get-arg `_pat2 `(_pat1 _pat2) `(,#`1 ,#`2)))). get-arg работает по такому алгоритму:
(define (get-arg pat-arg  pat-args args)
(ormap (lambda (pat arg)
(if (eq? pat pat-arg) arg #f))
pat-args
args))

Kergan

Members


Статус

300 сообщений

Где: ---
Род занятий:
Возраст:

#4513   2011-07-03 19:41 GMT+3 часа(ов)      
Цитата
Вы привязаны к #%app. Лучше перегрузите, например, фигурные скобки.

Чтобы перегрузить фигурные скобки, надо менять ридер, а в ридер лучше не лезть - это во-первых. Во-вторых, перегрузка скобок ничего не даст. #%app я использую исключительно за тем, чтобы определять является ли head формы макросом. Если это макрос - форма будет раскрываться, если не макрос - то будет применен #%app (который перегружен). при перегрузке скобок никакого способа определить макрос у нас или нет - не существует, то есть скобки #%app не заменят. Вообще неясно, чем вам не нравится перегрузка #%app - повторяю, он _именно для этого_ нужен. Чтобы его перегружали.

Цитата
Вы его неправильно используете.

Что значит неправильно? я написал обычный макрос и ваш инфикс сломалсЯ, то есть для макросов, которые могут аскрываться в infix:, надо выполнять какие-то условия? а вы уверены, что _сами_ знаете эти условия? Ну и ваш вариант - это вообще плохой вариант. Вы в макросе my-macros убили гигиену и теперь my-macro не работает, вот смотрите:

(module m racket
(require "infix.rkt")
(provide infix:
my-macro)
 
(define f add1)
 
(define-syntax (my-macro s)
(syntax-case s ()
[(_ x)
(datum->syntax s (syntax->datum #'(infix: (f x) + (f x))))])))
 
(module m2 racket
(require 'm)
 
(my-macro 2)) ; -> unbound variable

Kergan

Members


Статус

300 сообщений

Где: ---
Род занятий:
Возраст:

#4514   2011-07-03 19:44 GMT+3 часа(ов)      
Цитата
module-path-index-resolve: "self" index has no resolution: #<module-path-index>

Это не в макросе дело, это у вас какие-то траблы. Сам модуль не загружается, то есть с путями что-то. Или racket как-то не так установлен, или файл не в той папке лежит или еще какая гадость. Надо запускать так:
скопируйте код с макросом в какой-нибудь файл (например infix.rkt), в той же папке сделайте файл test.rkt, там первой строкой должно быть:
#lang s-exp "infix.rkt"
файлы сохранены, лежат в одной папке
все так делаете?

Ну и не забудьте для (1 + 3 > (2 + 3)) сделать (infix-set! (> 3 left))

misha

Moderators


Статус

1275 сообщений
http://racket-lang.org/
Где: Yemen
Род занятий:
Возраст:

#4515   2011-07-03 19:57 GMT+3 часа(ов)      
Цитата
Вот и видно, что не знаете
никакие syntax-case/syntax-rules/syntax-parse и прочие ф-и гигиены в себе не содержат

Ну вы прям Кашпировский - читаете между строк.
Где я сказал, что syntax-case занимается генерацией кода? Я говорил о подстановке переменных. Т.к. ранее вы утверждали, что я не понимаю принципы работы match и syntax-case.
Цитата
Вообще неясно, чем вам не нравится перегрузка #%app - повторяю, он _именно для этого_ нужен. Чтобы его перегружали.

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

А ведь делается это достаточно просто.
Цитата
Ну и ваш вариант - это вообще плохой вариант. Вы в макросе my-macros убили гигиену и теперь my-macro не работает, вот смотрите:

А с гигиеной он не будет вообще работать.
Цитата
(infix: (f x) + (f x))

1) Этот код у меня теперь вообще не должен работать.
2) Это же не гигиенический макрос.

misha

Moderators


Статус

1275 сообщений
http://racket-lang.org/
Где: Yemen
Род занятий:
Возраст:

#4516   2011-07-03 20:01 GMT+3 часа(ов)      
Цитата
Сам модуль не загружается, то есть с путями что-то.

Он загружается, например, при (1 + 1 * 2).

Kergan

Members


Статус

300 сообщений

Где: ---
Род занятий:
Возраст:

#4517   2011-07-03 20:07 GMT+3 часа(ов)      
Цитата
Где я сказал, что syntax-case занимается генерацией кода?

При чем тут генерация кода? Вы зачем-то приплели к syntax-case гигиену, хотя syntax-case с гигиеной не имеет ни малйешей связи. И syntax-rules тоже.

Цитата
Вот именно, перегружали все кому необходимо.

Вот я и перегрузил

Цитата
А ведь делается это достаточно просто.

Нет, в данном случае это довольно-таки сложно и чревато рядом весьма неприятных вещей. Куда удобнее переопределить #%app - это и проще и безопаснее. Зачем лепить ненадежные велосипеды, если есть специальные средства, созданные для решения задачи? Ну и переопределение скобок,как я уже упомянул, не решает главной проблемы - активизацию инфиксного преобразования только в том случае, когда форма не макровызов.

Цитата
А с гигиеной он не будет вообще работать.

То есть тот, кто пишет некоторый макрос, раскрывающийся в ваш infix:, виноват в том, что ваш infix: не работает с гигиеной? А если без гигиены - то тоже ломается все равно?

Цитата
Этот код у меня теперь вообще не должен работать.

Он не работает в том смысле, что выдает корректное сообщение об ошибке или просто падает невнятным образом?
Алсо - не работает - ну и ладно, сделаем вот так:

 
(module m racket
(require "infix.rkt")
(provide infix:
my-macro)
 
(define y 10)
 
(define-syntax (my-macro s)
(syntax-case s ()
[(_ x)
(datum->syntax s (syntax->datum #'(infix: y + x)))])))
 
(module m2 racket
(require 'm)
 
(my-macro 2)) ; -> unbound variable
 


Цитата
Он загружается, например, при (1 + 1 * 2).

Всмысле
 
#lang s-exp "infix.rkt"
(1 + 1 * 2)
 

работает, а

 
#lang s-exp "infix.rkt"
(1 + 2 * (3 - 4))
 

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

misha

Moderators


Статус

1275 сообщений
http://racket-lang.org/
Где: Yemen
Род занятий:
Возраст:

#4518   2011-07-03 20:09 GMT+3 часа(ов)      
Цитата
Алсо - не работает - ну и ладно, сделаем вот так:

Сдается мне, вы не понимаете как работают не гигиенические макросы.

Kergan

Members


Статус

300 сообщений

Где: ---
Род занятий:
Возраст:

#4519   2011-07-03 20:11 GMT+3 часа(ов)      
Цитата
Сдается мне, вы не понимаете как работают не гигиенические макросы.

Я прекрасно понимаю. Более того - я понимаю, как они _не_ работают. Вот ваш ломается на каждый чих. Можете попытаться вывести еще какое-нибудь сообщение об ошибке или еще что - я придумаю еще один способ того, как он сломается, не беспокойтесь. Что характерно - способы-то весьма простые, легко могут встретиться при написании обычного кода.

Kergan

Members


Статус

300 сообщений

Где: ---
Род занятий:
Возраст:

#4520   2011-07-03 20:12 GMT+3 часа(ов)      
или стоп - вы хотите предложить сделать provide на все импортированные символы?

misha

Moderators


Статус

1275 сообщений
http://racket-lang.org/
Где: Yemen
Род занятий:
Возраст:

#4521   2011-07-03 20:13 GMT+3 часа(ов)      
Цитата
При чем тут генерация кода? Вы зачем-то приплели к syntax-case гигиену, хотя syntax-case с гигиеной не имеет ни малйешей связи. И syntax-rules тоже.

У схемы синтаксический анализ как таковой отсутствует. syntax-case обычно применяют совместно с гигиеной.
Цитата
или стоп - вы хотите предложить сделать provide на все импортированные символы?

На те что используются.

Да и вообще, когда я сказал, что собираюсь его применять?

Kergan

Members


Статус

300 сообщений

Где: ---
Род занятий:
Возраст:

#4522   2011-07-03 20:16 GMT+3 часа(ов)      
Цитата
syntax-case обычно применяют совместно с гигиеной.

Это не отменяет того, что syntax-case не имеет ничего общего с гигиеной.

Цитата
У схемы синтаксический анализ как таковой отсутствует.

Это что вы имели в виду и к чему сказали?

Цитата
Да и вообще, когда я сказал, что собираюсь его применять?

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

Цитата
На те что используются.

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

misha

Moderators


Статус

1275 сообщений
http://racket-lang.org/
Где: Yemen
Род занятий:
Возраст:

#4523   2011-07-03 20:19 GMT+3 часа(ов)      
Цитата
Это что вы имели в виду и к чему сказали?

То что вы ранее описывали генерацию промежуточного кода.

Kergan

Members


Статус

300 сообщений

Где: ---
Род занятий:
Возраст:

#4524   2011-07-03 20:21 GMT+3 часа(ов)      
Цитата
То что вы ранее описывали генерацию промежуточного кода.

Я не описывал генерацию промежуточного кода.


Онлайн :

0 пользователь(ей), 31 гость(ей) :




Реклама на сайте: