将 lambda 绑定到函数或 var 在语义上更正确吗?
Is it more semantically correct to bind a lambda to a function or a var?
我正在编写一个简单的宏,它将一个名称绑定到一个 returns lambda 表达式,但是由于常见的 lisp 具有不同的函数和值的名称空间,我需要 funcall
不管我是用 defun
还是 defvar
包装它。
(defun foo () (lambda-returning-expr))
(defvar bar (lambda-returning-expr))
(funcall (foo)) ; evaluates correctly
(funcall bar) ; also evaluates
那么哪种方法更正确呢?或者更确切地说,lispers 最喜欢哪个?
(defun foo () (lambda-returning-expr))
(defvar bar (lambda-returning-expr))
这两种情况都需要 funcall,例如 (funcall (foo)) 和 (funcall bar) ,但有一个 非常 很大的不同之处在于 (foo) 涉及一个额外的函数调用,它计算 ( lambda-returning-expr) 每次都可以得到不同的函数。
- 如果您预计可能会有不同的函数,那么使用像 foo 这样的函数是合适的。
- 如果您希望只有一个,那么 bar 之类的变量将是合适的。
- 如果您预计 用户 想要更改函数(例如,使用 (let ((bar …)) ...) 作为 API 的一部分,那么变量肯定是有意义的。这在标准中使用,例如 *macroexpand-hook*。如果你需要这样做,那么特殊变量几乎肯定是要走的路,因为 Common Lisp 没有动态作用域的函数。
最近实际上有一个类似的 Scheme 问题,,其中讨论了其中一些问题。
(funcall (foo))
不是一个合适的选择,因为您执行了两个函数调用而不是一个。如果你想制作一个全局函数,你可以使用这个:
(setf (symbol-function 'foo) (lambda (x) x))
(foo 10) ; ==> 10
您也可以使用变量,但请记住 defvar
仅确保变量已绑定。
(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>
顺便说一句:defvar
和 defparameter
生成特殊变量。记住 *earmuffs*
这样你就不会因为动态范围而陷入奇怪的错误。
我正在编写一个简单的宏,它将一个名称绑定到一个 returns lambda 表达式,但是由于常见的 lisp 具有不同的函数和值的名称空间,我需要 funcall
不管我是用 defun
还是 defvar
包装它。
(defun foo () (lambda-returning-expr))
(defvar bar (lambda-returning-expr))
(funcall (foo)) ; evaluates correctly
(funcall bar) ; also evaluates
那么哪种方法更正确呢?或者更确切地说,lispers 最喜欢哪个?
(defun foo () (lambda-returning-expr))
(defvar bar (lambda-returning-expr))
这两种情况都需要 funcall,例如 (funcall (foo)) 和 (funcall bar) ,但有一个 非常 很大的不同之处在于 (foo) 涉及一个额外的函数调用,它计算 ( lambda-returning-expr) 每次都可以得到不同的函数。
- 如果您预计可能会有不同的函数,那么使用像 foo 这样的函数是合适的。
- 如果您希望只有一个,那么 bar 之类的变量将是合适的。
- 如果您预计 用户 想要更改函数(例如,使用 (let ((bar …)) ...) 作为 API 的一部分,那么变量肯定是有意义的。这在标准中使用,例如 *macroexpand-hook*。如果你需要这样做,那么特殊变量几乎肯定是要走的路,因为 Common Lisp 没有动态作用域的函数。
最近实际上有一个类似的 Scheme 问题,
(funcall (foo))
不是一个合适的选择,因为您执行了两个函数调用而不是一个。如果你想制作一个全局函数,你可以使用这个:
(setf (symbol-function 'foo) (lambda (x) x))
(foo 10) ; ==> 10
您也可以使用变量,但请记住 defvar
仅确保变量已绑定。
(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>
顺便说一句:defvar
和 defparameter
生成特殊变量。记住 *earmuffs*
这样你就不会因为动态范围而陷入奇怪的错误。