在Ubuntu Trusty Tahr上安装《人工智能现代方法》代码时遇到无法在本地声明常量变量的错误 – Common Lisp

我正在安装《人工智能现代方法》这本书的代码,代码来源于这里 http://aima.cs.berkeley.edu/lisp/doc/install.html,顺便说一下,我安装的是Lisp版本

我使用的是Ubuntu Trusty,Emacs SBCL slime环境,我将代码放置在~/.emacs.d目录下

按照上述链接的指示,我运行了(load “/home/w/.emacs.d/aima/code/aima.lisp”)

加载正常,输出为”T”

我运行(aima-load ‘all),这也正常工作,输出为”T”

但是当我运行(aima-compile)时,我得到了以下错误

Can't declare constant variable locally special: +NO-BINDINGS+   [Condition of type SIMPLE-ERROR]

我不太理解这个错误,我查阅了Hyperspec关于Declare和Special的说明,但这并没有帮助。我不反对使用一些技巧来解决这个问题,所以如果有人能帮我重新编写代码,或者告诉我是否有Emacs或SBCL的设置可以更改以正确声明上述变量,那就太好了。错误消息指的是这个文件/home/w/.emacs.d/aima/code/logic/algorithms/tell-ask.lisp

这一部分

(defmethod ask-each ((kb literal-kb) query fn)  "For each proof of query, call fn on the substitution that   the proof ends up with."  (declare (special +no-bindings+))  (for each s in (literal-kb-sentences kb) do       (when (equal s query) (funcall fn +no-bindings+))))

我已经验证了aima文件夹中所有文件的权限都设置为我的用户名可读写,并且我的用户名是所有者,作为纠正措施的一部分…但就理解错误而言,我需要帮助来找出下一步调试的步骤…代码可以从这里下载 http://aima.cs.berkeley.edu/lisp/code.tar.gz,对于有经验的Emacs/Lisp用户来说,安装非常简单…任何帮助都将不胜感激。


回答:

使用SBCL:

我同样尝试加载AIMA代码,在SBCL中遇到了相同的问题。只要在./logic/algorithms/tell-ask.lisp中注释掉这一行:

(declare (special +no-bindings+))

像这样

;;(declare (special +no-bindings+))

,或者完全删除这一行。不过,我所做的就是:

(defmethod ask-each ((kb literal-kb) query fn)  "For each proof of query, call fn on the substitution that   the proof ends up with."  ;;(declare (special +no-bindings+))  (for each s in (literal-kb-sentences kb) do       (when (equal s query) (funcall fn +no-bindings+))))

你仍然会在SBCL中运行(aims-compile)时遇到问题。它会抱怨一些常量被重新定义。只要查看可能的重启选项,每次选择:

0: [CONTINUE] GO ahead and change the value.

根据需要重复这个操作(大约6次),最终它会加载。这可能是由于AIMA的代码非标准构建/编译系统引起的。这可能很烦人,但另一种方法是跟踪代码,看看为什么/在哪里某些文件被重新加载。

使用Clozure (CCL):

CCL在./utilities/utilities.lisp中遇到了不同的问题。CCL预定义了truefalse函数,因此你必须确保直接在(defun true ...)(defun false ...)之前的这两行:

#-(or MCL Lispworks)

更改为:

#-(or MCL Lispworks CCL)

此外,在同一源文件中,修改for-each宏中的error,使其看起来像这样:

(error "~a is an illegal variable in (for each ~a in ~a ...)"   var var list)

有了这些修改,CCL似乎可以正常加载AIMA代码。

总的来说:

重新定义常量或以某种方式绕过调试器重启是一个坏主意。最好的解决方案是让(defconstant ...)只被评估一次,或许通过将它们放置在一个单独的源文件中,并确保构建系统只选择一次。

另一个解决方案在这里找到 这里,它涉及到像这样用宏包装对defconstant的调用(借用自 这里):

(defmacro define-constant (name value &optional doc)  (if (boundp name)      (format t              "~&already defined ~A~%old value ~s~%attempted value ~s~%"              name (symbol-value name) value))  `(defconstant ,name (if (boundp ',name) (symbol-value ',name) ,value)     ,@(when doc (list doc))))

然后像这样替换所有defconstant的出现:

(defconstant +no-bindings+ '((nil))             "Indicates unification success, with no variables.")

替换为:

(define-constant +no-bindings+ '((nil))                 "Indicates unification success, with no variables.")

如果你选择define-constant“解决方案”,请确保define-constant首先被评估。

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注