Следующая страница > 1 < [2]

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

qaqa

Members


Статус

18 сообщений

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

#6412   2012-08-06 23:07 GMT+3 часа(ов)      
Возьмем для примера код:
(define f
(lambda (x) ... (display x) ...))
Значение переменной x необходимо только в выражении (display x) и в остальных частях процедуры не используется.

Пусть необходимо привести код к виду:
(define f
(special-form-with-hidden-input ... (display-hidden-input) ...))
В результате раскрытия второго варианта, должен получаться первый. При этом, имя входной переменной не имеет значения, так как скрыто, и генерируется автоматически с соблюдением гигиены.
Знаний, чтобы реализовать только средствами макросов, не хватает. Сделал несколько другим образом, проще:
(define param (make-parameter #f))
(define-syntax-rule (special-from-with-hidden-input a ...)
(lambda (x)
(parameterize ([param x])
a ...)))
(define (display-hidden-input)
(display (param)))
Но в решении используется параметр - по большому счету глобальная переменная.

Есть варианты лучше?

Oleg

Members


Статус

2 сообщений

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

#6413   2012-08-08 11:44 GMT+3 часа(ов)      
Может скрыть значение x (define f (lambda (x) (let ([x #f]) ...)(display x)(let ([x #f]) ...))

Kergan

Members


Статус

300 сообщений

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

#6415   2012-08-09 00:37 GMT+3 часа(ов)      
Если display-hidden-input - функция, то никак. Только через параметр. Если макрос - можно ввести анафору. Можно более конкретный пример, что требуется сделать?

qaqa

Members


Статус

18 сообщений

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

#6418   2012-08-09 09:08 GMT+3 часа(ов)      
Цитата
Oleg :
Может скрыть значение x (define f (lambda (x) (let ([x #f]) ...)(display x)(let ([x #f]) ...))

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

То есть никакой let не должен скрывать входную переменную.

qaqa

Members


Статус

18 сообщений

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

#6419   2012-08-09 09:42 GMT+3 часа(ов)      
Цитата
Kergan :
Если display-hidden-input - функция, то никак. Только через параметр. Если макрос - можно ввести анафору. Можно более конкретный пример, что требуется сделать?

Так и есть, если уходить от параметров, то display-hidden-input функцией никак быть не может.
Такой пример я привел, чтобы не усложнять. Более подробно: входной параметр - это продолжение. И хотелось бы что-то подобное:

(define (f switch-k)
...
(let ([switch-k (let/cc k (switch-k k))])
...
(let ([switch-k (let/cc k (switch-k k))])
...
(f switch-k)))) ;в конце переход на начало цикла

привести к виду:

(define f
(cycle-with-switching
...
(switch)
...
(switch)
...
))

Только какими средствами это сделать

Aoloa

Members


Статус

37 сообщений

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

#6420   2012-08-09 13:29 GMT+3 часа(ов)      
Цитата

Пусть необходимо привести код к виду:
(define f
(special-form-with-hidden-input ... (display-hidden-input) ...))



syntax-case я пока что не понимаю, а с er-macro-transformer (в Chicken Scheme) можно сделать как-то так:
(define-syntax special-form-with-hidden-input
(er-macro-transformer
(lambda (exp rename compare)
`(,(rename 'lambda)
(,(rename 'x))
,@(map (lambda (subform)
(if (and (list? subform)
(eq? (car subform)
'display-hidden-input))
(list (rename 'display) (rename 'x))
subform))
(cdr exp))))))
 
(define ololo
(special-form-with-hidden-input
(display "lol!")
(newline)
(display-hidden-input)
(newline)
(display "ololo!")
(newline)))


Вот только в 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

Members


Статус

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 задает некоторое преобразование предыдущих форм и мы можем его дооопределять. Будет как-то так:
 
#lang racket
 
(require syntax/parse/define
racket/stxparam
racket/stxparam-exptime
(for-syntax syntax/parse))
 
(provide cycle-with
start
call
switch)
 
(module+ extras
(provide cycle-with-hidden
define-cycle-with-clause))
 
(define-syntax-parameter cycle-with-hidden
(lambda (stx) (raise-syntax-error 'anaphora "can be used only in cycle-with context" stx)))
 
(begin-for-syntax
(struct cycle-with-clause (transformer)
#:property prop:procedure (lambda (stx) (raise-syntax-error #f "can be used only in cycle-with context" stx)))
 
(define-syntax-class cycle-with-clause-class
(pattern (x:id rest ...)
#:do [(define value (syntax-local-value #'x (lambda _ #f)))]
#:when (cycle-with-clause? value)
#:attr transformer (cycle-with-clause-transformer value))))
 
(define-simple-macro (define-cycle-with-clause name:id [pattern:expr res:expr] ...+)
(define-syntax name (cycle-with-clause (syntax-parser [pattern res] ...))))
 
(define-syntax (cycle-with stx)
(syntax-parse stx
[(cycle-with c:cycle-with-clause-class r ...) ((attribute c.transformer) #'(c r ...))]
[(cycle-with e:expr r:expr ...+) #'(begin e (cycle-with r ...))]
[(cycle-with e:expr) #'e]))
 
(define-cycle-with-clause start
[((start) r ...+) #'(lambda (param)
(syntax-parameterize ([cycle-with-hidden (make-rename-transformer #'param)])
(cycle-with r ...)))])
 
(define-simple-macro (call name:id)
(name cycle-with-hidden))
 
(define-cycle-with-clause switch
[((switch) r:expr ...+) #'(let ([param (let/cc k (cycle-with-hidden k))])
(syntax-parameterize ([cycle-with-hidden (make-rename-transformer #'param)])
(cycle-with r ...)))])
 

если импортируется сам модуль, то доступа к скрытой переменной нет (ни на изменение ни на чтение), если импортируем extras - доступ есть (и на изменение и на чтение). Можно еще сделать варинат с доступом на чтение, но без доступа на изменение, однако в этом случае переменная все равно будет шадовиться let'ом (имеется ввиду cycle-with-hidden, a не tmp, tmp в любом лучае эффективно скрыта и получить к ней доступ никак нельзя).

Kergan

Members


Статус

300 сообщений

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

#6422   2012-08-09 19:29 GMT+3 часа(ов)      
2Aoloa
в racket автоматическая гигиена, то есть по сути все rename выполняются по дефолту. Аналог твоего макроса будет выглядеть на racket так:
 
#lang racket
(require syntax/parse/define
(for-syntax syntax/parse))
 
(begin-for-syntax
(define-syntax-class with-clause
(pattern ((~datum display-hidden-input))
#:with e #'(display x))
(pattern form
#:with e #'form)))
 
(define-simple-macro (special-form-with-hidden-input c:with-clause ...)
(lambda (x) c.e ...))
 

qaqa

Members


Статус

18 сообщений

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

#6425   2012-08-09 21:58 GMT+3 часа(ов)      
2Kergan
Так как я c syntax/parse и с остальными неясными для меня вещами, присутствующими в примере, не разбирался еще, то понять сразу, что тут делается не получится. Одна только просьба, приведите небольшой пример того, как это должно использоваться
У меня в примере cycle-with-switching (это у вас короче называется cycle-with), должна раскрываться в лямбду, а если, пользуясь вашим кодом написать:
(cycle-with
(display "HELLO!"))
, то осуществляется печать сразу.
А за примеры большое спасибо!

misha

Moderators


Статус

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

#6426   2012-08-09 22:07 GMT+3 часа(ов)      
Цитата
(special-form-with-hidden-input c:with-clause ...)
Я бы в паттерн добавил еще одну переменную.
Коротко, но плохо (требует проверки):
(define-syntax (special-form-with-hidden-input stx)
#`(lambda(x)
(let ([#,(datum->syntax stx 'display-hidden-input) (lambda() (display x))])
#,@(stx-cdr stx))))

Чуть лучше:
(define-syntax (special-form-with-hidden-input stx)
(syntax-case stx ()
[(_ e1 e2 ...)
(with-syntax ([display-x (datum->syntax stx 'display-hidden-input)])
#`(lambda(x)
(let ([display-x (lambda() (display x))])
e1 e2 ...)))]))

misha

Moderators


Статус

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

#6427   2012-08-09 22:10 GMT+3 часа(ов)      
Цитата
(f switch-k)))) ;в конце переход на начало цикла
На начало текущего цикла? Можете привести развернутый пример?

Kergan

Members


Статус

300 сообщений

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

#6428   2012-08-09 22:24 GMT+3 часа(ов)      
2qaqa
Там, условно говоря, две части - ядро дсл (все кроме последних трех define-ов) и определение конкретных форм. В данном случае определены две top-level формы - start и switch, первая обернет все нижеследующее в лямбду, а вторая - в (let ... (param (let/cc k ...)) ...), то есть использовать надо как-то так:
 
(define f
(cycle-with (start)
(display 1)
(switch)
(display 2)
(display 3)
(switch)
(display 4)
(when #f (call f))))
 

если импортировать extras, то можно доопределять новые формы для дсл в дополнение к start, switch, call. Ну и можно написать макрос, который будет всегда раскрываться (macro body ...) -> (with-cycle (start) body ...), естественно

qaqa

Members


Статус

18 сообщений

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

#6429   2012-08-09 22:30 GMT+3 часа(ов)      
Цитата
На начало текущего цикла? Можете привести развернутый пример?

Там имелось в виду, что f должна представлять собой бесконечный цикл, и поэтому в последней строке вызывает сама себя

Kergan

Members


Статус

300 сообщений

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

#6430   2012-08-09 22:32 GMT+3 часа(ов)      
2misha
Код с datum->syntax может себя иногда вести весьма нетривиально, так что подобных низкоуровневых преобразований следует по возможности избегать. По части дополнительной переменной - да, лучше так:
 
define-simple-macro (special-form-with-hidden-input c:with-clause ...+)
(lambda (x) c.e ...))
 

qaqa

Members


Статус

18 сообщений

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

#6431   2012-08-09 22:39 GMT+3 часа(ов)      
2Kergan
Проверил, то что надо! Буду разбираться дальше

Kergan

Members


Статус

300 сообщений

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

#6432   2012-08-09 22:47 GMT+3 часа(ов)      
вот пост про синтаксические параметры: http://blog.racket-lang.org/2008/02/dirty-looking-hygiene.html

misha

Moderators


Статус

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

#6433   2012-08-09 23:29 GMT+3 часа(ов)      
Цитата
Код с datum->syntax может себя иногда вести весьма нетривиально, так что подобных низкоуровневых преобразований следует по возможности избегать.
Вообще-то он обязан вести себя в соответствии со стандартом r6rs. Тем более, что это базовая вещь, которая используется повсеместно.

misha

Moderators


Статус

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

#6434   2012-08-09 23:43 GMT+3 часа(ов)      
Цитата
Там имелось в виду, что f должна представлять собой бесконечный цикл, и поэтому в последней строке вызывает сама себя
Ok. Ну, тогда вопрос эстетического плана. Вы и вправду считаете, что макрос cycle-with-switching читабелен?
(cycle-with-switching
...
(switch)
...
(switch)
...
)
Имхо, непонятно с первого раза, что есть (switch). Может его лучше упростить, добавить сахарку?

Kergan

Members


Статус

300 сообщений

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

#6435   2012-08-09 23:54 GMT+3 часа(ов)      
Цитата
Вообще-то он обязан вести себя в соответствии со стандартом r6rs. Тем более, что это базовая вещь, которая используется повсеместно.

ну так это поведение и есть иногда очень и очень нетривиально

misha

Moderators


Статус

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

#6436   2012-08-10 00:15 GMT+3 часа(ов)      
Цитата
ну так это поведение и есть иногда очень и очень нетривиально
А где гарантия, что, например, rename-transformer будет вести себя тривиально(как ожидалось)?

Kergan

Members


Статус

300 сообщений

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

#6437   2012-08-10 00:31 GMT+3 часа(ов)      
Цитата
А где гарантия, что, например, rename-transformer будет вести себя тривиально(как ожидалось)?

ну мы верим что он реализован в соответствии со спецификацией. его нетривиальное поведение может быть разве что результатом бага, а вот нетривиальное поведение datum->syntax - идет из спецификации. Мы ведь берем контекст из объекта stx, но почему не из части этого объекта? тогда контексты будут разные. кроме того очень трудно проследить за контекстами, если это выражение попало сперва в один макрос, потом в другой, а сгенерировано было в третем макросе, который сам является результатом генерации четвертого

qaqa

Members


Статус

18 сообщений

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

#6438   2012-08-10 09:37 GMT+3 часа(ов)      
Цитата
Имхо, непонятно с первого раза, что есть (switch). Может его лучше упростить, добавить сахарку?

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

Макрос cycle-with-switching разворачивается в процедуру, которая принимает на вход продолжение switch-k, переданного движком. Продолжение switch-k используется в форме switch. Форма switch разворачивается в код, который захватывает текущее продолжение k и вызывает продолжение switch-k c передачей ему k. Грубо говоря, switch - это передача управления движку, с сохранением текущего состояния в продолжении k.

Примерный код движка:
(define stop? #f)
(define (stop!) (set! stop? #t))
;;tasks - список, элементы которого либо
;;cycle-with-switching (если еще ни разу не вызывались),
;;либо продолжения.
(define tasks (list ...))
(define (engine)
(if (or (null? tasks) stop?) (display "engine stopped!")
(let ([f (first tasks)])
(let ([k (let/cc switch-k (f switch-k))])
(if (continuation? k) ; если было передано не продолжение
(set! tasks (append (rest tasks) (list k)))
(set! tasks (rest tasks)))
(engine)))))
(define t (thread (thunk (engine))))

Kergan

Members


Статус

300 сообщений

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

#6439   2012-08-10 14:05 GMT+3 часа(ов)      
2Qaqa, вообще, если ограничиться конкретно тем что требуется, то можно мой код значительно упростить:
 
(define-syntax switch #f)
 
(define-syntax (with-cycle stx)
(define (helper stx sym)
(syntax-case stx (switch)
[((switch) r rr ...) #`(let ([param (let/cc k (param k))])
#,(helper #'(r rr ...) sym))]
[(r rr ...) #`(begin r #,(helper #'(rr ...) sym))]
[() #`(#,sym param)]))
 
(syntax-case stx ()
[(_ id rest ...) #`(lambda (param) #,(helper #'(rest ...) #'id))]))
 
(define f
(with-cycle f
(display 1)
(display 2)
(switch)
(display 3)
(display 4)
(switch)
(display 5)))
 

qaqa

Members


Статус

18 сообщений

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

#6440   2012-08-10 14:26 GMT+3 часа(ов)      
2Kergan
Ну да, так в разы короче. Но, получается, первый вариант более расширяемый. Или как?

qaqa

Members


Статус

18 сообщений

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

#6441   2012-08-10 14:30 GMT+3 часа(ов)      
2Kergan
Ну и дублирование f, по хорошему, надо убирать, то есть еще один простенький макрос надо

misha

Moderators


Статус

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

#6442   2012-08-10 17:35 GMT+3 часа(ов)      
Цитата
Мы ведь берем контекст из объекта stx, но почему не из части этого объекта? тогда контексты будут разные.
Конечно, в данном случае это может привести к выпадению переменной из области видимости.
Цитата
кроме того очень трудно проследить за контекстами, если это выражение попало сперва в один макрос, потом в другой, а сгенерировано было в третем макросе, который сам является результатом генерации четвертого
Ну, это относится и к трансформерам, т.к. есть вероятность что после трансформации контексты не будут совпадать.

misha

Moderators


Статус

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

#6443   2012-08-10 17:44 GMT+3 часа(ов)      
Имхо, так более читабельно:
(with-cycle f
(begin
(display 1)
(display 2))
(switch
(display 3)
(display 4))
(switch
(display 5)))
чем
(with-cycle f
(display 1)
(display 2)
(switch)
(display 3)
(display 4)
(switch)
(display 5))

Kergan

Members


Статус

300 сообщений

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

#6444   2012-08-10 19:32 GMT+3 часа(ов)      
Цитата
Ну, это относится и к трансформерам, т.к. есть вероятность что после трансформации контексты не будут совпадать.

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

Kergan

Members


Статус

300 сообщений

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

#6445   2012-08-10 19:42 GMT+3 часа(ов)      
2qaqa
Цитата
Ну, это относится и к трансформерам, т.к. есть вероятность что после трансформации контексты не будут совпадать.

да, именно так.между решениями две существенные разницы:
1. в первом случае используются синтаксические параметры, во втором - обычная переменная. Доступ к введенной макросом лексической переменной без нарушения гигиены позволяет обращаться к этой переменной только в рамках вызова текущего макротрансформера (как это и сделано во втором примере). Синтаксические параметры лишены этого ограничения - т.о. они могут обеспечивать взаимодействие _между_ вызовами, то есть связывать между собой различные макросы, в первом примере у нас много связанных макросов, во втором - всего один, и если мы попытаемся ввести другой макрос, который мог бы обращаться к скрытому параметру, то у нас со вторым примером не выйдет ничего, а с первым - не будет никаких затруднений, главное импортировать субмодуль extras.
2. в первом случае реализован "стандартный" механизм, позволяющий определять свои собственные формы (start/switch как раз и реализованы при его помощи) и макросы (как call), использующие скрытый параметр и переопределяющие его, это как раз обеспечивается благодаря первому пункту.

Цитата
2Kergan
Ну и дублирование f, по хорошему, надо убирать, то есть еще один простенький макрос надо

оно дублируется и в первом и во втором случае, т.к. f используется в контексте define и вне контекста with-cycle, то есть with-cycle о нем ничего не знает. Единственный способ решения этой проблемы - сделать макрос, который будет сразу раскрываться в define форму с внутренней формой with-cycle, какой-нибудь define-with-cycle то есть.

Kergan

Members


Статус

300 сообщений

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

#6446   2012-08-10 19:47 GMT+3 часа(ов)      
Цитата
Имхо, так более читабельно:

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

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


Онлайн :

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




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