在下面的实验中,我缩写为REPL返回错误,并添加了[num],以便在讨论中可以参考。
我对为什么调用存储在变量中的函数的尝试失败感到困惑。在我看来,语法比需要的复杂。
为什么我既不发行(f 3)
也不发行(#'f 3)
?
是否不允许将尖引号作为表格的第一要素?
为什么这里需要funcall
?
[235]> (setf f #'abs) ; I'm ok with this
#<SYSTEM-FUNCTION ABS>
[236]> (abs 3) ; This is fine
3
[237]> (f 3) ; Err due to sep. fn namespace. OK.
-- Err[1]: "Undefined function f" --
[238]> (#'f 3) ; Don't get what this err is telling me...
-- Err[2]: "#'F is not a function name, try using a symbol instead"
[239]> (funcall #'f 3) ; seems very long winded...!
3
这是否意味着系统功能与用户定义功能的区别?
出于完整性考虑:
[240]> (funcall abs 3)
-- Err[3]: variable ABS has no value -- ; I get why this is an error.
[241]> (funcall #'abs 3) ; Isn't this verbose... ?
3
我还没有进入ANSI Common Lisp中的符号一章,也许对您有所帮助。
答案 0 :(得分:7)
[235]> (setf f #'abs) ; I'm ok with this
#<SYSTEM-FUNCTION ABS>
以上将设置为f
的变量设置为函数对象-来自名为abs
的函数。
[236]> (abs 3) ; This is fine
3
上面调用了函数abs
。
[237]> (f 3) ; Err due to sep. fn namespace. OK.
以上:没有名为f
的函数。
-- Err[1]: "Undefined function f" --
[238]> (#'f 3) ; Don't get what this err is telling me...
-- Err[2]: "#'F is not a function name, try using a symbol instead"
以上:Common Lisp仅接受符号作为函数名称,符号作为宏名称,符号作为特殊运算符或lambda表达式作为cons形式的第一个元素。 (function f)
不是函数名称。
这是否意味着系统功能与用户定义功能的区别?
否。
[239]> (funcall #'f 3) ; seems very long winded...!
3
上面用命名函数funcall
中的函数对象调用函数f
。 funcall
然后以3
作为参数调用此函数对象。
似乎缠绕很长
是的。
为什么我既不发行(f 3)也不发行(#'f 3)?不允许将尖引号作为表格的第一要素吗?
因为f
未命名函数。它命名一个变量。 #'f
也不是函数名称。我们必须使用函数名称(实际上是一个符号)。
命名空间
公用Lisp(与其他Lisp方言一样)有两个用于函数和变量的命名空间。
定义变量foo
:
CL-USER 54 > (defvar foo 3)
FOO
定义函数foo
:
CL-USER 55 > (defun foo (x) (* foo 10))
FOO
我们可以使用从变量foo
获得的值来调用函数foo
:
CL-USER 56 > (foo foo)
30
如何从函数的全局名称获取函数对象:
CL-USER 57 > (fdefinition 'foo)
#<interpreted function FOO 4060001CAC>
CL-USER 58 > (symbol-function 'foo)
#<interpreted function FOO 4060001CAC>
与上述相同,但用一个简短的符号表示:
CL-USER 58a > #'foo
#<interpreted function FOO 4060001CAC>
CL-USER 59 > (function foo) ; works also for local functions
#<interpreted function FOO 4230008AAC>
如何从全局变量获取值:
CL-USER 60 > (symbol-value 'foo)
3
或者只使用变量:
CL-USER 61 > foo
3
一些肯定:
正面:没有名字冲突。
我们可以写
(defun foo (list) (list list))
也不必写
(defun foo (lst) (list lst))
正面:更简单的编译
(let ((list 3))
(list 1 list 3))
以上在Common Lisp中永远不会是错误。在Scheme中,这将是错误:3 is not a function
。