簡單的區別在於符號的價格比較便宜。可以使用eq?
來比較兩個相同的符號。這是因爲在編譯期間,編譯器實際上會枚舉所有帶有數字的符號,因此您只是比較整數,這是一個非常便宜的機器操作。
這意味着當且僅當它們由相同字符組成時,兩個符號是相同的。沒有辦法辨別代碼中具有相同字符的兩個符號,它們是常數,它們是相同的對象,就像3
和3
一樣。
然而,兩個字符串可能是不同的對象,它們駐留在不同的內存位置,並且要比較它們需要比較每個字符單獨進行匹配。
所以符號應該,也常常用於此,例如考慮:
(assq 'symb '((foo 1 2 3) (bar symb) (symb "match")))
這將返回列表(symb "match")
這是便宜,因爲比較:
(assq 4 '((0 1 2 3) (1 symb) (4 "match")))
它返回列表(4 "match")
。但是,使用字符串作爲密鑰assq
不再足夠,它使用eq?
過程進行比較,而必須使用assoc
,該過程使用equal?
過程,由於它遞歸比較結構,因此成本更高。上面的實現實際上足夠便宜,足以經常被用作爲解釋器中的關聯數組和環境建模的一種方式,儘管它當然不是隨機訪問。
編輯:正如你問,在流:
該計劃標準支持一雙很漂亮的,一個是叫force
功能,其他的雖然是叫delay
一個特殊形式。切實什麼
(delay (+ 1 2 3))
或代替(+ 1 2 3)
回報任何其他代碼是所謂的「承諾」,它延遲了這一承諾答案的計算,但承諾,當評價,其結果將是相同的6
我們到達那裏。這似乎是完全無用的,但說其結果將取決於一些變數,這是可以改變的:
(define x 4) ; x is bound to 4.
(let ((promise (delay (+ 2 x)))) ; evaluating the expression now would result into 6, but we delay it.
(set! x 5) ; we change the value of x.
(display (force promise)) ; displays 7
(set! x 6) ; change it again
(force promise) ; ALSO displays 7, not 8
)
很明顯的是,承諾確實只計算一次,並再次用力時,它產生相同的值當第一次評估時。
這是通常用於流或概念性'無限列表'中的內容。在這種情況下,列表的CDR是當它取回其被強制列表的其餘部分的承諾,因爲否則它會變成無窮的計算,例如,一般我們定義:
(define (stream-cdr x) (force (cdr x))) ; it forces that promise to evaluate it.
; and optionally
(define stream-car car) ; same
由於這一個無法評價它的參數,它需要一種特殊的形式:
(define-syntax stream-cons
(syntax-rules()
((stream-cons x y)
(cons x (delay y))))
你的計劃編譯器或解釋現在的(stream-cons x y)
每一次出現轉化爲(cons x (delay y))
對任意x和y。
所以,作爲一個簡單的例子,現在我們的評估被延遲,直到我們需要它,我們可以創建零的無限名單:
(define zero-stream (stream-cons 0 zero-streams))
名單consed達本身,它必將永遠不會終止如果我們沒有使用流,沒用,但它顯示了這個想法。我們可以一次又一次地使用stream-cdr
而不需要到達一個空的列表,我們只是再次獲得相同的「無限的0列表」。
一個更實際的例子是所有的斐波那契數的列表,這是一些 - 什麼更復雜的:
(define fibs
(stream-cons 0 (stream-cons 1
(stream-map + fibs (stream-cdr fibs))))
流圖是法線貼圖的模擬,它的定義很複雜,但我我確定你可以查看它,它自己產生一個流。所以`(stream-map(lambda(x y)(+ 1 x y))置零)將會產生一個完全充滿了它的流。 fibs流本身是遞歸定義的。前兩個元素是給出的,其餘的計算來自兩個流,它們恰好是fibs和fibs本身的流cdr。
http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-16.html#%_sec_2.3 – 2010-06-27 07:37:10