【问题标题】:Common Lisp: Beginner's trouble with funcallCommon Lisp:初学者的 funcall 问题
【发布时间】:2010-12-10 05:45:00
【问题描述】:

我正在尝试将一个函数作为参数传递并在另一个函数中调用该函数。

我的一段代码如下所示:

(defun getmove(strategy player board printflag)
(setq move (funcall strategy player board))
(if printflag
    (printboard board))

策略作为符号传递,在二维列表中表示为诸如“随机策略”之类的东西

我不断收到错误: "FUNCALL: 'RANDOMSTRATEGY 不是函数名;请尝试使用符号...

当我用 'randomstrategy 替换策略时,它工作正常。 我也可以独立调用随机策略。 有什么问题?

【问题讨论】:

  • 另外 move 不是一个定义的变量 'randomstrategy 是一个列表:(引用 randomstrategy),你不能调用那个列表。
  • 您的缩进具有误导性,并且您的括号显然不平衡。我怀疑 SETQ 的使用是这里的代码异味。您还应该说明您打算如何调用此函数。

标签: lisp common-lisp


【解决方案1】:

问题在于变量strategy 不包含符号randomstrategy,而是包含列表 (!) 'randomstrategy(这是(quote randomstrategy) 的简写符号)。

现在,您可以,当然,通过函数second 从列表中提取符号,但这只会涵盖真正的问题,这可能是调用的某个地方链。尝试确定为什么传递给函数getmove 的参数是'randomstrategy,而不是应该的randomstrategy。 (也许您在引用列表中错误地使用了引用?)

哦,不要让自己对 (funcall 'randomstrategy ...) 有效这一事实感到困惑:表达式 'randomstrategy 毕竟不是对自身求值,而是对符号 randomstrategy 求值。

【讨论】:

    【解决方案2】:

    strategy 是具有函数值的变量吗?如果不是,那么在它之前使用#' 语法宏,即#'strategy,或者只是(如果函数是全局的)'strategy

    为什么?因为对 funcall 调用的参数进行了评估。在这种情况下,您的 strategy 符号只是一个变量名。变量这个值'RANDOMSTRATEGY。但是你应该给funcall一个函数。如果我们有符号,如何访问函数?

    三种情况:

    1. 符号可以表示具有函数值的变量。
    2. 符号可能表示一个全局函数(symbol-function 在这种情况下是访问器。
    3. 符号可能表示局部函数(flet、标签等)。

    您好像忘记定义 RANDOMSTRATEGY 函数了。

    (defun RANDOMSTRATEGY …)

    FUNCALL:'随机策略

    也许你有(setq strategy ''RANDOMSTRATEGY)

    然后strategy 将评估为'RANDOMSTRATEGY。 您注意到符号名称前的'了吗? 'RANDOMSTRATEGY (quote RANDOMSTRATEGY);这不是一个正确的函数名。

    【讨论】:

    • 什么意思?我说我可以称之为“随机策略”效果很好。这是随机策略函数: (defun randomstrategy(player board) (let*((moves (legalmoves player board))) (r (nth (+ 1(random (- (nth 0 move) 1))) moves))) r ))
    • 也许你写过 (setq strategy ''RANDOMSTRATEGY) ?
    • 策略没有setq。它只是一个函数参数。这不是问题不是吗?
    • 我将如何剥离该报价(?
    • “RANDOMSTRATEGY”如何成为战略的价值?
    【解决方案3】:

    您是否在任何地方制定了策略?这看起来像是一个范围界定问题。

    试试这个

    (setq strategy 'randomstrategy)
    (setq move (funcall strategy player board))
    

    【讨论】:

      【解决方案4】:

      没有看到代码,我在想象你正在做这样的事情:

      (defun randomstrategy (a b c) ...)

      然后这样做:

      (getmove '随机策略 x y z)

      您要做的是使用#'将函数“randomstrategy”传递给getmove:

      (getmove #'randomstrategy x y z)

      在 CommonLisp 中,#' 产生绑定到符号的函数,即 你想要传递给 getmove 的内容。

      【讨论】:

      • 在 Common Lisp 中,用 funcall 符号命名全局函数是完全有效的。
      猜你喜欢
      • 1970-01-01
      • 2013-12-07
      • 2012-03-25
      • 2020-01-04
      • 2020-11-23
      • 2015-03-16
      • 2012-04-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多