[racket] Help with simple macro

From: Eli Barzilay (eli at barzilay.org)
Date: Mon May 21 10:01:51 EDT 2012

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!


Posted on the users mailing list.