什么时候使用with-syntax

在用syntax-case的时候,多处使用quasisyntax,unsyntax,unsyntax-splicing会把代码搞的跟咒语一样:

;无法嘲笑perl了
(syntax-case #'(a 1 2 3) ()
    [(name . args) #`(name #,@#'args)]

这个时候with-syntax就又用了,能让代码可读性好很多:

;又可以嘲笑perl了
(syntax-case #'(a 1 2 3) ()
  [(name . args) 
   (with-syntax ([(a ...) #'args]) 
     #'(name a ...))])

宏的模板部分就简单多了 

with-syntax语法跟let类似,但是自带模式匹配,跟match-let更像 

前面那个例子太trival了,下面来个稍微现实一点的:

比如我想要个新语法alist ,它根据所给的参数生成一个asscociative list: (即变量及其值的二元组 list)


(let ([a "meme"]) 
  (alist a (b 1) (c (* 2 b))))

=> {{a "meme"} {b 1} {c 2}} 

 在这个环境下,a的值是字符串"meme",b的值是1,c是2,所以生成对应的alist:{{a "meme"} {b 1} {c 2}}

(define-syntax alist;(alist arg ...)
  (lambda (x)
    (define (x->name&value x);aux transformer function
      (syntax-case x ()
        [(n v) (identifier? #'n) #'(n v)];(var val) -> (var val)
        [n (identifier? #'n) #'(n n)]))  ;var       -> (var val)
    (syntax-case x ()
      [(alist arg ...) 
       (with-syntax 
           ([((name value) ...)
             (map x->name&value #'(arg ...))])
         #'(let* ([name value] ...)
             (list (list 'name name) ...)))])))

 这里使用with-syntax可以避免分情况讨论,分情况的细节封装在辅助transformer,然后map过去就是了.这样一来可读性提高了不少.嗯哼

 

posted @ 2012-03-28 11:42  硅胶鱼  阅读(314)  评论(0编辑  收藏  举报