如何将输入模式中的文字标识符作为符号插入语法规则宏中

问题描述

我有这样的代码

(define-Syntax macron
  (Syntax-rules ()
    ((_ name)
     (lambda (x)
       (eval (cons 'name x) (interaction-environment))))))

(define x (map (macron lambda)
               '(((x) (display x)) ((a b) (+ a b)))))

(let ((square (car x)) 
      (sum (cadr x))) 
  (display (square 10)) 
  (newline) 
  (display (sum 1 2 3)) 
  (newline))

代码正在运行,通过将其与lambda封装在一起使用宏作为值。我的问题是如何将语法规则宏文字符号'name而不是(cons 'lambda ...)放在其中,所以输出代码为:

(lambda (x)
  (eval (cons 'name x) (interaction-environment)))

因此它可以与以下代码一起使用:

(define (name x)
  (display x)
  (newline))

(for-each (macron lambda) ;; lambda can be anything
          '((1) (2) (3)))

它会打印所有数字。

我知道我可以将模式中的名称更改为其他名称,但是我想进一步了解语法规则及其边缘情况。因此,如果我将其用作输入模式,可以使用名称吗?

我正在寻找R7RS的答案,其中涵盖了更多此类边缘情况。

解决方法

所有宏都发生在编译时,因此运行时内容可能不存在。这意味着您应该将其视为语法糖并将其用作替代。例如。

(for-each (macron something) '((1) (2) (3)))

然后应该在此基础上进行扩展。您当前的扩展就是变成这样:

(for-each (lambda (x)
            (eval (cons 'someting x) (interaction-environment))
          '((1) (2) (3)))

对于something作为宏,它将在运行时应用宏。这是坏的。首先,它也消除了对宏的需要。您可以改为:

(define (macron-proc name)
  (lambda (x)
    (eval (cons name x) (interaction-environment))))

(for-each (macron-proc 'something) '((1) (2) (3)))

我制作了一种具有可传递宏的编程语言:

(define xor (flambda (a b) `(if,a (not,b),b)))
(define (fold comb init lst)
  (if (null? lst)
      init
      (fold comb (comb (car lst) init) (cdr lst))))
(fold xor #f '(#t #t)) ; ==> #f

如果您针对高效的编译最终产品,这不是一个很好的方法。第一个宏确实是这样的,他们在Common Lisp之前的LISP 1.5中将其删除。 Scheme多年来一直避免使用宏,并在R4RS中选择了syntax-rules作为可选功能。 R6RS是唯一具有完整功能宏的版本。

使用过程而不是宏,实际上与以下代码相同,但删除了错误的eval

(for-each (lambda (x)
            (apply something x))
          '((1) (2) (3)))

这意味着您可以更轻松地实现macron

(define-syntax macron
  (syntax-rules ()
    ((_ name)
     (lambda (x)
       (apply name x)))))

但是从现在的角度来看,您根本不需要宏。这是部分应用程序。

(define (partial proc arg)
  (lambda (lst)
    (apply proc arh lst)))

(map (partial + 3) '((1 2) (3 4) (4 5)))
; ==> (6 10 12)

实际上有一个SRFI-26,叫做cut / cute,它使我们可以将其包装在lambda中,从而执行类似的操作:

(map (cut apply + 3 <>) '((1 2) (3 4) (4 5)))

syntax-rules是功率最低的宏。您不能做任何不卫生的事情,也不能基于其他标识符创建新的标识符。例如。不可能实现球拍样式struct,在其中您可以执行(struct complex [real imag])并让宏创建complex?complex-realcomplex-imag作为过程。您需要像SRFI-57那样做,并要求用户指定所有名称,这样您就不必连接到新标识符。

现在,R7RS-small仅具有syntax-rules。我认为没有一个更强大的宏作为替代是一个错误,因为现在R7RS-large无法用R7RS-small来实现。