首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SICP练习1.41

SICP练习1.41
EN

Stack Overflow用户
提问于 2013-10-01 03:26:55
回答 3查看 429关注 0票数 2

练习1.41.定义了一个过程double,它以一个参数的过程为参数,并返回一个应用原始过程两次的过程。例如,如果inc是一个向其参数添加1的过程,那么(double inc)应该是一个添加2的过程。

我用Python实现了它。

代码语言:javascript
复制
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)

输出:

代码语言:javascript
复制
<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

我的问题是:

  1. 为什么print((double(double(double)))(inc)(0)的输出是16而不是8?
  2. 为什么double函数在运行(double(double))(inc)(0)时被调用3次而不是2次
  3. 是否有任何调试工具可以在python中设置断点,比如C中的"gdb“,以便我可以调试这个程序?

谢谢!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-10-01 03:59:09

让我们分析一下您的代码:

代码语言:javascript
复制
print( double(inc)(0) )

因此,这将使用参数double调用函数inc。因此,正如预期的那样,它将返回一个函数,该函数将对一个参数应用函数inc两次。所以你会得到2作为输出。你做得对。

有趣的一点是:

代码语言:javascript
复制
print( (double(double))(inc)(0) )

注意,您已经用参数double调用函数double,然后用参数inc调用结果函数。这就是所发生的事:

  1. 调用double(double) #,即带有参数doubledouble (第一次调用double)
  2. 您将得到一个函数,它将在参数上调用两次double
  3. 您可以在inc上使用该函数。
  4. 因此,您将得到一个函数,它将向double应用两次inc (这里有两次对double的调用)

实际上,这不是2*2,而是2^2,这只是巧合(或者不是),2^2 = 2*2 = 4,所以你仍然可以得到4的答案。

第三版:

代码语言:javascript
复制
print((double(double(double)))(inc)(0)

实际上,您对double的结果调用double(double),这将对其本身应用double(double)函数两次。实际上你是在打电话给double(double)(double(double(inc)))。所以应用函数inc 2*2*(2*2) = 16次。

要更好地理解这一点,请注意:

代码语言:javascript
复制
print( double(double(double(inc)))(0) )

会打印8张。

票数 3
EN

Stack Overflow用户

发布于 2013-10-01 04:03:26

其他人已经回答了要点,下面是您的代码的一个改进版本,它显示了带有描述性函数名称的执行流:

代码语言:javascript
复制
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))

产出:

代码语言:javascript
复制
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
EN

Stack Overflow用户

发布于 2013-10-01 03:53:13

  1. double将其参数应用于自身,正如您明确指出的那样: lambda x: f(f(x)) 那么double(double(double))是什么?一定是 (双(双)) 所以,16次。
  2. double(double)使用对double的调用来生成lambda f: double(double(f))。将其应用于某些f (本例中的inc)需要对double进行两次调用。总共有三个。
  3. 我不知道gdb是否真的会在这里帮助你。铅笔和纸β-还原在这种情况下并不难,而且很可能更能说明问题。

祝SICP好运!

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19107431

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档