2011-07-11 28 views
7

我不是計劃專家,所以不確定在這裏使用的是正確的術語。讓我們爲自己的代碼說話:計劃中引用的符號

CSI> (define tree '(1 2 3 'Symb 4 5 6)) 
#<unspecified> 
CSI> tree 
(1 2 3 (quote Symb) 4 5 6) 
CSI> (symbol? 'Symb) 
#t 
CSI> (map symbol? tree) 
(#f #f #f #f #f #f #f) 

從Clojure的背景的,我還以爲符號使用這樣的方案,像Clojure的關鍵字。我應該通過嵌套列表結構並用函數調用替換符號。這是我的一維解決方案,它的工作:

(define (print-track track attrs) 
    (apply fmt #t 
     (map (lambda (attr) 
       (cond 
        ((symbol? attr) (get-attr attr track)) 
        (else   attr))) 
      attrs))) 

上述(symbol?)行空的空間是一個(list?)條件,但它可能是錯的形式給出。

我正在使用雞計劃。

回答

18

你已經遇到了Lisp引用「gotcha」。在Scheme中,符號被用於變量引用,你顯然理解它。這評估爲真:

> (symbol? 'Symb) 

因爲你引用了符號,並且阻止它被用作變量引用。

> (symbol? Symb) 

先查找Symb變量的值,然後檢查該值是否爲符號。

> (let ((Symb 'foo)) (symbol? Symb)) 

由於Symb的值爲符號foo,因此計算爲#t。

> (let ((Symb 7)) (symbol? Symb)) 

當然會評價爲#f。

你似乎已經絆倒在一個微妙的報價。

'Symb 

實際上是速記;它相當於

(quote Symbol) 

這又一次返回它的未評估論證。

但是你的代碼不需要內部報價。當你

> (define tree '(1 2 3 'Symb 4 5 6)) 

整個列表被引用; 沒有任何內容將被評估。這就是爲什麼

> tree ; => (1 2 3 (quote Symb) 4 5 6) 

裏面的引用列表'Symb等於(引用Symb),這實際上是一個列表。由於引用了整個列表,因此使用未加引號的符號將不會被視爲變量引用。它只是符號。現在

> (define tree '(1 2 3 Symb 4 5 6)) 
> tree ; => (1 2 3 Symb 4 5 6) 

,如果你通過了所有的參數列表功能,你本來是正確的:

> (define tree (list 1 2 3 'Symb 4 5 6)) 
> tree ; => (1 2 3 Symb 4 5 6) 

在這種情況下,你傳遞這些參數的函數;對函數的參數進行評估,因此您需要引號以防止將符號視爲變量引用。

> (define tree (list 1 2 3 (quote Symb) 4 5 6)) 

會做同樣的事情。

+0

+1爲清晰,徹底 – acfoltzer

+1

一個真的不能寫任何比這更清晰的答案:) – progo