为什么这个宏在Racket中不起作用

时间:2016-08-22 07:49:16

标签: scheme racket

我正在尝试使用一个宏来应用'当'功能当'否则'声明没有给出,否则'如果'使用:

(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) ) 

但是,这不起作用。错误是:

myif: use does not match pattern: 
   (myif condition body (body2 #f)) in: (myif (> x 10) (println x))

1 个答案:

答案 0 :(得分:3)

define-syntax-rules不会像带有可选参数的过程那样使用参数。

(define-syntax-rule (myif condition body (body2 #f))
  ...)

与:

相同
(define-syntax myif
  (syntax-rules ()
   [(myif condition body (body2 #f)) ...]))

有效使用是(myif predicate consequence (alternative #f)),它会变成:

(if (not (alternative #f))
    (when predicate consequence)
    (if predicate consequence (alternative #f)))

您似乎正在尝试使用应该运行编译时间而不是扩展的一部分的代码,因为这将在谓词之前评估备选方案。这不适用于syntax-rules,但是您可以使用两种不使用简化语法的模式来执行您想要的操作:

(define-syntax myif
  (syntax-rules ()
   [(_ predicate consequence alternative) (if predicate consequence alternative)]
   [(_ predicate consequence) (when predicate consequence)])

修改

所以用一个函数来做同样的事情,而不是宏。这是一个没有惊险刺激,没有我能想到的特殊功能实现。注意:对于像这样的宏来说,我只是初学者。

(define-syntax (myif stx)
  (let ((lst (syntax->list stx)))
    (if (= (length lst) 3)
        #`(when #,@(cdr lst))
        #`(if #,@(cdr lst)))))

请注意,lst的部分是语法对象,其中包含来自何处的信息。 `#, #,, and #,@`,,@的语法。