Exercise 1.41. Define a procedure double that takes a procedure of one argument as argument and returns a procedure that applies the original procedure twice. For example, if inc is a procedure that adds 1 to its argument, then
(double inc)
should be a procedure that adds 2. What value is returned by(((double (double double)) inc) 5)
我用 Python 实现了它。
def double(f):
print(f)
return (lambda x: (f(f(x))))
def inc(x):
return x+1
print(double(inc)(0))
print((double(double))(inc)(0))
print((double(double(double)))(inc)(0)
输出:
<function inc at 0x00000000029BBB70>
2
<function double at 0x0000000002141730>
<function inc at 0x00000000029BBB70>
<function double.<locals>.<lambda> at 0x00000000029BBC80>
4
<function double at 0x0000000002141730>
<function double.<locals>.<lambda> at 0x00000000029BBD08>
<function inc at 0x00000000029BBB70>
<function double.<locals>.<lambda> at 0x00000000029BBBF8>
<function double.<locals>.<lambda> at 0x00000000029BBD90>
<function double.<locals>.<lambda> at 0x00000000029BBE18>
16
我的问题是:
为什么输出
print((double(double(double)))(inc)(0)
是 16 而不是 8?为什么
double
的功能运行时调用了 3 次而不是 2 次(double(double))(inc)(0)
有没有调试工具可以在 python 中设置断点,比如 C 中的“gdb”,以便我调试这个程序?
谢谢!
最佳答案
让我们分析一下您的代码:
print( double(inc)(0) )
所以这将调用带有参数 inc
的函数 double
。因此,正如预期的那样,它将返回一个函数,该函数将对一个参数应用函数 inc
两次。所以你会得到 2 作为输出。你做对了。
现在,有趣的地方来了:
print( (double(double))(inc)(0) )
请注意,您已使用参数 double
调用函数 double
,然后使用参数 inc
调用结果函数。所以这就是发生的事情:
- 调用
double(double)
# 也就是说,double
带有参数double
(第一次调用double
) - 你得到一个函数,它将对参数调用
double
两次 - 您在
inc
上使用该函数。 - 所以你得到一个函数,它将两次应用
double
到inc
(这里有两次调用double
)<
你得到的是一个递增 4 的函数。实际上这不是 2*2,而是 2^2,2^2 = 2*2 = 4 只是巧合(或不巧合),所以你仍然得到 4 的答案。
第三次打印:
print((double(double(double)))(inc)(0)
实际上,您对 double(double)
的结果调用了 double
,这将对自身应用函数 double(double)
两次。如此有效地调用 double(double)(double(double(inc)))
。因此,您应用函数 inc
2*2*(2*2) = 16 次。
为了更好地理解这一点,请注意:
print( double(double(double(inc)))(0) )
将打印 8。
关于python - SICP 练习 1.41,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19107431/