2015-04-03 83 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*,因为动态范围,所以你不会陷入奇怪的错误。