2011-08-28 29 views
0

比方說,我在R中的下面的宏 RS方案:方案宏 - 在變換中配對,但列出爲輸出?

(define-syntax pair-test 
    (syntax-rules() 
    ((_ (a b . c)) 
     (quote (a b . c))))) 

宏轉換的輸入對的輸出對,正如人們所預料:

(pair-test (1 2 . 3)) 
==> (1 2 . 3) 

我也可以根據規範允許將一個列表傳遞給宏。但是,輸出是一個列表,而不是一對:

(pair-test (1 2 3)) 
==> (1 2 3) 

究竟是怎麼回事?爲什麼輸出是一個列表而不是一對?

回答

5

在第二種情況下可能c(3 .())?我不積極,但這對我來說是有道理的。然後引用(a b . c)就是(1 2 . (3 .()))這就是(1 2 . (3))(3)是一個正確的清單,那麼(1 2 3)

+0

是的。其實c是'(3。())'---你所擁有的額外引號應該不存在---但你基本上是正確的。 –

2

要了解這裏發生了什麼,您需要知道Scheme中的列表是元素對和其他列表的遞歸鏈。任何遵循列表形式的數據將始終打印爲列表。一旦你知道了基本列表是如何構建的,你將能夠看到你的宏中發生了什麼。

Scheme中的對可以使用.運算符或使用cons函數創建。這裏有一個簡單的對數字:

(quote (1 . 2)) 
==> '(1 . 2) 
(cons 1 2) 
==> '(1 . 2) 

要創建1方案列表,你可以做一對出來的東西和空單:

(quote (1 .())) 
==> '(1) 
(cons 1 (list)) 
==> '(1) 

清單2是一對左邊是一些東西,右邊是一個1的列表。同樣,清單3與清單2配對的一個元素:

(quote (1 . (2 . (3 .())))) 
==> '(1 2 3) 
(cons 1 (cons 2 (cons 3 (list)))) 
==> '(1 2 3) 

要查看宏在做什麼,你可以重新排列(quote (a b . c))更加明確:

(quote (a . (b . c))) 
(cons (quote a) (cons (quote b) (quote c))) 

現在你可以看到這個表單看起來與構建列表時非常相似。如果(quote c)產生一個列表,那麼整個表達式將成爲一個列表。在(pair-test (1 2 3))的情況下,變成c(3 .())

(quote (a . (b . c))) 
==> (quote (1 . (2 . (3 .())))) 
==> '(1 2 3) 
(cons (quote a) (cons (quote b) (quote c))) 
==> (cons '1 (cons '2 '(3 .()))) 
==> '(1 2 3) 

此值由REPL印刷作爲一個列表,因爲這是一個「正確列表」。每個右側(cdr)都是一個列表,一直到最後的空列表,所以這個值完全遵循列表形式。 REPL假定您希望將結果看作列表,因此打印時不會出現.

您會看到'(1 2 . 3)(pair-test (1 2 . 3)),因爲這是REPL如何打印「不正確的列表」。如果成對鏈中的最後一個元素不是空列表,則該值被視爲「不正確列表」,並且將以不同的方式打印:

(quote (1 . (2 . 3))) 
==> '(1 2 . 3) 
(cons 1 (cons 2 3)) 
==> '(1 2 . 3)