我是一名Lisp初学者,试图了解如何正确使用Lisp包系统,同时学习LTK进行GUI编程,使用SBCL 1.0.55.0.debian和Limp 0.3.4(如果重要的话还有Debian Wheezy)。我已经使用aptitude包管理器安装了ASDF(包cl-asdf& cl-common-lisp-controller),然后我使用Quicklisp网站(http://www.quicklisp.org/beta/index.html)上的说明安装了Quicklisp(不是来自Debian存储库)然后我在SBCL控制台中安装了(ql:quickload 'ltk)
的LTK。
hello-1.lisp(直接来自LTK教程):
(defun hello-1()
(with-ltk ()
(let ((b (make-instance ’button
:master nil
:text "Press Me"
:command (lambda ()
(format t "Hello World!~&")))))
(pack b))))
如果我在新的SBCL Lisp图像中直接编译,我会收到WITH-LTK
和PACK
是未定义函数的消息,'BUTTON
是未定义的变量。
所以,我发现我需要先加载'ltk
然后再使用in-package
。我能够运行它,我首先必须使用(ql:quickload 'ltk)
和{{1在SBCL控制台中。但是,我仍然是(in-package :ltk)
未定义变量的错误消息。
'BUTTON
然后,由于这没有按照我想要的方式解决,我还尝试根据另一个问题(Problems with ltk (common lisp))的答案来定义我自己的包定义,Xach的博客文章“使用一个小的Lisp项目quickproject和Quicklisp“http://xach.livejournal.com/278047.html?thread=674335和ASDF手册(http://common-lisp.net/project/asdf/asdf/The-defsystem-form.html)使用* (ql:quickload 'ltk)
To load "ltk":
Load 1 ASDF system:
ltk
; Loading "ltk"
(LTK)
* (in-package :ltk)
#<PACKAGE "LTK">
* (compile-file "/home/user/code/lisp/hello-1.lisp")
; caught WARNING:
; undefined variable: ’BUTTON
;
; compilation unit finished
; Undefined variable:
; ’BUTTON
; caught 1 WARNING condition
; /home/user/code/lisp/hello-1.fasl written
; compilation finished in 0:00:00.009
#P"/home/user/code/lisp/hello-1.fasl"
T
T
*
,但没有成功。目前我有以下文件:
package.lisp(如果我第一次quickproject:make-project
SBCL REPL,那就干净地编译):
(ql:quickload 'ltk)
hello-world-ltk.asd(在我第一次编译package.lisp后干净地编译):
(defpackage :hello-world-ltk-system
(:use :cl :asdf :ltk))
hello-world-ltk.lisp(我得到编译错误(in-package :hello-world-ltk-system)
(asdf:defsystem :hello-world-ltk
:serial t
:description "Describe hello-world-ltk here"
:author "Your Name <your.name@example.com>"
:license "Specify license here"
:depends-on (:cl :asdf :ltk)
:components ((:file "package")
(:file "hello-world-ltk")))
)。
The name "HELLO-WORLD-LTK" does not designate any package
当我在成功编译package.lisp和hello-world-ltk.asd(它们都位于同一目录中)后尝试编译这个hello-world-ltk.lisp时,我收到以下错误:
(require 'hello-world-ltk)
(in-package :hello-world-ltk)
(defun hello-world-1 ()
(with-ltk ()
(let ((b (make-instance 'button
:master nil
:text "Press me!"
:command (lambda ()
(format t "Hello world!~&")))))
(pack b))))
所以,我在这里迷失了各种不同的方法来定义包,ASDF,Quicklisp,package.lisp,; compiling (IN-PACKAGE :HELLO-WORLD-LTK)
debugger invoked on a SB-KERNEL:SIMPLE-PACKAGE-ERROR in thread
#<THREAD "initial thread" RUNNING {10029A0FA3}>:
The name "HELLO-WORLD-LTK" does not designate any package.
Type HELP for debugger help, or (SB-EXT:QUIT) to exit from SBCL.
restarts (invokable by number or by possibly-abbreviated name):
0: [ABORT] Exit debugger, returning to top level.
(SB-INT:%FIND-PACKAGE-OR-LOSE "HELLO-WORLD-LTK")
0]
(load "/home/user/code/lisp/hello-world-ltk/hello-world-ltk")
debugger invoked on a SIMPLE-ERROR in thread
#<THREAD "initial thread" RUNNING {10029A0FA3}>:
attempt to load an empty FASL file:
"/home/user/code/lisp/hello-world-ltk/hello-world-ltk.fasl"
Type HELP for debugger help, or (SB-EXT:QUIT) to exit from SBCL.
restarts (invokable by number or by possibly-abbreviated name):
0: [ABORT] Reduce debugger level (to debug level 1).
1: Exit debugger, returning to top level.
(SB-FASL::LOAD-AS-FASL
#<SB-SYS:FD-STREAM
for "file /home/user/code/lisp/hello-world-ltk/hello-world-ltk.fasl"
{1005291233}>
NIL
#<unavailable argument>)
0[2]
,quickproject
,asdf:defsystem
和require
...... ql:quickload
看起来很有希望,但我真的不知道我的源文件还有什么问题。我正在寻找一个解决方案,它应该在整个项目的单个命令中优先处理所有编译和包加载,并且对于更大的项目也应该是可扩展的。
感谢您的帮助:)
答案 0 :(得分:9)
代码中的第一个问题是您使用撇号(’
)而不是刻度线('
)。这就是为什么你得到未定义的变量错误,因为’button
被读作变量名(它没有被引用)。
现在关于包和系统。 包是使用defpackage
定义的,它是符号的集合,在文件(或交互式会话)中的in-package
表单之后使用。包具有内部和外部(导出)符号,可分别作为package::internal-symbol
和package:external-symbol
访问。包也可以import
来自其他包的符号。如果您use-package
,则导入其所有外部符号。虽然in-package
将当前包切换到指定的包,但您开始在其中定义符号(并且不希望在第三方包中执行此类操作,如LTK
)。因此,如果您想使用LTK
或with-ltk
等button
符号,则只需use-package
LTK
或从LTK
导入这些符号以defpackage
形式:
(defpackage :hello-world-ltk-system
(:use :cl)
(:import-from :ltk :with-ltk :button))
或只是导入所有LTK
符号(带use
子句):
(defpackage :hello-world-ltk-system
(:use :cl :ltk))
最后,系统和包是完全无关的事情。 系统是类ASDF:SYSTEM
的一个实例,它包含有关物理文件及其关系的信息,以便可以适当地编译和加载它们。对于你的hello-world应用程序,我建议你现在不用担心系统,并将所有代码写在一个文件中。此文件应以defpackage
表单开头,然后是in-package
,然后是其余代码。
当此文件变得足够大时,您将看到其中的清晰部分,您可以将这些部分分解为单独的文件。然后,您将必须创建一个系统定义文件,如下所示:
(asdf:defsystem :hello-world
:depends-on (:ltk)
:serial t
:components ((:file "package")
(:file "first")
(:file "second")
...))
"package.lisp"
文件现在将保存您的包定义。