2010-06-26 66 views
4

我爲我的原始英語提前道歉;我會盡我所能避免語法錯誤等。Scheme,何時使用符號而不是字符串?

兩個星期前,我決定在實施一些數學材料的同時,更新自己對Scheme(及其啓發)的知識,特別是從自動機理論和計算的課程中學習正規語言。

到目前爲止,我已經代表字母作爲符號,而不是字符的

  1. 名單名單,因爲我想擁有可變大小的字母。
  2. 字符串列表,因爲我有點覺得這是不夠的。

我沒經驗,想知道你對這個特定選擇的看法。符號是否被保留用於某種特定的任務,我是否濫用了這些符號?任何對此的評論非常感謝,因爲我正在尋求指導。

在進一步的範圍內,還將有時間來實現字母表上所有可能的單詞集合,這是無限的。我正在考慮通過允許的最大字數來限制這個集合。再次,這是一個好的做法,還是我應該去爲溪流?我覺得流是一個更好的方法,但我還沒有學到它們,所以我不知道使用它們的含義。

無論如何,任何建議或評論是歡迎的。我非常感謝你花時間閱讀我的疑惑。週末愉快!

+0

http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-16.html#%_sec_2.3 – 2010-06-27 07:37:10

回答

7

簡單的區別在於符號的價格比較便宜。可以使用eq?來比較兩個相同的符號。這是因爲在編譯期間,編譯器實際上會枚舉所有帶有數字的符號,因此您只是比較整數,這是一個非常便宜的機器操作。

這意味着當且僅當它們由相同字符組成時,兩個符號是相同的。沒有辦法辨別代碼中具有相同字符的兩個符號,它們是常數,它們是相同的對象,就像33一樣。

然而,兩個字符串可能是不同的對象,它們駐留在不同的內存位置,並且要比較它們需要比較每個字符單獨進行匹配。

所以符號應該,也常常用於此,例如考慮:

(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。

+0

乾杯!您對使用符號的含義有一個非常簡單和簡明的解釋。完全理解你說的沒有汗水的一切:)然後,我會堅持。 順便說一句,因爲我覺得這個線程不會再吸引更多的答案,你有沒有在流上的備用詞或任何其他評論或建議給像我這樣的新手? 無論哪種方式,再次感謝您花時間回答。非常感激。 – Landau 2010-06-27 22:25:39

+0

完成,編輯它。 – Zorf 2010-06-27 22:56:13

+0

精彩博覽會!非常感謝你 :) – Landau 2010-06-28 13:09:32

相關問題