练习1.41。定义一个过程double,它将一个参数的过程作为 参数并返回应用原始过程的过程 两次。例如,如果inc是一个向其参数添加1的过程, 然后
返回(double inc)
应该是一个增加2的过程。什么是值 由(((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中设置断点的调试工具,如&#34; gdb&#34;在C中,我可以调试这个程序吗?
谢谢!
答案 0 :(得分:2)
让我们分析您的代码:
print( double(inc)(0) )
因此,这将使用参数double
调用函数inc
。正如预期的那样,它将返回一个函数,该函数将在参数上应用函数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。
答案 1 :(得分:2)
正如其他人已经回答了要点,这里是一个改进的代码版本,它显示了具有描述性函数名称的执行流程:
def double(f):
print('double({})'.format(f))
def _f(x):
print('{}({})'.format(_f.__name__, x))
return f(f(x))
_f.__name__ = 'double_{}'.format(f.__name__)
return _f
def inc(x):
return x + 1
print(double(inc)(0))
print((double(double))(inc)(0))
print((double(double(double)))(inc)(0))
输出:
double(<function inc at 0x7fb3a9ffa578>)
double_inc(0)
2
double(<function double at 0x7fb3a9ffa500>)
double_double(<function inc at 0x7fb3a9ffa578>)
double(<function inc at 0x7fb3a9ffa578>)
double(<function double_inc at 0x7fb3a9ffa6e0>)
double_double_inc(0)
double_inc(0)
double_inc(2)
4
double(<function double at 0x7fb3a9ffa500>)
double(<function double_double at 0x7fb3a9ffa7d0>)
double_double_double(<function inc at 0x7fb3a9ffa578>)
double_double(<function inc at 0x7fb3a9ffa578>)
double(<function inc at 0x7fb3a9ffa578>)
double(<function double_inc at 0x7fb3a9ffa8c0>)
double_double(<function double_double_inc at 0x7fb3a9ffa938>)
double(<function double_double_inc at 0x7fb3a9ffa938>)
double(<function double_double_double_inc at 0x7fb3a9ffa9b0>)
double_double_double_double_inc(0)
double_double_double_inc(0)
double_double_inc(0)
double_inc(0)
double_inc(2)
double_double_inc(4)
double_inc(4)
double_inc(6)
double_double_double_inc(8)
double_double_inc(8)
double_inc(8)
double_inc(10)
double_double_inc(12)
double_inc(12)
double_inc(14)
16
答案 2 :(得分:1)
double
将其论证应用于自身,正如您明确指出:
lambda x:f(f(x))
那么double(double(double))
是什么?一定是
(double(double))(double(double))
所以,16次。
SUCC(1)。 (是的,Markdown,2!2!2!2!)double(double)
使用双倍调用来生成lambda f: double(double(f))
。将其应用于某些f
(在这种情况下为inc
)需要两次调用double
。所以总共有三个。
SUCC(SUCC(1))。我不知道gdb
是否真的在这里帮助过你。在这种情况下,铅笔和纸β-reduction并不困难,而且很可能更具启发性。
祝SICP好运!