是否可以在不做任何更改的情况下从这个 SICP 第 3 章代码中简单地删除 let 块?
Can the let block be trivially removed from this SICP chapter 3 code without anything changing?
Chapter 3 of SICP 包含这个不寻常的代码块。
(define (propagate)
(if (empty-agenda? the-agenda)
'done
(let ((first-item (first-agenda-item the-agenda)))
(first-item)
(remove-first-agenda-item! the-agenda)
(propagate))))
在我看来,first-item
在这里只用了一次,所以我认为 let
没有必要。是否有任何特殊原因导致以下代码不等价?
(define (propagate)
(if (empty-agenda? the-agenda)
'done
(begin
(first-agenda-item the-agenda)
(remove-first-agenda-item! the-agenda)
(propagate))))
你的转型想法非常好,但你做错了,正如肖恩在评论中所说。
最简单的错误示例是将代码转换成这样:
(let ((f something))
(f)
x)
进入
(begin
something
x)
请注意,此处遗漏了对 (f)
的额外调用:原始版本计算一个函数 然后调用它 ,而转换计算一个函数但抛出它走了。更准确的转换是:
(begin
(something)
x)
"The idea of a let
block that is not doing variable assignment is strange to me."
但它会进行变量初始化和变量引用。可以写成
(define (propagate)
(if (empty-agenda? the-agenda)
'done
(let ((first-item #f))
(set! first-item (first-agenda-item the-agenda))
(first-item)
(remove-first-agenda-item! the-agenda)
(propagate))))
你写的相当于
(define (propagate)
(if (empty-agenda? the-agenda)
'done
(let ((first-item #f))
(set! first-item (first-agenda-item the-agenda))
first-item ; NB! _No_ _Parens_
(remove-first-agenda-item! the-agenda)
(propagate))))
您的行 (first-agenda-item the-agenda)
returns the-agenda
中的第一个值但未使用它 -- 不对其执行任何操作.
但原始的 (first-item)
通过名称引用该值,first-item
,并且 使用 它即调用该值作为不带参数的函数。
遵循以等代替等的原则,在纯代码中(即只处理值,而不处理任何places in computer memory),我们在代码的纯子集中替换name
; impure: deals with a named place in computer memory
(set! first-item (first-agenda-item the-agenda) )
; pure: refers to a value by the name it was given
( first-item )
及其价值
( (first-agenda-item the-agenda) )
Chapter 3 of SICP 包含这个不寻常的代码块。
(define (propagate)
(if (empty-agenda? the-agenda)
'done
(let ((first-item (first-agenda-item the-agenda)))
(first-item)
(remove-first-agenda-item! the-agenda)
(propagate))))
在我看来,first-item
在这里只用了一次,所以我认为 let
没有必要。是否有任何特殊原因导致以下代码不等价?
(define (propagate)
(if (empty-agenda? the-agenda)
'done
(begin
(first-agenda-item the-agenda)
(remove-first-agenda-item! the-agenda)
(propagate))))
你的转型想法非常好,但你做错了,正如肖恩在评论中所说。
最简单的错误示例是将代码转换成这样:
(let ((f something))
(f)
x)
进入
(begin
something
x)
请注意,此处遗漏了对 (f)
的额外调用:原始版本计算一个函数 然后调用它 ,而转换计算一个函数但抛出它走了。更准确的转换是:
(begin
(something)
x)
"The idea of a
let
block that is not doing variable assignment is strange to me."
但它会进行变量初始化和变量引用。可以写成
(define (propagate)
(if (empty-agenda? the-agenda)
'done
(let ((first-item #f))
(set! first-item (first-agenda-item the-agenda))
(first-item)
(remove-first-agenda-item! the-agenda)
(propagate))))
你写的相当于
(define (propagate)
(if (empty-agenda? the-agenda)
'done
(let ((first-item #f))
(set! first-item (first-agenda-item the-agenda))
first-item ; NB! _No_ _Parens_
(remove-first-agenda-item! the-agenda)
(propagate))))
您的行 (first-agenda-item the-agenda)
returns the-agenda
中的第一个值但未使用它 -- 不对其执行任何操作.
但原始的 (first-item)
通过名称引用该值,first-item
,并且 使用 它即调用该值作为不带参数的函数。
遵循以等代替等的原则,在纯代码中(即只处理值,而不处理任何places in computer memory),我们在代码的纯子集中替换name
; impure: deals with a named place in computer memory
(set! first-item (first-agenda-item the-agenda) )
; pure: refers to a value by the name it was given
( first-item )
及其价值
( (first-agenda-item the-agenda) )