Guile`syntax-rules`:形式错误的省略号;如何编写带有两个椭圆的宏?

时间:2019-04-17 17:32:39

标签: macros scheme guile syntax-rules

我正在或多或少地尝试通过let重新创建syntax-rules构造,但似乎由于使用了两个椭圆而使它绊倒了。

我试图这样写:

(define-syntax if-let
  (syntax-rules ()
    [(_ (([binding        value]  ...)
         ([binding2 funct value2])
         ([binding3       value3] ...)) then else) (let ([binding  value]  ...
                                                         [binding2 value2]
                                                         [binding3 value3] ...)
                                                     (if (funct binding2) then else))]))

我发现[binding2 funct value2]中间的独特模式可以根据模式对第一个模式何时结束以及第二个模式何时开始进行清楚的划分,但是我一直回想起标题错误。

预期的结果是能够执行类似的操作

(if-let ([var1                  1]
         [diff null? '(1 2 3 4 5)]
         [var2                  2])
    var1
  var2)

并返回2,但是能够根据远程需要在var之前和之后拥有diff,因此最终使用的变量的顺序无关紧要。

我缺少明显的东西吗?而且这种模式是否可以用卫生宏完成?感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

这可以通过助手宏来执行,以便在中间找到funct事物时所需的递归。

(if-let-helper processed-bindings processed-conditions input-binding-conditions then else)

重复出现时,会将input-binding-conditions中的信息传输到 processed-bindingsprocessed-conditions,当 input-binding-conditions为空。

(define-syntax if-let-helper
  (syntax-rules ()
    [(_ ([bnd val] ...) (cnd ...) () then else)
     (let ([bnd val] ...)
       (if (and cnd ...) then else))]
    [(_ ([bnd val] ...) (cnd ...) ([binding value] . rest) then else)
     (if-let-helper ([bnd val] ... [binding value]) (cnd ...) rest then else)]
    [(_ ([bnd val] ...) (cnd ...) ([binding funct value] . rest) then else)
     (if-let-helper ([bnd val] ... [binding value]) (cnd ... (funct binding))
                    rest then else)]))

(define-syntax if-let
  (syntax-rules ()
    [(_ (binding-funct-value ...) then else)
     (if-let-helper () () (binding-funct-value ...) then else)]))

使用它:

> (if-let ([var1                  1]
           [diff null? '(1 2 3 4 5)]
           [var2                  2])
    var1
    var2)
2

为解释这一点,我将逐步介绍该示例如何处理每个子句。它最初变成了这个if-let-helper调用:

(if-let-helper
  ()
  ()
  ([var1                  1]
   [diff null? '(1 2 3 4 5)]
   [var2                  2])
  var1
  var2)

前两个列表开始为空,因为它尚未处理任何东西。

(if-let-helper
  ([var1                  1])
  ()
  ([diff null? '(1 2 3 4 5)]
   [var2                  2])
  var1
  var2)

这时,它已经处理了第一个子句,并向第一个“处理的绑定”列表中添加了一个绑定值对。但是,第一子句中没有funct,因此它没有向第二个“处理条件”列表中添加条件。

(if-let-helper
  ([var1                  1]
   [diff       '(1 2 3 4 5)])
  ((null? diff))
  ([var2                  2])
  var1
  var2)

此时,它已经处理了前两个子句,并向第二个列表添加了(null? diff)条件,因为它在第二个子句中看到了funct

(if-let-helper
  ([var1                  1]
   [diff       '(1 2 3 4 5)]
   [var2                  2])
  ((null? diff))
  ()
  var1
  var2)

至此,它已经处理了所有三个子句,因此它符合基本情况,并转换为最终的letif

(let ([var1                  1]
      [diff       '(1 2 3 4 5)]
      [var2                  2])
  (if (and (null? diff))
      var1
      var2))