在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

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

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