Is there any way to define a compile-time (expansion-time) macro variable in Racket or any other Scheme?

StackOverflow https://stackoverflow.com/questions/18238722

Вопрос

To give a simple example:

(define-macro-variable _iota 0) ; define-macro-variable does not really exist

(define-syntax (iota stx)
  (syntax-case stx ()
    ((iota)
     (let ((i _iota))
       (set! _iota (+ i 1))
       #`#,i))))

Such that given:

(define zero (iota))
(define one-two-three (list (iota) (iota) (iota)))
(define (four) (iota))

the following should all evaluate to #t:

(equal? zero 0)
(equal? one-two-three '(1 2 3)) ; possibly in a different order
(equal? (four) 4)
(equal? (four) 4)
(equal? (four) 4)

Is there any real racket feature that does what define-macro-variable is supposed to do in the example above?

EDIT:

I found a work-around:

(define-syntaxes (macro-names ...)
  (let (macro-vars-and-vals ...)
    (values macro-bodies-that-nead-the-macro-vars ...)))

but I would prefer a solution that does not require all the macros that use the macro variables to be in one expression.

Это было полезно?

Решение

You want define-for-syntax (in Racket).

(define-for-syntax _iota 0)

(define-syntax (iota stx)
  (syntax-case stx ()
    ((iota)
     (let ((i _iota))
       (set! _iota (+ i 1))
       #`#,i))))

(define zero (iota))
(define one-two-three (list (iota) (iota) (iota)))
(define (four) (iota))

(equal? zero 0)
(equal? one-two-three '(1 2 3))
(equal? (four) 4)
(equal? (four) 4)
(equal? (four) 4)

produces all true.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top