Scheme 节目什么时候开始;交织定义和使用“;?
他说: 在过程体中,嵌入的定义必须放在第一位。管理层不对运行混淆定义和使用的程序的后果负责 这到底意味着什么?我明白:Scheme 节目什么时候开始;交织定义和使用“;?,scheme,lisp,definition,sicp,Scheme,Lisp,Definition,Sicp,他说: 在过程体中,嵌入的定义必须放在第一位。管理层不对运行混淆定义和使用的程序的后果负责 这到底意味着什么?我明白: “定义”指的是程序创建和价值分配 “一个程序主体”将被删除。它是过程定义中参数列表后面的代码 “嵌入式定义必须在过程体中放在第一位”是指“在过程体中创建和使用的任何定义必须放在其他定义之前” “interjune definition and use”是指“在定义过程或赋值之前调用它;” 然而,这种理解似乎与答案相矛盾,我可以将答案总结为“你的引用所指的错误是在程序主体开始
- “定义”指的是程序创建和价值分配
- “一个程序主体”将被删除。它是过程定义中参数列表后面的代码
- “嵌入式定义必须在过程体中放在第一位”是指“在过程体中创建和使用的任何定义必须放在其他定义之前”
- “interjune definition and use”是指“在定义过程或赋值之前调用它;”李>
sqrt
过程李>
num prod
视为他们定义的num
中的一个值,而不是一个过程。然而,作者显然让它工作了,所以我可能错了到底发生了什么?误解在哪里?这是很微妙的,正如脚注和您提到的问题所暗示的,根据特定语言的实现,这些细节可能会有所不同 这些问题将在本书后面(第3章和第4章)进行更详细的讨论,通常情况下,文本避免使用内部定义,以便在详细检查之前避免这些问题 脚注上方代码之间的主要区别:
(define (sqrt x)
(define (good-enough? guess)
(< (abs (- (square guess) x)) 0.001))
(define (improve guess)
(average guess (/ x guess)))
(define (sqrt-iter guess)
(if (good-enough? guess)
guess
(sqrt-iter (improve guess))))
(sqrt-iter 1.0))
前者中的所有定义都是过程定义,而num
和denom
是值定义。程序体在调用该程序之前不会进行评估。但赋值时会对值定义进行求值
具有值定义:
(define sum (add 2 2))
评估定义时将评估(添加2)
,如果是,则必须已定义add
。但有一个程序定义:
(define (sum n m) (add n m))
程序对象将分配给sum
,但程序主体尚未计算,因此定义sum
时不需要定义add
,但必须在调用sum
时定义:
(sum 2 2)
正如我所说的,有很多子类型和很多变化,所以我不确定以下是否总是适用于方案的每个变化,但在“SICP方案”中,你可以说
有效(定义的评估顺序不显著):
同样有效的还有:
;procedure body
(define (sum) (add 2 2))
(define (add m n) (+ m n))
(sum)
通常无效(对define
s的评估顺序很重要):
以下各项是否有效取决于实施情况:
;procedure body
(define (add m n) (+ m n))
(define sum (add 2 2))
最后是一个交织定义和使用的示例,这是否有效还取决于实现。IIRC,如果已经实施了,这将适用于本书第4章中描述的方案
;procedure body
(sum)
(define (sum) (add 2 2))
(define (add m n) (+ m n))
这是复杂而微妙的,但关键是:
你发现了这个计划的困难之一。和lisp。由于这种问题,没有单一的lisp,但出现了大量的lisp 如果R5RS中的
letrec
-逻辑中的代码和R6RS中的letrec*
-逻辑中不存在绑定形式,则语义未定义。也就是说,一切都取决于方案实施者的意愿
请参阅论文FixedLetrec:Scheme递归绑定构造的忠实而高效的实现
此外,您还可以阅读来自的讨论,当时方案的不同实施者之间没有达成普遍共识
此外,麻省理工学院开发了两个版本的方案——学生版本和研究人员开发版本,它们在定义形式的顺序上表现不同。在给定程序的定义/代码中
- “内部定义”是以
开头的表单define
- “过程主体”是以
开头的表单之后的所有其他表单define
- “嵌入定义必须在过程体中首先出现”是指所有内部
表单必须先出现,然后是所有其他内部表单。一旦出现非define
内部表单,之后就不能出现内部define
表单define
- “无交错使用”是指在定义任何名称之前,不得使用任何名称。假设所有内部
表单都被收集到一个等价的define
,并遵循其规则letrec
(define (proc args ...)
;; internal, or "embedded", definitions
(define a1 ...init1...)
(define a2 ...init2...)
......
(define an ...initn...)
;; procedure body
exp1 exp2 .... )
任何ai
都可以在任何initj
表达式中使用,但只能在lambda表达式中使用。(*)否则它将在定义aj
时引用ai
的值,这是禁止的,因为在计算任何initj
表达式时,认为尚未定义任何ai
名称
(*)Rem
;procedure body
(define (add m n) (+ m n))
(define sum (add 2 2))
;procedure body
(sum)
(define (sum) (add 2 2))
(define (add m n) (+ m n))
(define (proc args ...)
;; internal, or "embedded", definitions
(define a1 ...init1...)
(define a2 ...init2...)
......
(define an ...initn...)
;; procedure body
exp1 exp2 .... )
(define proc
(lambda (args ...)
;; internal, or "embedded", definitions
(letrec ( (a1 ...init1...)
(a2 ...init2...)
......
(an ...initn...) )
;; procedure body
exp1 exp2 ....
)))
;; or, equivalently,
(define (my-proc x) (define my-proc
(lambda (x)
(define (foo) a) (letrec ( (foo (lambda () a))
(define a x) (a x) )
;; my-proc's body ;; letrec's body
(foo)) (foo))))
(define (my-proc x)
(define (foo) x) ; `foo` is defined as a function
(define a (foo)) ; `foo` is used by being called as a function
a)