使用asdf:defsystem和quickproject定义包的正确方法

时间:2012-04-11 19:41:20

标签: lisp common-lisp sbcl asdf quicklisp

我是一名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-LTKPACK是未定义函数的消息,'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] quickprojectasdf:defsystemrequire ...... ql:quickload看起来很有希望,但我真的不知道我的源文件还有什么问题。我正在寻找一个解决方案,它应该在整个项目的单个命令中优先处理所有编译和包加载,并且对于更大的项目也应该是可扩展的。

感谢您的帮助:)

1 个答案:

答案 0 :(得分:9)

代码中的第一个问题是您使用撇号()而不是刻度线(')。这就是为什么你得到未定义的变量错误,因为’button被读作变量名(它没有被引用)。

现在关于系统是使用defpackage定义的,它是符号的集合,在文件(或交互式会话)中的in-package表单之后使用。包具有内部和外部(导出)符号,可分别作为package::internal-symbolpackage:external-symbol访问。包也可以import来自其他包的符号。如果您use-package,则导入其所有外部符号。虽然in-package将当前包切换到指定的包,但您开始在其中定义符号(并且不希望在第三方包中执行此类操作,如LTK)。因此,如果您想使用LTKwith-ltkbutton符号,则只需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"文件现在将保存您的包定义。