仔細思考了SICP的練習1.5,對正則序和應用序產生了越來越多的問題,這篇博客不提供解答,只記錄了一些自己的疑惑和思考
最常見的一種正則序應用序的定義方式是,正則序是先展開後規約,應用序是先求值再應用
對於這個定義,產生了幾個問題如下:
- 展開到什麼程度
- 什麼順序展開
- 什麼時候會求值
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)
返回是什麼呢