0

我有这样的代码:

(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 的答案,它涵盖了更多此类边缘情况。

4

1 回答 1

2

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

(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 多年来一直避免使用宏,并选择syntax-rules在 R4RS 中作为可选功能。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,它允许我们做类似的事情,它将它包装在一个 lambda 中:cutcute

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

syntax-rules是功率最小的宏。您不能做任何不卫生的事情,也不能根据其他标识符制作新的标识符。例如。不可能实现一种球拍风格struct,您可以在其中执行(struct complex [real imag])宏 create complex?complex-realcomplex-imagas 过程。您需要像SRFI-57那样做,并要求用户指定所有名称,这样您就不需要连接到新的标识符。

目前 R7RS-small 只有syntax-rules. 我认为没有更强大的宏作为替代方案是错误的,因为现在 R7RS-large 不能用 R7RS-small 实现。

于 2020-08-21T13:17:17.993 回答