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

nrz*_*nrz 7 lisp sbcl common-lisp 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网站上的说明安装了Quicklisp(http://www.quicklisp.org/beta/index.html) (不是来自Debian存储库)然后我(ql:quickload 'ltk)在SBCL控制台中安装了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))))
Run Code Online (Sandbox Code Playgroud)

如果我在一个新的SBCL Lisp的图像编译这个直上,我得到的消息WITH-LTKPACK未定义功能,'BUTTON是不确定的变量.

所以,我发现我需要加载'ltk,然后再使用in-package.我能够运行它,我首先要使用(ql:quickload 'ltk)(in-package :ltk)在SBCL控制台.但是,我仍然是一个'BUTTON未定义变量的错误消息.

* (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
* 
Run Code Online (Sandbox Code Playgroud)

然后,由于这没有按照我想要的方式解决,我还尝试根据另一个问题的答案定义我自己的包定义(与ltk(常见的lisp)的问题),Xach的博客文章"使用quickproject创建一个小的Lisp项目"和Quicklisp" http://xach.livejournal.com/278047.html?thread=674335和ASDF手册(http://common-lisp.net/project/asdf/asdf/The-defsystem-form.html)使用quickproject:make-project,但没有成功.目前我有以下文件:

package.lisp(如果我第一个(ql:quickload 'ltk)SBCL REPL,则编译得很干净):

(defpackage :hello-world-ltk-system 
  (:use :cl :asdf :ltk))
Run Code Online (Sandbox Code Playgroud)

hello-world-ltk.asd(在我第一次编译package.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")))
Run Code Online (Sandbox Code Playgroud)

hello-world-ltk.lisp(我得到编译错误The name "HELLO-WORLD-LTK" does not designate any package).

(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))))          
Run Code Online (Sandbox Code Playgroud)

当我在成功编译package.lisp和hello-world-ltk.asd(它们都驻留在同一目录中)后尝试编译这个hello-world-ltk.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]
Run Code Online (Sandbox Code Playgroud)

所以,我在这儿住失去了所有不同的方式来定义的包,航空自卫队,Quicklisp,package.lisp, ,,quickproject 和... 看起来很有希望,但我真的不知道什么是错还是我的源文件.我正在寻找一个解决方案,它应该在整个项目的单个命令中优先处理所有编译和包加载,并且对于更大的项目也应该是可扩展的.asdf:defsystemrequireql:quickloadquickproject:make-project

感谢您的任何帮助 :)

Vse*_*kin 11

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

现在关于系统.甲被定义与defpackage和它的符号,这是本之后使用的集合in-package形式的文件中(或在交互会话).包具有内部和外部(导出)符号,可分别作为package::internal-symbol和符号访问package:external-symbol.包也可以import来自其他包的符号.如果您use-package,则导入其所有外部符号.在in-package将当前包切换到指定的包时,您开始在其中定义符号(并且不希望在第三方包中执行此类操作,例如LTK).因此,如果您想使用LTK符号,with-ltk或者button,您只需要在表单中use-package LTK输入或导入这些符号:LTKdefpackage

(defpackage :hello-world-ltk-system 
  (:use :cl)
  (:import-from :ltk :with-ltk :button))
Run Code Online (Sandbox Code Playgroud)

或者只是导入所有LTK符号(带use子句):

(defpackage :hello-world-ltk-system 
  (:use :cl :ltk))
Run Code Online (Sandbox Code Playgroud)

最后,系统是完全不相关的东西.一个系统,是一个类的实例ASDF:SYSTEM,其中包含有关物理文件及其关系的信息,使他们可以编译和适当地加载.对于你的hello-world应用程序,我建议你现在不用担心系统,并将所有代码写在一个文件中.此文件应以defpackage表单开头,然后是in-package,然后是代码的其余部分.

当此文件变得足够大时,您将看到其中的清晰部分,您可以将这些部分分解为单独的文件.然后,您将不得不创建一个系统定义文件,如下所示:

(asdf:defsystem :hello-world
  :depends-on (:ltk)
  :serial t
  :components ((:file "package")
               (:file "first")
               (:file "second")
               ...))
Run Code Online (Sandbox Code Playgroud)

"package.lisp"文件现在将保存您的包定义.

  • 我添加了`(eval-when(:compile-toplevel:load-toplevel:execute)(ql:quickload'ltk))`用于小型测试和学习程序,使用ASDF和适当的系统定义并没有带来那么多优势.我明白,对于使用ASDF而没有任何`(ql:quickload ...)`代码的大型项目,这将是正确的方法.(在之前的评论中有一个拼写错误,它应该是"ql:quickload",而不是"qt:quickload",这可能会使阅读这些评论的人感到困惑.) (2认同)