rnso
rnso

Reputation: 24623

Why this macro does not work in Racket

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

Answers (1)

Sylwester
Sylwester

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

Related Questions