3

全体人员,

我是坚持用 SETF 定义变量的类型之一。我已经升级到一台新机器(和一个新版本的 SBCL),它并没有让我侥幸逃脱(当然,我得到了适当的“==> undefined variable...”错误)

我的问题是,我已经编写了 20,000 行代码(错误地)用 SETF 定义我的变量,我不喜欢重写我的所有代码以让解释器消化所有代码的前景。

有没有办法关闭该错误以便解释可以继续?

任何帮助表示赞赏。

真挚地,

-托德

4

2 回答 2

2

setf一种选择是设置您的包环境,以便使用裸符号my-gross-hack::setf而不是cl:setf. 例如,您可以进行如下设置:

(defpackage #:my-gross-hack
  (:use #:cl)
  (:shadow #:setf))

;;; define your own setf here

(defpackage #:my-project
  (use #:cl)
  (shadowing-import-from #:my-gross-hack #:setf))

;;; proceed to use setf willy-nilly
于 2018-01-22T00:37:34.527 回答
1

您可以处理警告,以便编译终止;这样做时,您可以收集足够的信息来修复您的代码

用 SBCL 1.3.13 测试

处理警告

setf使用未定义的变量时出现警告。以下调用调试器,我可以从中调用muffle-warning

(handler-bind ((warning #'invoke-debugger)) 
  (compile nil '(lambda () (setf *shame* :on-you))))

警告的类型为SIMPLE-WARNING,具有以下访问器:SIMPLE-CONDITION-FORMAT-CONTROLSIMPLE-CONDITION-FORMAT-ARGUMENTS.

(defparameter *setf-declarations* nil)

(defun handle-undefined-variables (condition)
  (when (and (typep condition  'simple-warning)
             (string= (simple-condition-format-control condition)
                      "undefined ~(~A~): ~S"))
    (let* ((arguments (simple-condition-format-arguments condition))
           (variable (and (eq (first arguments) :variable)
                          (second arguments))))
      (when variable
        (proclaim `(special ,variable))
        (push variable *setf-declarations*)
        (invoke-restart 'muffle-warning)))))

将其用作处理程序:

(handler-bind ((warning #'handle-undefined-variables))
  ;; compilation, quickload, asdf ...
  )

上面的处理程序并不健壮:错误消息可能会在未来的版本中发生变化,代码假设参数遵循给定的模式,......但这只需要工作一次,因为从现在开始您将声明所有变量。

修复你的代码

现在你的代码编译好了,去掉丑陋的。或者至少,添加适当的声明。

(with-open-file (out #P"declarations.lisp" :direction :output)
  (let ((*package* (find-package :cl-user)))
    (format out
            "(in-package :cl-user)~%~%~{(defvar ~(~S~))~%~}"
            *setf-declarations*)))

这将遍历您收集的所有符号并将声明写入单个文件中。在我的示例中,它将包含:

(in-package :cl-user)

(defvar *shame*)

通过在编译过程的早期但在定义包之后加载此文件,尝试在不处理错误的情况下干净地重新编译。最终,您可能希望找到时间将这些声明移到setf触发警告的表达式的位置。

于 2018-01-22T15:51:30.830 回答