Reputation: 24623
I am trying to have a macro which applies 'when' function when the 'else' statement is not given, otherwise 'if' is used:
(define-syntax-rule (myif condition body (body2 #f))
(if (not body2)
(when condition body)
(if condition
body
body2)))
(define x 15)
(myif (> x 10) (println x) )
However, this is not working. The error is:
myif: use does not match pattern:
(myif condition body (body2 #f)) in: (myif (> x 10) (println x))
Upvotes: 0
Views: 276
Reputation: 48775
define-syntax-rules
doesn't take the arguments like a procedure with optional arguments.
(define-syntax-rule (myif condition body (body2 #f))
...)
Is the same as:
(define-syntax myif
(syntax-rules ()
[(myif condition body (body2 #f)) ...]))
A valid use would be (myif predicate consequence (alternative #f))
and it turns into:
(if (not (alternative #f))
(when predicate consequence)
(if predicate consequence (alternative #f)))
It seems you are trying to have code that should run compile time and not part of the expansion since this will evaluate the alternative before the predicate. That won't work with syntax-rules
, however you can do what you want with having two patterns not using the simplified syntax:
(define-syntax myif
(syntax-rules ()
[(_ predicate consequence alternative) (if predicate consequence alternative)]
[(_ predicate consequence) (when predicate consequence)])
EDIT
So to do the same thing with a function imlpementing the macro instead. Here is a no thrills, no special feature implementation I could think of. NB: I'm a mere beginner when it comes to macros like these.
(define-syntax (myif stx)
(let ((lst (syntax->list stx)))
(if (= (length lst) 3)
#`(when #,@(cdr lst))
#`(if #,@(cdr lst)))))
Notice that the part of lst
are syntax objects that have information of where it came from. `#
, #,
, and #,@
are the syntax evivalent of `
, ,
, and ,@
.
Upvotes: 3