2013-10-01 119 views
2

練習1.41。定義一個程序雙它有一個參數的步驟, 參數,並返回適用原程序 兩次的過程。例如,如果INC是加1,其參數的程序,然後 應該(double inc)是增加了2.程序 通過(((double (double double)) inc) 5)SICP練習1.41

我實現了它在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 

我的問題是:

  1. 爲什麼的print((double(double(double)))(inc)(0)輸出是16而不是8?

  2. 爲什麼運行(double(double))(inc)(0)

  3. 是否有任何的調試工具,可以用設定斷點蟒蛇像「廣發行」,這樣我可以調試該程序時的double函數被調用3次而不是2倍?

謝謝!

+0

您可以使用'pdb'('import pdb; pdb.Pdb().set_trace()'是一個「斷點」)或Python支持的IDE,比如PyCharm(「社區版」現在是免費的)。 –

回答

2

我們來分析一下你的代碼:

print(double(inc)(0)) 

因此,這將調用該函數double與參數inc。如預期的那樣,它將返回一個函數,該函數將兩次應用函數inc作爲參數。所以你會得到2作爲輸出。你已經做到了這一點。

現在,有趣的是在這裏:

print((double(double))(inc)(0)) 

注意,您必須調用函數double的說法double,然後調用導致函數參數inc。因此,這是什麼情況:

  1. 呼叫double(double)#就是double與參數double(先打電話double
  2. 你得到一個函數,它會呼籲
  3. 您使用該參數double兩次功能inc
  4. 等你拿這將適用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
  1. double應用其參數本身,因爲你清楚地表明:

    拉姆達X = F(F(X))

有啥double(double(double))?它必須是

(double(double))(double(double)) 

因此,16次。

SUCC(1)。 (是的,減價,2!2!2!2!)double(double)使用一個電話加倍產生lambda f: double(double(f))。將其應用於一些finc在這種情況下),需要兩次調用double。總共有三個。

SUCC(SUCC(1))。我不知道gdb會在這裏幫助你。鉛筆和紙β-reduction在這種情況下並不困難,而且可能更有啓發性。

祝SICP!

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 
+0

這很可愛!哈哈 – justhalf