
A very beginning macro question: (define-syntax switch-log
(syntax-rules ()
[(_ #t)
(begin
(define (printf/debug x . xs) (apply printf (cons x xs)))
(define (printf/info x . xs) (apply printf (cons x xs)))
(define (printf/warning x . xs) (apply printf (cons x xs))))]
[(_ #f)
(begin
(define (printf/debug x . xs) (void))
(define (printf/info x . xs) (void))
(define (printf/warning x . xs) (void)))]))
(switch-log #t)
(printf/debug "xxx") ; <--- ERROR: printf/debug: unbound identifier
But (switch-log #t)
exactly macro expand to (begin
(define-values
(printf/debug)
(lambda (x . xs) (#%app apply printf (#%app cons x xs))))
(define-values
(printf/info)
(lambda (x . xs) (#%app apply printf (#%app cons x xs))))
(define-values
(printf/warning)
(lambda (x . xs) (#%app apply printf (#%app cons x xs)))))
(printf/debug "xxx")
;; xxx
Need help, thanks.

Possibly a scoping/hygiene thing? That is, the scope information attached to the syntax-objects for the ids printf/debug
(etc.) may not include the right scope? I’m not sure of that, though

@chansey97 With syntax-rules
you need to do this: (define-syntax switch-log
(syntax-rules ()
[(_ printf/debug printf/info printf/warning #t)
(begin
(define (printf/debug x . xs) (apply printf (cons x xs)))
(define (printf/info x . xs) (apply printf (cons x xs)))
(define (printf/warning x . xs) (apply printf (cons x xs))))]
[(_ printf/debug printf/info printf/warning #f)
(begin
(define (printf/debug x . xs) (void))
(define (printf/info x . xs) (void))
(define (printf/warning x . xs) (void)))]))
(switch-log printf/debug printf/info printf/warning #t)
(printf/debug "xxx")

Time to try out syntax-parse
!

Thanks all! (Although I don’t know exactly what’s going on inside.)

The problem is that syntax-rules
can’t introduce new identifiers where the macro is used (at the place where you write (switch-log #t)
. The solution is to give the identifiers to syntax-rules
.

The default scope for a an identifier that appears in a template is restricted to referenced to it in that template.

Can I understand that syntax-rules
can capture identifiers, but can not create identifiers?

I am not sure what you mean by “capture an identifier”.

(define printf/debug #f)
(define printf/info #f)
(define printf/warning #f)
(define-syntax switch-log
(syntax-rules ()
[(_ #t)
(begin
(set! printf/debug (lambda (x . xs) (apply printf (cons x xs))))
(set! printf/info (lambda (x . xs) (apply printf (cons x xs))))
(set! printf/warning (lambda (x . xs) (apply printf (cons x xs)))))]
[(_ #f)
(begin
(set! printf/debug (lambda (x . xs) (void)))
(set! printf/info (lambda (x . xs) (void)))
(set! printf/warning (lambda (x . xs) (void))))]))
(switch-log #t)
(printf/debug "xxx")
;; xxx
Then OK.

This is fine due to lexical scope.

Yes. In this case, syntax-rules captured printf/debug. But if no printf/debug
identifier in advance, syntax-rules can not create by define, unless manually pass them.

Yes.

The syntax-case
and syntax-parse
macro systems use format-id
or datum->syntax
to transfer the context of call to a new identifier. That is, they can make an identifier that behaves as it had been passed to the macro (as in the version I wrote above).

I accidentally found that struct constructor does not support keywords.