普通 Lisp,"defined but never used"
Common Lisp, "defined but never used"
This function compile with warnings, fn is defined and never used in the first line, fn 是未定义的函数第二行:
(defun test-function (fn)
(funcall #'fn))
为什么?对它进行一般性解释或 link 会很棒。
PD:完整日志:
test.lisp:9:1:
style-warning:
The variable FN is defined but never used.
--> PROGN SB-IMPL::%DEFUN SB-IMPL::%DEFUN SB-INT:NAMED-LAMBDA
==>
#'(SB-INT:NAMED-LAMBDA TEST-FUNCTION
(FN)
(BLOCK TEST-FUNCTION (FUNCALL #'FN)))
test.lisp:10:3:
style-warning:
undefined function: FN
==>
(SB-C::%FUNCALL #'FN)
如果要调用作为参数传递的函数或分配给变量的函数,只需将变量或参数用作 funcall
:
的第一个参数
(defun test-function(fn)
(funcall fn))
(test-function #'+)
;; => 0
表示法#'X
是(function X)
的缩写,(见manual),其中X
必须是函数的名称,例如用 defun
或 labels
或 flet
或 lambda 表达式定义的。因此,#'fn
不起作用,因为 fn
不是函数的名称,而是变量(在本例中为参数)。
Common-Lisp是一个Lisp-2,就是函数的命名空间与其他变量的命名空间不同。所以函数的名字是特殊的,因为你可以直接在一个表单中调用它们,而如果一个函数被赋值给一个变量,它必须用 (funcall name-of-the-variable arguments)
.
来调用。
This function compiles with warnings
请注意,这些只是警告:
CL-USER> (defun test-function (fn)
(funcall #'fn))
- 未使用变量
FN
。
- 函数
FN
未定义。
我们来看函数:
(defun test-function (fn) ; this introduces a variable FN
(funcall #'fn)) ; here you use a function FN
由于范围内没有局部函数 FN
,您使用的是全局函数 FN
。在你的情况下,它没有定义。
以后可以定义一个全局函数FN
:
CL-USER> (defun fn ()
'foobar)
FN
这已经可以工作了,因为 Common Lisp 通常还对未定义的函数使用 后期绑定,并会在运行时查找函数。
如果我们再次编译你的原始函数,那么你会看到只剩下一个警告:
CL-USER> (defun test-function (fn) ; the variable FN is defined
(funcall #'fn)) ; the function FN is used
; The variable FN is defined but never used.
这是因为我们现在定义了一个全局函数FN
。
但是:调用全局函数可能不是您想要的,因为这样写起来更容易:
(defun test-function (fn)
(fn)) ; calling the function `FN`.
FUNCALL 用于调用带参数的函数对象:
FUNCALL
的 个典型用例 是使用参数调用函数对象:
(funcall foo 1 2 3)
其中 FOO
是绑定到函数的变量。
在你的情况下,这可能是为了:
CL-USER> (defun test-function (fn) ; a variable FN gets introduced
(funcall fn)) ; a variable FN gets used
记住:(funcall #'foo ...)
看起来不对。
如果你的代码中有类似 (funcall #'foo 1 2 3)
的东西,那么你可能做错了什么,因为它可以更容易地写成 (foo 1 2 3)
.
因此使用 (funcall #'foo 1 2 3)
是一种 代码味道 ,表明您可能想调用一个函数对象,但实际上您是通过它的名称调用一个函数.
This function compile with warnings, fn is defined and never used in the first line, fn 是未定义的函数第二行:
(defun test-function (fn)
(funcall #'fn))
为什么?对它进行一般性解释或 link 会很棒。
PD:完整日志:
test.lisp:9:1:
style-warning:
The variable FN is defined but never used.
--> PROGN SB-IMPL::%DEFUN SB-IMPL::%DEFUN SB-INT:NAMED-LAMBDA
==>
#'(SB-INT:NAMED-LAMBDA TEST-FUNCTION
(FN)
(BLOCK TEST-FUNCTION (FUNCALL #'FN)))
test.lisp:10:3:
style-warning:
undefined function: FN
==>
(SB-C::%FUNCALL #'FN)
如果要调用作为参数传递的函数或分配给变量的函数,只需将变量或参数用作 funcall
:
(defun test-function(fn)
(funcall fn))
(test-function #'+)
;; => 0
表示法#'X
是(function X)
的缩写,(见manual),其中X
必须是函数的名称,例如用 defun
或 labels
或 flet
或 lambda 表达式定义的。因此,#'fn
不起作用,因为 fn
不是函数的名称,而是变量(在本例中为参数)。
Common-Lisp是一个Lisp-2,就是函数的命名空间与其他变量的命名空间不同。所以函数的名字是特殊的,因为你可以直接在一个表单中调用它们,而如果一个函数被赋值给一个变量,它必须用 (funcall name-of-the-variable arguments)
.
This function compiles with warnings
请注意,这些只是警告:
CL-USER> (defun test-function (fn)
(funcall #'fn))
- 未使用变量
FN
。 - 函数
FN
未定义。
我们来看函数:
(defun test-function (fn) ; this introduces a variable FN
(funcall #'fn)) ; here you use a function FN
由于范围内没有局部函数 FN
,您使用的是全局函数 FN
。在你的情况下,它没有定义。
以后可以定义一个全局函数FN
:
CL-USER> (defun fn ()
'foobar)
FN
这已经可以工作了,因为 Common Lisp 通常还对未定义的函数使用 后期绑定,并会在运行时查找函数。
如果我们再次编译你的原始函数,那么你会看到只剩下一个警告:
CL-USER> (defun test-function (fn) ; the variable FN is defined
(funcall #'fn)) ; the function FN is used
; The variable FN is defined but never used.
这是因为我们现在定义了一个全局函数FN
。
但是:调用全局函数可能不是您想要的,因为这样写起来更容易:
(defun test-function (fn)
(fn)) ; calling the function `FN`.
FUNCALL 用于调用带参数的函数对象:
FUNCALL
的 个典型用例 是使用参数调用函数对象:
(funcall foo 1 2 3)
其中 FOO
是绑定到函数的变量。
在你的情况下,这可能是为了:
CL-USER> (defun test-function (fn) ; a variable FN gets introduced
(funcall fn)) ; a variable FN gets used
记住:(funcall #'foo ...)
看起来不对。
如果你的代码中有类似 (funcall #'foo 1 2 3)
的东西,那么你可能做错了什么,因为它可以更容易地写成 (foo 1 2 3)
.
因此使用 (funcall #'foo 1 2 3)
是一种 代码味道 ,表明您可能想调用一个函数对象,但实际上您是通过它的名称调用一个函数.