【问题标题】:Understanding sharp quote in common lisp理解普通 lisp 中的尖锐引用
【发布时间】:2019-09-16 04:23:28
【问题描述】:

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

【问题讨论】:

    标签: common-lisp


    【解决方案1】:
    [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
    

    上面使用来自命名函数f 的函数对象调用函数funcallfuncall 然后以3 作为参数调用这个函数对象。

    好像很啰嗦

    是的。

    为什么我既不能发出 (f 3) 也不能发出 (#'f 3)?是否不允许使用尖引号作为表单的第一个元素?

    因为f 没有命名函数。它命名一个变量。 #'f 也不是函数名。我们需要使用函数名(实际上是一个符号)。

    命名空间

    Common 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.

    【讨论】:

    • 谢谢 - 很高兴听到拥有两个命名空间的好处。我可以问一个后续问题吗?我是否使用了 setf,如 (setf f #'abs),我现在知道将函数对象分配给 variable f(not 分配给 function name i> f)”,完全不是惯用语吗?“分配给(符号为)函数名 f”是否仅使用 defun 完成?(我看到它与 fletlabels 一起完成)如果我希望为 variable f 分配一个函数,我可以,那么如果我这样做,我只需要接受我们所指的“冗长的”? ...继续关于符号的章节。 .. 非常感谢 Rainer!
    • @mwal:(setf f ...) 的“主要”问题是 f 到目前为止是一个未定义的变量...
    • @mwal:你可以为函数设置一个变量,但我们需要一个理由......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-13
    • 1970-01-01
    • 2010-12-10
    • 1970-01-01
    • 2011-12-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多