2014-10-21 77 views
3

我在閱讀關於懶惰評估和無法理解他們給出的基本示例。爲什麼不這個球拍代碼終止?

#lang racket 
(define (bad-if x y z) 
    (if x y z)) 
(define (factorial-wrong x) 
    (bad-if (= x 0) 
      1 
      (* x (factorial-wrong (- x 1))))) 

(factorial-wrong 4) 

我有點困惑,爲什麼這個程序永遠不會終止。我知道下面的代碼工作得很好:

(define (factorial x) 
    (if (= x 0) 
     1 
     (* x (factorial (- x 1))))) 

(factorial 4) 

所以我假設它與範圍有關。我試圖一步一步調試和階乘-錯誤執行,即使當x映射到0。

回答

5

標準if

(if test-expr then-expr else-expr) 

將僅評估then-exprelse-expr,取決於遞歸函數test-expr,因爲這if是一個特殊形式句法擴展基於一種特殊的形式,這意味着它做不遵循正常的評估規則。

bad-if另一方面是一個標準程序。在這種情況下,Scheme首先評估兩個表達式,因爲它們是參數bad-if之前實際執行bad-if的參數。所以,即使對於x = 0,(* x (factorial -1))也會被評估,這將依次評估(* x (factorial -2))等等,這是一個無限循環。

+0

所以'if'語句在兩個例子中的行爲是不同的?任何想法爲什麼這樣? – jeebface 2014-10-21 21:46:25

+3

否if語句的行爲完全相同。不同之處在於你稱之爲壞的事實 - 如果這是一個過程。這是強制進行額外評估的程序調用機制。 – uselpa 2014-10-21 21:54:43

+1

爲了進一步說明'if'不是一個過程,如果你在REPL中輸入'bad-if',你應該看到類似'#',而如果你輸入'if ',你應該得到一個'bad-syntax'錯誤。 「或」和「和」也是如此,因爲這兩種形式對於何時評估他們的論點也有特殊的規則。 – Jack 2014-10-21 22:20:49

4

使用步進器!

更具體:

  • 剪去#lang球拍掉你的程序
  • 更改語言級別爲「中級學員」
  • 單擊步驟按鈕的上方。仔細觀察,看看事情發生在哪裏。
+2

'#lang htdp/isl' ;-) – 2014-10-22 04:16:40