[racket] Help with simple macro
Thanks to this Eli, I now see what parameters are.
By chance I also just came across your's, Ryan's and Matthew's article
"Keeping It Clean with Syntax Parameters"
http://www.schemeworkshop.org/2011/papers/Barzilay2011.pdf
that makes crystal clear all the issues about the question I asked.
Cheers,
Harry
On Mon, May 21, 2012 at 10:01 AM, Eli Barzilay <eli at barzilay.org> wrote:
> On Wednesday, Harry Spier wrote:
>> [...]
>> but I've been unable to create a macro to create this form:
>> ---------------------------------------
>> (with-sequence SOME-SEQUENCE
>> . . . .. . (get-next) .
>> . . . (get-next) . . . etc.)
>> ---------------------------------------
>>
>> where I don't pass the names of the thunks to test for end of sequence
>> or to get the next item in the sequence, but that they are called
>> "more?" and "get-next" by convention.
>>
>> How would I do this.
>
> Since you're using the name as a function, you can do that easily with
> a parameter:
>
> (define current-get-next (make-parameter (λ () (error "no next"))))
> (define (get-next) ((current-get-next)))
> (define-syntax-rule (with-sequence seq body ...)
> (let-values ([(more? the-get-next) (sequence-generate seq)])
> (parameterize ([current-get-next the-get-next])
> body ...)))
> (with-sequence '(1 2 3)
> (list (get-next) (get-next) (get-next)))
>
> [You could also make it appear as a magical binding with an identifer
> macro:
>
> (define-syntax next
> (syntax-id-rules ()
> [(_ x ...) ((get-next) x ...)]
> [_ (get-next)]))
> ]
>
> This does have some performance penalty though, since each call to
> `get-next' goes through the parameter. The way to avoid that is to
> switch the parameter to a syntax parameter -- the idea is similar to a
> parameter, except that it's done at the syntax level:
>
> (require racket/stxparam)
> (define-syntax-parameter get-next
> (λ (stx) (raise-syntax-error #f "not in `with-sequence'" stx)))
> (define-syntax-rule (with-sequence seq body ...)
> (let-values ([(more? the-get-next) (sequence-generate seq)])
> (syntax-parameterize ([get-next (make-rename-transformer #'the-get-next)])
> body ...)))
> (with-sequence '(1 2 3)
> (list (get-next) (get-next) (get-next)))
>
> --
> ((lambda (x) (x x)) (lambda (x) (x x))) Eli Barzilay:
> http://barzilay.org/ Maze is Life!