函数的方案结果

时间:2010-06-26 20:43:08

标签: scheme racket

我在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。 提前致谢

5 个答案:

答案 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)

一方面注意:您需要使用环境模型来解决这个问题。因为词汇范围与动态范围的答案不同。