2011-05-01 31 views
2

有沒有一種方法可以在advace中不知道它的情況下輕鬆地引用另一個軟件包中的符號?在common-lisp編譯時未知的其他軟件包中的符號

比方說,我有這樣的包名以下MY-PACKAGE功能

(defun foo-bar (foo bar) 
    `((,foo . foo) 
    (,bar . bar))) 

如果我撥打以上來自同一個包我會得到類似如下:

MY-PACKAGE> (foo-bar 1 2) 
((FOO . 1) (BAR . 2)) 

如果我把它從其它的什麼包,假設CL-USER,符號返回指包MY-PACKAGE:

CL-USER> (my-package:foo-bar 1 2) 
((MY-PACKAGE:FOO . 1) (MY-PACKAGE:BAR . 2)) 

有時,特別是在編寫宏時,我希望將函數返回符號插入調用該函數的包中(在本例中爲CL-USER)。 我已經能夠做到這一點的唯一方法是通過改寫富吧如下

(defun foo-bar (foo bar) 
    `((,(intern "FOO" *package*) . ,foo) 
    (,(intern "BAR" *package*) . ,bar))) 

這很快變得難看,expecially當符號被賦予作爲參數。 有沒有更好的方法來處理這個問題?

回答

1

函數不從包中調用。軟件包僅供閱讀器和符號創建功能(如INTERN)使用。在通話時間,函數的符號已經被放在最初讀取源代碼的包中。對於函數本身來說,如何獲取它的符號名稱並將其調用並不重要。

如果你想根據變量* package *的值在不同的包中創建符號,那麼你必須這麼說。 INTERN是創建新符號的方式,包是一個參數。也可以創建符號而不將它們包裝在包中。

如果符號包不重要,那麼可能需要使用無間斷符號或通常使用關鍵字符號。關鍵字符號被封裝在package關鍵字中並自行評估。

+2

符號包無關緊要的另一種選擇是使用STRING =作爲測試。 – Xach 2011-05-01 16:06:25

+0

感謝您的回答Rainer。我知道我可以使用INTERN,但是我想知道它是否是唯一的選擇,或者是否可以以與我不同的方式完成。我不確定我能否使用無間斷符號,因爲在某些情況下,我需要比較它們的值。我可以使用關鍵字符號或簡單地導出我需要的符號,但它不是我想要的。我正在尋找一些與'loop'宏有關的東西,我可以在這裏寫出例如'(cl:loop for x upto 10 collect x)''不必使用':for'或'cl:for' – 2011-05-06 08:23:32

+0

@Marco Righele:你可以簡單地替換符號。宏在某些包中獲取帶有符號內部的表達式。然後它可以用某種方式遍歷這個表達式,並用標準包中的符號替換特定的內部符號。通常LOOP宏的設計會導致在這些包中創建的符號不被視爲最好的主意。 – 2011-05-06 13:07:11

1

使用INTERN*package*很好如果您確實打算根據上下文在不同的包中實施關聯列表的關鍵符號。但是,請注意*package*可能不會綁定到調用的包,除非您明確地綁定它。您可以通過來解決這個問題,它定義了一個宏而不是一個函數,並在宏擴展時使用*package*綁定。

如果這些符號是作爲函數調用的參數給出的,那麼它們可能已經被包含在函數調用的包中。因此不需要使用INTERN

如果您打開其他方法,Rainer的答案會提供很好的建議,例如使用:foo:bar等關鍵字符號代替。

+0

嗨Terje。感謝您的解釋。該函數已經是宏的一部分,所以它不應該是一個問題。這些符號(可能)已經被實施,但我不知道任何其他方式來說「包'X'」中的符號'foo'(X在調用之前不知道)。 – 2011-05-06 08:57:20

+0

'FIND-SYMBOL name&optional package'查找包中名稱的符號,如果找到,則返回該符號。在呼叫之前,'name'和'package'都可以是未知的字符串。 – 2011-05-06 16:54:56

相關問題