首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >letrec语法和let语法在Scheme中有什么区别?

letrec语法和let语法在Scheme中有什么区别?
EN

Stack Overflow用户
提问于 2020-04-11 12:27:49
回答 1查看 725关注 0票数 1

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

但是,对于letrec语法和let语法,这也是一样的。

代码语言:javascript
复制
(let-syntax ((foo (lambda (x) `(bar (list ',(car x) ',(caadr x)))))
             (bar (lambda (x) `(display ',x))))
    (foo (list 1 2 3)))

您能给出这两个宏/语法不同的代码示例吗?

编辑:

发现这个:

代码语言:javascript
复制
(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了。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-04-11 14:03:57

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

代码语言:javascript
复制
(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形式,您将了解为什么它调用全局test

代码语言:javascript
复制
((lambda (test) (test 5))
 (lambda (v)
   (if (zero? v)
       (list 0)
       (cons v (test (- v 1))))))

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

代码语言:javascript
复制
(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确保stestsyntax-rules转换程序的环境中可用,以便它与自身匹配,而不是顶级宏。

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

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61156799

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档