1. 程式人生 > >刷SICP遇到的問題——深入學習理解正則序和應用序

刷SICP遇到的問題——深入學習理解正則序和應用序

仔細思考了SICP的練習1.5,對正則序和應用序產生了越來越多的問題,這篇部落格不提供解答,只記錄了一些自己的疑惑和思考

最常見的一種正則序應用序的定義方式是,正則序是先展開後規約,應用序是先求值再應用

對於這個定義,產生了幾個問題如下:

  1. 展開到什麼程度
  2. 什麼順序展開
  3. 什麼時候會求值

1 正則序展開到什麼程度

書上的正則序定義是這樣的"Instead it would first substitute operand expressions for parameters until it obtained an expression involving only primitive operators, and would then perform the evaluation."

因此,正則序會展開到只剩下primitive operators,就是Scheme裡面不需要自己define就可以呼叫的operators

2 正則序以什麼順序展開

來看練習1.5

Exercise 1.5.  Ben Bitdiddle has invented a test to determine whether the interpreter he is faced with is using applicative-order evaluation or normal-order evaluation. He defines the following two procedures:

(define (p) (p))

(define (test x y)
  (if (= x 0)
      0
      y))

Then he evaluates the expression

(test 0 (p))

What behavior will Ben observe with an interpreter that uses applicative-order evaluation? What behavior will he observe with an interpreter that uses normal-order evaluation? Explain your answer.

(Assume that the evaluation rule for the special form if is the same whether the interpreter is using normal or applicative order: The predicate expression is evaluated first, and the result determines whether to evaluate the consequent or the alternative expression.)

意思就是,這段程式碼在正則序和應用序的直譯器上會有不同的表現,為什麼

先不考慮這道題是怎麼做,來看看正則序是如何展開(test 0 (p))的,這裡有兩個combination,是先展開(p)還是(test)

看一下書上的正則序展開示例

所以是先展開最左側的括號,想想也是,如果先展開(p)那和應用序有什麼區別嘛

3 應用序什麼時候求值

這個問題來源於我不小心寫錯了題目中的程式碼, 寫成了如下的樣子

(define (p) (p))

(define (test x y)
  (if (= x 0)
      0
      y))

(test 0 p)

直譯器完美執行,返回了0

為什麼這裡應用序不求解p了?

寫一個程式碼檢測

(define (p)
  (display "yes\n"))

(define (testOrder x y)
  (display "test\n")
  (if (= x 0)
      0
      y))

(testOrder 0 p)
(testOrder 0 (p))

 

結果很明顯,沒有給p加括號,根本不會去呼叫p, 我想了一下,有了一個猜想(不一定對),p是作為一個類似函式指標一樣的東西傳給testOrder的,所以對p的求值只是獲取到了他的函式指標

一個佐證是,用lazyracket這個正則序直譯器執行如下程式

#lang lazy
(define (p)
  (p))

(define (testOrder x y)
  (if (= x 0)
      0
      y))

(testIOrder 1 p)

返回是什麼呢