了解常见Lisp中的引号

mwa*_*wal 1 common-lisp

在下面的实验中,我缩写为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中的符号一章,也许这会有所帮助...感谢任何提示。

Rai*_*wig 7

[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从命名函数调用带有函数对象的函数ffuncall然后使用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