1

有类似的问题,但没有语法宏,但我认为不同之处在于一个宏看不到另一个,如 letrec 和 let 函数。

但这与 letrec-syntax 和 let-syntax 相同

(let-syntax ((foo (lambda (x) `(bar (list ',(car x) ',(caadr x)))))
             (bar (lambda (x) `(display ',x))))
    (foo (list 1 2 3)))

你能展示这两个宏/语法不同的代码示例吗?

编辑:

发现这个:

(let-syntax ((bar (lambda (x) `(display ',x)))
             (foo (lambda (x) (bar x))))
   (foo (list 1 2 3)))

不适用,let-syntax它适用于letrec-syntax,但这有什么好处?如果那些局部变量不能是函数(输出是(bar x)),那么 的目的是let-syntax什么?我需要可以在代码中使用它的示例,在不需要的地方letrec-syntax,它就足够了let-syntax

4

1 回答 1

3

let它与和相同letrec。在let评估值时,您不能期望绑定存在。这只会影响过程/lambda/闭包的创建,因为所有过程都是在创建它们的环境中调用的。

(define (test v)
  (list 'default v))

(let ((test (lambda (v) 
              (if (zero? v)
                  (list 0)
                  (cons v (test (- v 1)))))))
  (test 5))
; ==> (5 default 4)

(letrec ((test (lambda (v)
                (if (zero? v)
                    (list 0)
                    (cons v (test (- v 1)))))))
  (test 5))
; ==> (5 4 3 2 1 0)

因此,在let示例中,本地let不在闭包的主体中,因为在评估值时它不存在。在实践中,如果您扩展let为等效的 lambda 形式,您就会明白它为什么调用 global test

((lambda (test) (test 5))
 (lambda (v)
   (if (zero? v)
       (list 0)
       (cons v (test (- v 1))))))

你明白为什么它不调用自己吗?letrec专门用于创建具有自身约束力的本地程序来解决这个小问题。对于语法规则,它对相似名称具有相同的绑定属性,但是我们正在处理语法,因此我们需要使这些步骤不依赖于运行时算术:

(define-syntax stest
  (syntax-rules ()
    ((_ v . rest) '(default v))))

(let-syntax ((stest (syntax-rules () 
                      ((_ v . rest) (cons 'v (stest . rest)))
                      ((_) '()))))
  (stest 5 4 3 2 1 0))
; ==> (5 default 4)

(letrec-syntax ((stest (syntax-rules () 
                         ((_ v . rest) (cons 'v (stest . rest)))
                         ((_) '()))))
  (stest 5 4 3 2 1 0))
; ==> (5 4 3 2 1 0)

再次letrec-syntax确保stest在变压器的环境中可用,syntax-rules以便它匹配自身而不是顶级宏。

至于您的示例,它们不是Scheme。它们可能会在某些特定的方案实现中作为事实上的额外功能工作,但它们不会像我的示例那样在任何 R5RS、R6RS 或 R7RS 实现中工作。R6RS 有syntax-case一个额外的变压器,我猜 R7RS-large 也会有额外的变压器。如果您追求事实上的行为,则需要标记特定的实现。

于 2020-04-11T14:03:57.243 回答