Lisp (定义…)的嵌套应用程序之间的竞争条件?

Lisp (定义…)的嵌套应用程序之间的竞争条件?,lisp,scheme,racket,race-condition,Lisp,Scheme,Racket,Race Condition,在linux和Mac操作系统上使用DrRacket时,下面的代码给出了此错误 *: expects type <number> as 1st argument, given #<undefined> 这是Racket的scheme解释器中的一个bug,还是指定的语言使得(define…)的嵌套调用可能发生混乱?如果是后者,我在哪里可以找到语言规范的相关部分 另一方面,我非常了解“let”结构,并且知道这不是定义此类程序的推荐方法。不过,我没有料到会出现这种错误。以下是与

在linux和Mac操作系统上使用DrRacket时,下面的代码给出了此错误

*: expects type <number> as 1st argument, given #<undefined>
这是Racket的scheme解释器中的一个bug,还是指定的语言使得(define…)的嵌套调用可能发生混乱?如果是后者,我在哪里可以找到语言规范的相关部分

另一方面,我非常了解“let”结构,并且知道这不是定义此类程序的推荐方法。不过,我没有料到会出现这种错误。

以下是与R5RS规范相关的解释内部定义行为的内容。请注意,第§5.2.2节规定:

。。。必须能够评估
中每个内部定义的每个
,而无需分配或引用所定义的任何
的值

换句话说,如果在同一内部定义中定义依赖于先前定义的值的值,则不能指望正确的行为。为此使用
let*

(define (quadr x y)
  (let* ((xx   (* x x))
         (yy   (* y y))
         (xxyy (* xx yy)))
    (+ xx yy xxyy)))
或者更详细一点,使用两个嵌套的
let
s:

(define (quadr x y)
  (let ((xx (* x x))
        (yy (* y y)))
    (let ((xxyy (* xx yy)))
      (+ xx yy xxyy))))

非常奇怪的是,插入
(换行)
会使变量定义适用于本例,但当您处理未定义的行为时,任何情况都可能发生。作为旁注,如果我使用
#lang racket
而不是
#lang r5rs
,那么原始代码在没有额外的
(换行)

的情况下对我有效。这是您最后的评论:r5rs对于内部定义具有
letrec
语义,而R6RS和R7RS具有
letrec*
语义。这就是为什么你会看到不同的行为,这取决于你是否在使用
#lang r5rs
@ChrisJester Young racket在走自己的路之前是否真的改变了他们的语言以符合
R6RS
,所以R6RS和Racket在很多方面都是一致的,这并不奇怪。不一定建议在内部定义上使用
let
。Racket程序员尤其倾向于使用内部定义,因为
#lang Racket
支持更多语法形式的内部定义。
(define (quadr x y)
  (let ((xx (* x x))
        (yy (* y y)))
    (let ((xxyy (* xx yy)))
      (+ xx yy xxyy))))