Matt G
Matt G

Reputation: 1681

Using Syntax Parameters in Racket

I'm trying to define a macro that generates an anonymous function taking one argument named it, for succinctness, so that instead of

(λ (it) body)
I can write
(λλ body)

(In other words, (λλ body) transforms to (λ (it) body))

(define-syntax-parameter it #f)
(define-syntax λλ
  (syntax-rules ()
    ((_ body)
     (λ (x) (syntax-parameterize ((it x)) body)))))
(λλ (< it 0)) ; For testing

I get operators.rkt:13:28: ?: literal data is not allowed; no #%datum syntax transformer is bound in the transformer environment in: #f at (define-syntax-parameter if #f), but as far as I can tell, this is exactly like the example given in racket's doc for how to use define-syntax-parameter. I can suppress the error by replacing #f with a function (I used member, but not for any real reason), but after doing that, I get operators.rkt:17:38: x: identifier used out of context in: x. What am I doing wrong?

Upvotes: 3

Views: 1176

Answers (2)

C. K. Young
C. K. Young

Reputation: 222973

Syntax parameters are not the only way to implement the macro you have in mind. A simpler (IMO) way is to just use datum->syntax to inject the identifier it:

(define-syntax (λλ stx)
  (syntax-case stx ()
    ((_ body ...)
     (with-syntax ((it (datum->syntax stx 'it)))
       #'(λ (it) body ...)))))

To use your example:

(define my-negative? (λλ (< it 0)))
(my-negative? -1)   ;; => #t

Upvotes: -1

stchang
stchang

Reputation: 2540

You left out the syntax-id-rules part in the example. It's the part that specifies that it should expand to x. Alternatively, you can use make-rename-transformer:

#lang racket
(require racket/stxparam)

(define-syntax-parameter it #f)
(define-syntax λλ
  (syntax-rules ()
    ((_ body)
     (λ (x) (syntax-parameterize ([it (make-rename-transformer #'x)]) body)))))
((λλ (< it 0)) 5)
((λλ (< it 0)) -5)

=>

#f
#t

Upvotes: 4

Related Questions