在下面的实验中,我缩写为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
Run Code Online (Sandbox Code Playgroud)
这是否意味着系统功能与用户定义功能的区别?
为了完整性:
[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
Run Code Online (Sandbox Code Playgroud)
我还没有进入ANSI Common Lisp中的符号一章,也许这会有所帮助...感谢任何提示。
[235]> (setf f #'abs) ; I'm ok with this
#<SYSTEM-FUNCTION ABS>
Run Code Online (Sandbox Code Playgroud)
上面的方法设置了一个命名f
为函数对象的变量-来自名为的函数abs
。
[236]> (abs 3) ; This is fine
3
Run Code Online (Sandbox Code Playgroud)
上面叫做函数abs
。
[237]> (f 3) ; Err due to sep. fn namespace. OK.
Run Code Online (Sandbox Code Playgroud)
上图:没有名为的函数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"
Run Code Online (Sandbox Code Playgroud)
上图:Common Lisp仅接受符号作为函数名称,符号作为宏名称,符号作为特殊运算符或lambda表达式作为cons形式的第一个元素。(function f)
不是函数名称。
这是否意味着系统功能与用户定义功能的区别?
没有。
[239]> (funcall #'f 3) ; seems very long winded...!
3
Run Code Online (Sandbox Code Playgroud)
上面funcall
从命名函数调用带有函数对象的函数f
。funcall
然后使用3
作为参数调用此函数对象。
似乎很long
它是。
为什么我既不发出(f 3)也不发出(#'f 3)?是否不允许将尖引号作为表格的第一要素?
因为f
没有命名功能。它命名一个变量。#'f
也不是函数名称。我们需要使用一个函数名(实际上是一个符号)。
命名空间
普通Lisp(和其他Lisp方言一样)有两个用于函数和变量的名称空间。
定义一个变量foo
:
CL-USER 54 > (defvar foo 3)
FOO
Run Code Online (Sandbox Code Playgroud)
定义功能foo
:
CL-USER 55 > (defun foo (x) (* foo 10))
FOO
Run Code Online (Sandbox Code Playgroud)
我们可以foo
使用从变量获取的值来调用函数foo
:
CL-USER 56 > (foo foo)
30
Run Code Online (Sandbox Code Playgroud)
如何从函数的全局名称获取函数对象:
CL-USER 57 > (fdefinition 'foo)
#<interpreted function FOO 4060001CAC>
CL-USER 58 > (symbol-function 'foo)
#<interpreted function FOO 4060001CAC>
Run Code Online (Sandbox Code Playgroud)
与上述相同,但有一个简短的符号:
CL-USER 58a > #'foo
#<interpreted function FOO 4060001CAC>
CL-USER 59 > (function foo) ; works also for local functions
#<interpreted function FOO 4230008AAC>
Run Code Online (Sandbox Code Playgroud)
如何从全局变量获取值:
CL-USER 60 > (symbol-value 'foo)
3
Run Code Online (Sandbox Code Playgroud)
或者只是使用变量:
CL-USER 61 > foo
3
Run Code Online (Sandbox Code Playgroud)
一些积极的方面:
正面:没有名字冲突。
我们可以写
(defun foo (list) (list list))
Run Code Online (Sandbox Code Playgroud)
而且不必写
(defun foo (lst) (list lst))
Run Code Online (Sandbox Code Playgroud)
正面:更简单的编译
(let ((list 3))
(list 1 list 3))
Run Code Online (Sandbox Code Playgroud)
以上永远不会是Common Lisp中的错误。在Scheme中,将出现错误:3 is not a function
。