應用序 or 正則序?
這是《計算機程式的構造與解釋》中的一道習題,如何去判斷一個scheme直譯器是採用什麼方式進行求值的?應用序 or 正則序。應用序是先對引數求值而後應用,而正則序則相反——完全展開而後歸約求值。正則序相比於應用序,會部分存在重複求值的情況。習題是這樣的:
Ben Bitdiddle發明了一種檢測方法,能夠確定直譯器究竟採用的哪種序求值,是採用正則序,還是採用應用序,他定義了下面兩個過程:
分別分析下這兩種情況下直譯器的求值過程:
1.如果直譯器是應用序,將先對過程test的引數求值,0仍然是0,(p)返回的仍然是(p),並且將無窮遞迴下去直到棧溢位,顯然,在這種情況下,直譯器將進入假死狀態沒有輸出。
2.如果直譯器是正則序,完全展開test過程:
一般lisp的直譯器都是採用應用序進行求值。這個問題在習題1.6中再次出現。我們知道scheme已經有一個cond else的特殊形式,為什麼還需要一個if else的特殊形式呢?那麼我們改寫一個new-if看看:
寫幾個過程測試一下:
因為直譯器是應用序求值,將對new-if過程的3個引數求值,其中第三個引數也是一個過程(sqrt_iter (improve guess x) x)) 遞迴呼叫自身,導致無限迴圈直到棧溢位。
Ben Bitdiddle發明了一種檢測方法,能夠確定直譯器究竟採用的哪種序求值,是採用正則序,還是採用應用序,他定義了下面兩個過程:
(define (p) (p))
(define (test x y)
(if (= x 0)
0
y))
而後他求值下列的表示式:(define (test x y)
(if (= x 0)
0
y))
(test 0 (p))
如果直譯器採用的是應用序求值,ben將會看到什麼情況?如果是正則序呢?分別分析下這兩種情況下直譯器的求值過程:
1.如果直譯器是應用序,將先對過程test的引數求值,0仍然是0,(p)返回的仍然是(p),並且將無窮遞迴下去直到棧溢位,顯然,在這種情況下,直譯器將進入假死狀態沒有輸出。
2.如果直譯器是正則序,完全展開test過程:
(define (test 0 (p))
(if (= 0 0)
0
(p))
接下來再進行求值,顯然0=0,結果將返回0。(if (= 0 0)
0
(p))
一般lisp的直譯器都是採用應用序進行求值。這個問題在習題1.6中再次出現。我們知道scheme已經有一個cond else的特殊形式,為什麼還需要一個if else的特殊形式呢?那麼我們改寫一個new-if看看:
(define (new-if predicate then-clause else-clause)
(cond (predicate then-clause)
(else else-clause)))
(cond (predicate then-clause)
(else else-clause)))
寫幾個過程測試一下:
(new-if (< 1 0) 1 0)
結果一切正常,但是,當這3個引數是過程的時候會發生什麼情況呢?在這3個引數如果存在遞迴呼叫等情況下,直譯器也將陷入無限迴圈導致棧溢位!比如書中的求平方根過程用new-if改寫:(define (new-if predicate then-clause else-clause)
(cond (predicate then-clause)
(else else-clause)))
(define (average x y)(/ (+ x y) 2))
(define (square x) (* x x))
(define (improve guess x)(average guess (/ x guess)))
(define (good_enough? guess x)
(< (abs (- (square guess) x)) 0.000001))
(define (sqrt_iter guess x)
(new-if (good_enough? guess x)
guess
(sqrt_iter (improve guess x) x)))
(define (simple_sqrt x)(sqrt_iter 1 x))
(cond (predicate then-clause)
(else else-clause)))
(define (average x y)(/ (+ x y) 2))
(define (square x) (* x x))
(define (improve guess x)(average guess (/ x guess)))
(define (good_enough? guess x)
(< (abs (- (square guess) x)) 0.000001))
(define (sqrt_iter guess x)
(new-if (good_enough? guess x)
guess
(sqrt_iter (improve guess x) x)))
(define (simple_sqrt x)(sqrt_iter 1 x))
因為直譯器是應用序求值,將對new-if過程的3個引數求值,其中第三個引數也是一個過程(sqrt_iter (improve guess x) x)) 遞迴呼叫自身,導致無限迴圈直到棧溢位。
相關文章
- 順序表應用5:有序順序表歸併
- 順序表應用6:有序順序表查詢
- Perl 正則式應用
- CSS規則的執行順序CSS
- 企業IT應用的優先順序甄別
- 系統觸發器的應用順序(四)觸發器
- 系統觸發器的應用順序(三)觸發器
- 系統觸發器的應用順序(二)觸發器
- 系統觸發器的應用順序(一)觸發器
- 正規表示式的用途語法與優先順序(/應為\)
- 大端序、小端序、網路位元組序
- 序 - 用H5技術開發手機應用H5
- django中“url對映規則”和“服務端響應順序”Django服務端
- 中序先序到後序 洛谷1827
- CSS 選擇器優先順序規則CSS
- nginx location規則優先順序比較Nginx
- MFC應用程式中處理訊息的順序
- 《ASP.NET AJAX 應用剖析立即上手》推薦序!ASP.NET
- 1385E. Directing Edges(拓撲序的應用)
- 還原二叉樹(先序+中序-〉後序)二叉樹
- 二叉樹的四種遍歷方法:先序,中序,後序,層序二叉樹
- golang之大端序、小端序Golang
- 譯者序、序、撰稿人
- replace()方法的正則表達相關應用
- Hive SQL語句的正確執行順序HiveSQL
- 層序遍歷在ExtJs的TreePanel中的應用JS
- for 迴圈中倒序 用reverse
- 二叉樹先知道後序和中序,求先序二叉樹
- 遞迴和迭代實現二叉樹先序、中序、後序和層序遍歷遞迴二叉樹
- dfs序
- 【二叉樹】前中序求後序,中後序求前序二叉樹
- 非遞迴遍歷二叉樹的四種策略-先序、中序、後序和層序遞迴二叉樹
- Oracle translate函式和正則的幾個應用Oracle函式
- 實驗二:順序表的基本操作實現及其應用
- 認知與設計:理解UI設計準則——序UI
- 理解C語言宣告的優先順序規則C語言
- C# 中大端序與小端序C#
- 二叉樹 前序、中序、後序二叉樹