Common Lisp:如何从Emacs Slime中获取(in-package ...)

时间:2014-11-23 22:45:13

标签: emacs common-lisp slime ccl eval-when

64位Windows 7
Clozure Common Lisp版本1.9 WindowsX8632
Emacs 24.3.1
史莱姆更改日期2014-06-17

我有一个示例.lisp文件,开头如下:

(ql:quickload 'qt)
(in-package "QT")

程序的其余部分显示一个对话框。 当我从命令行wx86cl -load helloqt.lisp运行它时,它似乎工作正常。 当我从Emacs Slime(C-x C-k)运行它时,它说没有包“QT”。 但是,如果我首先单独评估第一行(C-x C-e),那么我可以编译整个事情并且它可以工作,模拟尝试在Windows上的Slime内运行QT线程的正常问题。

如何制作,以便我可以从emacs编译/运行该文件,而无需先手动评估第一行?

另外,为什么(in-package ...)不会更改Slime会话中的当前包?如果我想与包内容进行交互,我必须手动更改它。

1 个答案:

答案 0 :(得分:5)

当您整体编译文件时,它首先作为一个整体读取。那时,尚未对其进行评估,因此尚未定义包QT

您可以使用eval-when在较早时间评估某些内容,或使用系统定义工具(ASDF现在占主导地位)以正确的顺序加载您的系统。

Eval-when

(eval-when (:compile-toplevel :load-toplevel :execute)
  (ql:quickload '#:qt))

(in-package #:qt)

请注意,您通常不应该在库包中捣乱,而是定义自己的新包以保存代码:

(eval-when (:compile-toplevel :load-toplevel :execute)
  (ql:quickload '#:qt))

(defpackage #:qt-example
  (:use #:qt))

(in-package #:qt-example)

;; your code here

(如果您想知道,defpackagedefundefclass等是专门设计的宏,可以扩展到此类eval-when内的表单。 )

对于一些小的一次性脚本,这有时是可以的。对于任何值得注意的系统,特别是只要它们有多个源文件,请使用ASDF:

;;;; qt-example.asd

(in-package #:cl-user)

(asdf:defsystem #:qt-experiments
  :description "Some experiments with QT."
  :serial t
  :components ((:file "package")
               (:file "qt-example"))
  :depends-on (#:qt))

;;;; package.lisp

(defpackage #:qt-example
  (:use #:qt))

;;;; qt-example.lisp

(in-package #:qt-example)

ASDF附带了大多数开源Common Lisp实现。您可能需要设置ASDF注册表。我喜欢为我的所有本地项目提供一个或两个基本目录,以便我可以将以下内容放入~/.config/common-lisp/source-registry.conf

(:source-registry
  (:tree (:home "devel"))
  (:tree (:home "src"))
  :inherit-configuration)

然后,ASDF查找在这些目录下定义的所有系统。在SLIME中,您只需使用REPL中的,load-system,open-system和系统名称来加载它即可。打开其中的所有文件,可选择加载它。

当从文件中编译单个顶层表单(使用C-c C-c)时,SLIME会从那里向后查找in-package表单以找出它应该采用的包。按照惯例,每个文件最多只能有一个in-package表单。

一个常用的快捷方式是Lisp源文件中的C-c ~,它将REPL切换到文件目录和点上的有效包。