适合交互式Common Lisp开发的load-file方法

3
我希望了解在emacs中进行common-lisp交互式开发的常见方法(我使用sly,但我认为slime的说明应该是相同的)。
假设我有这个文件:
(eval-when (:compile-toplevel :load-toplevel :execute)
  (ql:quickload :closer-mop))

(in-package :cl-user)

(defpackage :shapes
  (:use :closer-common-lisp-user)
  (:export #:rectangle))

(in-package :shapes)

(defclass rectangle ()
  ((height :initform 0.0 :initarg :height)
   (width :initform 0.0 :initarg :width)))

这非常简单。 逐个表达式评估它似乎是可行的,但加载整个文件(C-c C-l)会导致以下错误:

The variable SHAPES:RECTANGLE is unbound.
   [Condition of type UNBOUND-VARIABLE]

将其剥离为
(in-package :cl-user)

(defpackage #:shapes
  (:use #:cl-user)
  (:export #:rectangle))

(in-package #:shapes)

(defclass rectangle ()
  ((height :initform 0.0 :initarg :height)
   (width :initform 0.0 :initarg :width)))

没有做任何更改。

编译并加载(C-c C-k)也无法工作,使我只能使用:

; in: DEFCLASS RECTANGLE
;     (SHAPES::DEFCLASS SHAPES:RECTANGLE NIL
;      ((SHAPES::HEIGHT :INITFORM 0.0 :INITARG :HEIGHT)
;       (SHAPES::WIDTH :INITFORM 0.0 :INITARG :WIDTH)))
; 
; caught COMMON-LISP:STYLE-WARNING:
;   undefined function: SHAPES::DEFCLASS

我看到defclass无法从cl-user:defclass中正确解析,但是找不到解决方法。

我想知道我漏掉了什么? 在Emacs中进行交互式开发的常用流程是什么?


2
closer-common-lisp-user 包不会导出内置的 Lisp 函数。您还需要使用 :use #'common-lisp - Barmar
2
也许有一个叫做CLOSER-COMMON-LISP的软件包。 - Rainer Joswig
1
哇,你们两个的答案都是正确的(毫不意外)。能否请你们将它们移动到实际答案中? - leetwinski
1个回答

6
这里的根本问题是您混淆了CL中包可以使用的两种方式。一个包通常有以下两种用途之一或者两种都有:
1. 可以导出一些符号,这样就提供了某种功能的接口; 2. 可以是其他包被使用的包,也可以从中导入符号,但是不导出任何符号(除非它还是类型1的包)。
虽然这两种包之间没有正式的区别,但往往存在非正式的区别。上述第二种类型的包通常被称为* -USER,其中最典型的例子是CL-USER包。它们通常(但并不总是)作为临时性工作的地方。
所以,您正在定义一个使用列表为这种用户包的包。从您的第二个示例可以看出,你会发现这样不能正常运行,因为这个包的外部符号显而易见。
> (do-external-symbols (s (find-package "CL-USER"))
    (print s))
nil

换句话说,CL-USER不会导出任何符号。这意味着你的SHAPES包最初将无法访问任何符号,特别地,没有CL符号存在。
该语言定义了一个标准的“类型1”包,即CL:这个包的整个目的是导出定义Common Lisp语言的符号,仅限于这些符号。因此,第二个例子中SHAPES包的定义应该是:
(defpackage #:shapes
  (:use #:cl)
  (:export #:rectangle))

(注意,SHAPES 是一种类型 1 的包:它以 SHAPES:RECTANGLE 的形式提供某些功能,并且可能是为了供其他包使用。)
更接近 MOP 提供了两个与标准的 CLCL-USER 包相似的包:
  • CLOSER-COMMON-LISP 类似于 CL,但各种符号被 Closer to MOP 定义的符号替换,而且可能有额外的 MOP 符号;
  • CLOSER-COMMON-LISP-USER 类似于 CL-USER:它是一个旨在普遍使用的包,使用 CLOSER-COMMON-LISP,但不导出任何符号。

好的。整个问题都基于我的误解,用户*-user包重新导出值。谢谢! - leetwinski
2
@leetwinski:是的。如果我的回答过长,让您感到不必要地复杂了,我很抱歉:我希望留下一些未来可能有用的东西。 - user5920214

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接