我在Scheme中遇到了以下代码:
(define x!
(lambda(x)
(if (= x 1) 1 (* x (x! (- x 1))))))
(define fact x!)
(define x! (lambda (x) x))
(fact 5)
在重新定义x之前,一切都很清楚!并看到函数的结果(20)。 怎么解释?为什么它是20而不是5!= 120。 提前致谢
答案 0 :(得分:4)
以下是发生的事情:
当您(define fact x!)
时,您并未将fact
永久关联到x!
。您将fact
等于 x!
定义时的fact
。
所以(define fact x!)
实际上相当于:
(define fact
(lambda(x)
(if (= x 1) 1 (* x (x! (- x 1))))))
接下来,重新定义x!:
(define x! (lambda (x) x))
但不更改fact
- 它只会更改x!
。接下来,你这样做:
(fact 5)
接下来是解释器“做什么”(实际上可能会稍微有所不同 - 但只是如此,这至少可以帮助您理解程序的行为):
用其定义替换fact
给出:
(lambda(x)
(if (= x 1) 1 (* x (x! (- x 1)))))
用{em> new 定义替换x!
会产生:
((lambda(x)
(if (= x 1)
1
(* x
(- ((lambda (x)
x)
x)
1))))
5)
......简化给出:
((lambda(x)
(if (= x 1)
1
(* x (- x 1))))
5)
...
(if (= 5 1)
1
(* 5 (- 5 1)))
...
(if #f
1
(* 5 (- 5 1)))
......解决条件并简化减法给出:
(* 5 4)
......产生20。
答案 1 :(得分:3)
首先定义x!是计算阶乘的方法(即(x!5)= 120)
然后你定义事实是什么x!是,这是相同的功能(即事实= lambda(x) (if (= x 1)...
然后你改变什么x!是身份。但是,fact
仍然是相同的函数,你没有改变它,但该函数引用了x!在内部,所以它最终调用事实(这是你定义的第一件事)调用身份函数。
所以(fact 5)
与:
(if (= 5 1) 1 (* 5 (x! (- 5 1))))))
与:
相同(if false 1 (* 5 (x! 4)))
与:
相同(if false 1 (* 5 4))
与:
相同(* 5 4)
是20
答案 2 :(得分:3)
当您重新定义标识符时,Scheme的行为方式是使用set!
。在您的情况下,如果您用
(set! x! (lambda (x) x))
然后结果会更清晰。
(请注意,这不是所有计划所做的事情......)
答案 3 :(得分:2)
好的,这里发生的事情如下:
当您在(x! (- x 1))
的原始定义中执行x!
时,您将调用名为x!
的函数。因此,如果您更改名称x!
的含义,则会影响对此x!
的调用。
执行(define fact x!)
时,事实并未引用名称x!
,而是引用x!
的当前内容,即您刚定义的函数。
现在,您更改名称x!
的含义,然后调用(fact 5)
。这将首先调用x!
的原始定义(因为这是事实所指的),但是当它到达调用(x! (- 5 1))
时,它会调用x!
的新定义,返回4 ,所以你得到5 * 4 = 20.
答案 4 :(得分:0)
一方面注意:您需要使用环境模型来解决这个问题。因为词汇范围与动态范围的答案不同。