【问题标题】:Why can't I use the function symbol(#') extracted from the list in Common lisp?为什么我不能使用从 Common lisp 列表中提取的函数符号(#')?
【发布时间】:2012-05-18 07:12:09
【问题描述】:

第一个不起作用。 但是第二个有效,这让我感到困惑.. 谁能解释一下?

CL-USER> (funcall (first '(#'+ +)) 1)
; Evaluation aborted on #<TYPE-ERROR expected-type:
;  (OR FUNCTION SYMBOL) datum: #'+>.
CL-USER> (funcall #'+ 1)
1

【问题讨论】:

    标签: function functional-programming lisp common-lisp


    【解决方案1】:

    #' 是一个阅读器宏。 #'+(function +) 的缩写。 ' 是扩展为 (quote …) 的阅读器宏。后者返回未评估的参数。所以,'(#'+ +) 产生((function +) +)#'+ 将在读取时变成(function +))。这里的first 只是列表(function +),它不是一个函数。现在,(function +) 打印为 #'+,这就是您在调试器中看到的内容。

    使用非文字列表将起作用:

    CL-USER> (funcall (first (list #'+ '+)) 1)
    1
    

    【讨论】:

    • 谢谢丹雷。正如你所说,(first '(#'+ +)) 的结果是(function +),对吧?但是为什么它没有自动评估为#'+#'+(function +) 有什么不同?它们不都是函数对象吗?
    • 问题是:为什么不将其评估为函数? (记住#' 只是一个阅读器宏,没有任何东西被“评估为#'+”)。 '(#'+ +) 将被读取为(quote ((function +) +),这发生在读取时间,即读取器宏的扩展。现在,由于 (function +) 在引用的表达式中,它只会不经计算返回,因为这就是 quote 所做的。
    • 读取时间后,#'+(function +) 没有区别。 #'+ 只是扩展为(function +) 的缩写,但这只是一个列表——代码,但仍然是一个列表。所以,(function +) 不是一个函数对象,而是在评估时产生一个函数对象。 quote 评估它的参数,这就是为什么(function +) 保持原样:一个列表(恰好是在评估时返回一个函数对象的代码)。
    • 我明白了。谢谢! (我试过(first '((+ 3 4 ) + 2 3))它返回(+ 3 4)而不是7,然后我明白了~)
    【解决方案2】:

    您的输入是:

     (funcall (first '(#'+ +)) 1)
    

    当我们评估它时,'(#'+ +) 是什么?前面的引号阻止了对表单的评估,所以结果就是读者读到的数据:

    这是一个包含两个项目的列表:

    1. (function +)
    2. +

    通常写为 ((function +) +)。

    请注意,原始输入中的引用明确表示您不想评估列表或其内容。

    现在你在这个名单上打电话给FIRST。结果是第一项:(function +)。这是两个项目的列表:

    1. function
    2. +

    现在你用这个列表和值 1 调用 FUNCALL。

    FUNCALL 需要一个函数或一个符号作为输入。您将列表(function +) 作为第一个参数。 FUNCALL 不知道如何处理它。

    我们如何修复它?您可能想使用评估 (function +) 的结果的函数。

    所以你需要重写你的原始列表。而不是 `'(#'++))' 使用例如:

    (list #'+ '+)
    

    `(,#'+ +)    ; note the backquote in front
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-02-11
      • 2021-09-25
      • 2011-05-12
      • 2020-05-15
      • 2017-07-26
      • 2012-05-25
      • 2014-11-28
      • 2016-06-28
      相关资源
      最近更新 更多