我对lisp很新,最近我发现了一些我不理解的薄片。
此代码有效:
(define (f x) (define a x) (define (b) a) (b))
这不是:
(define (f x) (define a x) (define b a) b)
为什么?
答案 0 :(得分:2)
在kawa interpeter中它起作用 在Guile它没有,因为 这段代码
(define (f x) (define a x) (define b a) b)
扩展为
(define (f x) (letrec ((a x) (b a)) b))
在我分配之前,您无法访问a
。 letrec
不适用于非功能定义,例如:
(letrec ((x 5)
(y x))
y)
您可以使用let*
insted
(define (f x) (let* ((a x) (b a)) b))
在此代码中
(define (f x) (define a x) (define (b) a) (b))
在程序b中,您可以在已经定义的情况下访问变量。
答案 1 :(得分:2)
您应该查看有关letrec*
的讨论 - 有些实现会将其用作更严格letrec
的更宽松版本,这会导致您看到的差异。
答案 2 :(得分:0)
您可能会看到R5RS和R6RS标准之间的行为变化。其中一个changes in R6RS是“内部定义现在按letrec*
定义。”
在R5RS中,内部define
s are completely equivalent到letrec
。特别是,关于内部定义的部分说“就像等效的letrec
表达式一样,必须能够评估<expression>
中每个内部定义的<body>
而不分配或引用到被定义的任何<variable>
的值。“
但是,在R6RS中,内部define
s are equivalent到letrec*
。并且,正如您所期望的那样,letrec*
allows您可以在初始化器中引用先前变量的值以用于以后的变量。