Автор | Сообщение |
qaqa
18 сообщений |
#6412 2012-08-06 23:07 GMT+3 часа(ов) |
Возьмем для примера код:
(define fЗначение переменной x необходимо только в выражении (display x) и в остальных частях процедуры не используется. Пусть необходимо привести код к виду: (define fВ результате раскрытия второго варианта, должен получаться первый. При этом, имя входной переменной не имеет значения, так как скрыто, и генерируется автоматически с соблюдением гигиены. Знаний, чтобы реализовать только средствами макросов, не хватает. Сделал несколько другим образом, проще: (define param (make-parameter #f))Но в решении используется параметр - по большому счету глобальная переменная. Есть варианты лучше? |
|
Oleg
2 сообщений |
#6413 2012-08-08 11:44 GMT+3 часа(ов) |
Может скрыть значение x (define f (lambda (x) (let ([x #f]) ...)(display x)(let ([x #f]) ...))
|
|
Kergan
300 сообщений |
#6415 2012-08-09 00:37 GMT+3 часа(ов) |
Если display-hidden-input - функция, то никак. Только через параметр. Если макрос - можно ввести анафору. Можно более конкретный пример, что требуется сделать?
|
|
qaqa
18 сообщений |
#6418 2012-08-09 09:08 GMT+3 часа(ов) |
Цитата Цитата То есть никакой let не должен скрывать входную переменную. |
|
qaqa
18 сообщений |
#6419 2012-08-09 09:42 GMT+3 часа(ов) |
Цитата Так и есть, если уходить от параметров, то display-hidden-input функцией никак быть не может. (define (f switch-k) привести к виду: (define f Только какими средствами это сделать ![]() |
|
Aoloa
37 сообщений |
#6420 2012-08-09 13:29 GMT+3 часа(ов) |
Цитата syntax-case я пока что не понимаю, а с er-macro-transformer (в Chicken Scheme) можно сделать как-то так: (define-syntax special-form-with-hidden-input Вот только в Racket’е нет er-macro-transformer... ![]() |
|
With iTeX* your entire life can be encapsulated into a dynamic hyperdocument, downloadable by anybody you designate (Donald E. Knuth, An Earthshaking Announcement)
|
|
Kergan
300 сообщений |
#6421 2012-08-09 14:55 GMT+3 часа(ов) |
2qaqa
Если предоставить клиентскому коду возможность работы с этой скрытой переменной, то запрет на невозможность переопределения внешним let-ом будет нарушать гигиену. Если клиенсткому коду эта переменная не нужна, то гигиеническая анафора подойдет. Как я понял, требуется реализовать dsl cycle-with, имеющий следующий синтаксис (cycle-with body ...+), body ::= racket-expression | cycle-with-clause, причем cycle-with-clause задает некоторое преобразование предыдущих форм и мы можем его дооопределять. Будет как-то так:
если импортируется сам модуль, то доступа к скрытой переменной нет (ни на изменение ни на чтение), если импортируем extras - доступ есть (и на изменение и на чтение). Можно еще сделать варинат с доступом на чтение, но без доступа на изменение, однако в этом случае переменная все равно будет шадовиться let'ом (имеется ввиду cycle-with-hidden, a не tmp, tmp в любом лучае эффективно скрыта и получить к ней доступ никак нельзя). |
|
Kergan
300 сообщений |
#6422 2012-08-09 19:29 GMT+3 часа(ов) |
2Aoloa
в racket автоматическая гигиена, то есть по сути все rename выполняются по дефолту. Аналог твоего макроса будет выглядеть на racket так:
|
|
qaqa
18 сообщений |
#6425 2012-08-09 21:58 GMT+3 часа(ов) |
2Kergan
Так как я c syntax/parse и с остальными неясными для меня вещами, присутствующими в примере, не разбирался еще, то понять сразу, что тут делается не получится. Одна только просьба, приведите небольшой пример того, как это должно использоваться ![]() У меня в примере cycle-with-switching (это у вас короче называется cycle-with), должна раскрываться в лямбду, а если, пользуясь вашим кодом написать: (cycle-with, то осуществляется печать сразу. А за примеры большое спасибо! |
|
misha![]()
1275 сообщений |
#6426 2012-08-09 22:07 GMT+3 часа(ов) |
ЦитатаЯ бы в паттерн добавил еще одну переменную. Коротко, но плохо (требует проверки): (define-syntax (special-form-with-hidden-input stx) Чуть лучше: (define-syntax (special-form-with-hidden-input stx) |
|
misha![]()
1275 сообщений |
#6427 2012-08-09 22:10 GMT+3 часа(ов) |
ЦитатаНа начало текущего цикла? Можете привести развернутый пример? |
|
Kergan
300 сообщений |
#6428 2012-08-09 22:24 GMT+3 часа(ов) |
2qaqa
Там, условно говоря, две части - ядро дсл (все кроме последних трех define-ов) и определение конкретных форм. В данном случае определены две top-level формы - start и switch, первая обернет все нижеследующее в лямбду, а вторая - в (let ... (param (let/cc k ...)) ...), то есть использовать надо как-то так:
если импортировать extras, то можно доопределять новые формы для дсл в дополнение к start, switch, call. Ну и можно написать макрос, который будет всегда раскрываться (macro body ...) -> (with-cycle (start) body ...), естественно |
|
qaqa
18 сообщений |
#6429 2012-08-09 22:30 GMT+3 часа(ов) |
Цитата Там имелось в виду, что f должна представлять собой бесконечный цикл, и поэтому в последней строке вызывает сама себя ![]() |
|
Kergan
300 сообщений |
#6430 2012-08-09 22:32 GMT+3 часа(ов) |
2misha
Код с datum->syntax может себя иногда вести весьма нетривиально, так что подобных низкоуровневых преобразований следует по возможности избегать. По части дополнительной переменной - да, лучше так:
|
|
qaqa
18 сообщений |
#6431 2012-08-09 22:39 GMT+3 часа(ов) |
2Kergan
Проверил, то что надо! Буду разбираться дальше ![]() |
|
Kergan
300 сообщений |
#6432 2012-08-09 22:47 GMT+3 часа(ов) |
вот пост про синтаксические параметры: http://blog.racket-lang.org/2008/02/dirty-looking-hygiene.html
|
|
misha![]()
1275 сообщений |
#6433 2012-08-09 23:29 GMT+3 часа(ов) |
ЦитатаВообще-то он обязан вести себя в соответствии со стандартом r6rs. Тем более, что это базовая вещь, которая используется повсеместно. |
|
misha![]()
1275 сообщений |
#6434 2012-08-09 23:43 GMT+3 часа(ов) |
ЦитатаOk. Ну, тогда вопрос эстетического плана. Вы и вправду считаете, что макрос cycle-with-switching читабелен? (cycle-with-switchingИмхо, непонятно с первого раза, что есть (switch). Может его лучше упростить, добавить сахарку? |
|
Kergan
300 сообщений |
#6435 2012-08-09 23:54 GMT+3 часа(ов) |
Цитата ну так это поведение и есть иногда очень и очень нетривиально ![]() |
|
misha![]()
1275 сообщений |
#6436 2012-08-10 00:15 GMT+3 часа(ов) |
ЦитатаА где гарантия, что, например, rename-transformer будет вести себя тривиально(как ожидалось)? ![]() |
|
Kergan
300 сообщений |
#6437 2012-08-10 00:31 GMT+3 часа(ов) |
Цитата ну мы верим что он реализован в соответствии со спецификацией. его нетривиальное поведение может быть разве что результатом бага, а вот нетривиальное поведение datum->syntax - идет из спецификации. Мы ведь берем контекст из объекта stx, но почему не из части этого объекта? тогда контексты будут разные. кроме того очень трудно проследить за контекстами, если это выражение попало сперва в один макрос, потом в другой, а сгенерировано было в третем макросе, который сам является результатом генерации четвертого ![]() |
|
qaqa
18 сообщений |
#6438 2012-08-10 09:37 GMT+3 часа(ов) |
Цитата Непонятно потому, что не развернут контекст применения ![]() ![]() Макрос cycle-with-switching разворачивается в процедуру, которая принимает на вход продолжение switch-k, переданного движком. Продолжение switch-k используется в форме switch. Форма switch разворачивается в код, который захватывает текущее продолжение k и вызывает продолжение switch-k c передачей ему k. Грубо говоря, switch - это передача управления движку, с сохранением текущего состояния в продолжении k. Примерный код движка: (define stop? #f) |
|
Kergan
300 сообщений |
#6439 2012-08-10 14:05 GMT+3 часа(ов) |
2Qaqa, вообще, если ограничиться конкретно тем что требуется, то можно мой код значительно упростить:
|
|
qaqa
18 сообщений |
#6440 2012-08-10 14:26 GMT+3 часа(ов) |
2Kergan
Ну да, так в разы короче. Но, получается, первый вариант более расширяемый. Или как? |
|
qaqa
18 сообщений |
#6441 2012-08-10 14:30 GMT+3 часа(ов) |
2Kergan
Ну и дублирование f, по хорошему, надо убирать, то есть еще один простенький макрос надо ![]() |
|
misha![]()
1275 сообщений |
#6442 2012-08-10 17:35 GMT+3 часа(ов) |
ЦитатаКонечно, в данном случае это может привести к выпадению переменной из области видимости. ЦитатаНу, это относится и к трансформерам, т.к. есть вероятность что после трансформации контексты не будут совпадать. |
|
misha![]()
1275 сообщений |
#6443 2012-08-10 17:44 GMT+3 часа(ов) |
Имхо, так более читабельно:
(with-cycle fчем (with-cycle f |
|
Kergan
300 сообщений |
#6444 2012-08-10 19:32 GMT+3 часа(ов) |
Цитата если мы не используем иизкоуровневые средства преобразования, то у нас есть определенные гарантии - гарантии гигиены (то есть как выражение откуда и куда бы ни скакало - все будет корректно с точки зрения гигиены). Если начинаем эти средства использовать - гарантии гигиены исчезают, поведение становится менее предсказуемым, становится завязано на контекст использования макроса, усложняется обеспечение гарантий корректности. То есть низкоуровневые средства стоит применять тогда, когда их применение обосновано - то есть задача без них либо не решается, либо решение без них _значительно_ сложнее/длиннее/более трудно поддерживаемо/менее понятно. В противном случае следует предпочесть решение, основанное на использовании стандартных, проверенных средств. Ну это вобщем-то не только для макросов верно - для всего ![]() |
|
Kergan
300 сообщений |
#6445 2012-08-10 19:42 GMT+3 часа(ов) |
2qaqa
Цитата да, именно так.между решениями две существенные разницы: 1. в первом случае используются синтаксические параметры, во втором - обычная переменная. Доступ к введенной макросом лексической переменной без нарушения гигиены позволяет обращаться к этой переменной только в рамках вызова текущего макротрансформера (как это и сделано во втором примере). Синтаксические параметры лишены этого ограничения - т.о. они могут обеспечивать взаимодействие _между_ вызовами, то есть связывать между собой различные макросы, в первом примере у нас много связанных макросов, во втором - всего один, и если мы попытаемся ввести другой макрос, который мог бы обращаться к скрытому параметру, то у нас со вторым примером не выйдет ничего, а с первым - не будет никаких затруднений, главное импортировать субмодуль extras. 2. в первом случае реализован "стандартный" механизм, позволяющий определять свои собственные формы (start/switch как раз и реализованы при его помощи) и макросы (как call), использующие скрытый параметр и переопределяющие его, это как раз обеспечивается благодаря первому пункту. Цитата оно дублируется и в первом и во втором случае, т.к. f используется в контексте define и вне контекста with-cycle, то есть with-cycle о нем ничего не знает. Единственный способ решения этой проблемы - сделать макрос, который будет сразу раскрываться в define форму с внутренней формой with-cycle, какой-нибудь define-with-cycle то есть. |
|
Kergan
300 сообщений |
#6446 2012-08-10 19:47 GMT+3 часа(ов) |
Цитата первый вариант модифицируется до предложенного синтаксиса безо всяких проблем путем исправления пары строк. только вместо begin луяше использовать другой биндинг, switch-begin какой-нибудь. у твоего варианта, кстати, есть очень значительно преимущество - можно относительно корректно отобразить source location синтаксических объектов результата макроэкспанда в source location синтаксических объектов формы макровызова (с оригинальным синтакисом нельзя, то есть можно, но придется усложнять значительно сам макрос, а потом и выставлять source буквально руками, что, опять-таки, есть низкоуровневые подробности, использование которых может потом неожиданно аукнуться). Это значительно преимущество, помогающее при отладке. |
|