我正在阅读《Scheme 编程语言》第四版这本书。在练习中,有一个表达式 ((car (list + - */)) 2 3)
。以下是我认为将评估表达式的步骤。请告诉我我的理解是否正确。
- 表达式
(list + - */)
被计算为过程列表:(+ - */)
。 (我知道list
总是产生一个“正确的列表”,有人可以说明一下使用list
和cons
之间的一些区别吗?)< - 表达式
(car (+ - */))
被计算为符号+
,该符号计算为一个过程。 (我不太明白(car (+ - */))
是如何计算的,在 REPL 提示符处输入(car (+ - */))
会产生一个错误)。 - 表达式
(+ 2 3)
的计算结果为5
。
我希望我能得到一些其他/深入的解释。
最佳答案
- 是的!但是,这些过程没有文字表示,因此当您评估
+
时你会得到一些疯狂的文本表示,例如#<primitive-procedure-+>
复制它并将其粘贴到 repl 中不会返回相同的对象。与列表相同。当您评估(list 1 2 3)
时你得到(1 2 3)
但你不能只写(1 2 3)
因为它会认为应该调用1
作为带有两个参数的过程。(list 1 2 3)
使(cons 1 (cons 2 (cons 3 '())))
嵌套对链。那最后cdr
是()
这就是它的正确之处。因此,允许list
的原语做这件事是cons
。 错了。您有一个计算表达式
(list + - * /)
类似(#<primitive-procedure-+> #<...> #<...> #<...>)
。评估变量的列表,您现在可以看到它们的视觉表示。做car
它给你第一个对象#<primitive-procedure-+>
这与评估全局变量+
时得到的相同 。此步骤不涉及任何符号。上一步也不涉及符号,因为裸符号是变量。'test
成为符号,而test
变成变量所指向的任何内容。所有按名称命名的过程都只是在应用之前评估的变量。这是Scheme 中的默认行为。由于该对象与值
+
相同它会将其余操作数在求值后添加到一起。由于它们都是数字,因此传递给 apply 的参数保持不变,但如果您有像(+ (* 3 3) (* 4 4))
这样的表达式那么操作数如(* 3 3)
需要进行评估,其结果就是所应用的。
您可以应用替换规则。这不是Scheme解释器所做的,但是任何变量都可以被它拥有的值替换,每个表达式都可以被它的结果替换,只要你不改变任何东西:
((car (list + - * /)) (- 5 2) (/ 4 2)) ; == (car (list + - * /)) evaluates to the same value as the variable +
(+ (- 5 2) (/ 4 2)) ; == (- 5 2) evaluates to 3, (/4 2) evaluates to 2
(+ 3 2) ; == (+ 3 2) evaluates to 5
; ==> 5 (the result)
注意我替换了(car (list + - * /))
变量 +
而不是一个符号。它们都是相同的:(eq? (car (list + - * /)) +) ; ==> #t
关于方案表达式评估,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43613269/