【问题标题】:Common Lisp `case` on `read` with custom package带有自定义包的“read”上的Common Lisp“case”
【发布时间】:2020-06-18 14:13:50
【问题描述】:

如果我在没有自定义包的 REPL 中运行以下来自 Paul G 的 OnLisp 的代码,它可以正常工作。当我定义一个包并将其与(in-package :mypackage) 一起使用时,它不起作用——它总是在case 语句中采用t 的情况:

(defun run-node (name)
 (let ((n (gethash name *nodes*)))
  (cond ((node-yes n)
         (format t "~A~%>> " (node-contents n))
         (case (read)
           (yes (run-node (node-yes n))) ; never hits this in package
           (t (run-node (node-no n))))) 
        (t (node-contents n)))))

【问题讨论】:

  • 正确格式化代码、缩进代码并提供可重现的测试用例总是有帮助的......

标签: package lisp common-lisp user-input sbcl


【解决方案1】:

首先请注意,您正在做的事情非常危险:对read 的无约束调用可能会导致程序执行任何代码。如果您必须调用read 以获取用户输入,请以安全的方式调用它:

(with-standard-io-syntax
  (let ((*read-eval* nil)
        (*package* ...))
    (read)))

其次,缩进你的代码以便人们阅读:

(defun run-node (name)
  (let ((n (gethash name *nodes*)))
    (cond ((node-yes n)
           (format t "~A~%>> " (node-contents n))
           (case (read)
             (yes (run-node (node-yes n))) ;never hits this in package
             (t (run-node (node-no n))))) 
          (t (node-contents n)))))

现在我们可以注释您的代码(添加一些最小的read-defanging)来向您展示错误是什么:

(defun run-node (name)
  (with-standard-io-syntax
    (let ((n (gethash name *nodes*))
          (*read-eval* nil))
      (cond ((node-yes n)
             (format t "~A~%>> " (node-contents n))
             (let ((got (read)))
               (format *debug-io*
                       "~&*package* ~16T~A~%got package~16T~A~%our package~16T~A~%"
                       (package-name *package*)
                       (typecase got
                         (symbol (package-name (symbol-package got)))
                         (t "(not a symbol"))
                       (package-name (symbol-package 'yes)))
               (case got
                 (yes (run-node (node-yes n))) ;never hits this in package
                 (t (run-node (node-no n))))))
            (t (node-contents n))))))

你会发现,你读到的符号的包和你比较的符号的包不一样,所以符号是不同的。

【讨论】:

    猜你喜欢
    • 2011-12-24
    • 2020-08-01
    • 2020-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多