2015-04-03 39 views
3

我正在寫一個簡單的宏,將名稱綁定到返回lambda表達式的表達式,但由於common lisp具有不同的函數和值的名稱空間,所以我需要funcall它無論我是否將它包裝在一個defundefvar將lambda綁定到函數或var更正確的語義?

(defun foo() (lambda-returning-expr)) 
(defvar bar (lambda-returning-expr)) 

(funcall (foo)) ; evaluates correctly 
(funcall bar) ; also evaluates 

那麼哪個更正確的方法?或者說,這是大多數人喜歡的由lispers?

+0

你確定它不是'(funcall(foo))'那有效嗎? – Sylwester 2015-04-03 15:12:05

+0

你知道嗎?我做了很多測試,結果都混在一起了,當然你是對的 – 2015-04-03 15:15:53

回答

4
(defun foo() (lambda-returning-expr)) 
(defvar bar (lambda-returning-expr)) 

您需要爲這兩種情況下funcall,例如(funcall(富))(funcall吧),但有在(富)一非常大的差異涉及一個額外的函數調用,每次評估(lambda-expr-expr),因此每次都可以獲得不同的函數。

  • 如果您預計可能有不同的功能,然後用像功能將是適當的。
  • 如果你期望只有一個,那麼變量,如,將是適當的。
  • 如果您期望用戶到要更改的功能(例如,(讓((巴…))...)作爲API的一部分,那麼一個變量肯定是有道理這是在標準,例如,對於*macroexpand-hook*使用。如果你需要這樣做,那麼特殊的變量是幾乎可以肯定要走的路,因爲Common Lisp中沒有動態範圍的功能。

有竟是類似的Scheme問題最近,Differences between two similar definitions,其中討論了其中一些問題。

2

(funcall (foo))不是老虎機的選擇,因爲你做了兩個函數調用而不是一個。如果你想建立一個全球性的功能,你可以這樣做:

(setf (symbol-function 'foo) (lambda (x) x)) 
(foo 10) ; ==> 10 

可以使用變量太多,但請記住,只有defvar可以確保varible必然。

(defvar *test* 10) 
*test* ; ==> 10 
(defvar *test* (lambda (x) x)) 
*test* ; ==> 10 (not changed since it's already existing) 

如果您希望將其始終設置爲評估表達式,請改爲使用defparameter

(defparameter *test* 10) 
*test* ; ==> 10 
(defparameter *test* (lambda (x) x)) 
*test* ; ==> #<FUNCTION :LAMBDA (X) X> 

BTW:defvardefparameter使得特殊變量。記住*earmuffs*,因爲動態範圍,所以你不會陷入奇怪的錯誤。