对SBCL中的``ql:quickload``和可执行脚本感到困惑

时间:2014-09-15 23:09:08

标签: common-lisp sbcl quicklisp

我一直在尝试在我的可执行脚本中使用Quicklisp包。一个(平凡的)工作示例是:

#!/usr/bin/sbcl --script

(eval-when (:compile-toplevel :load-toplevel :execute)
  (ql:quickload "lisp-unit")) ;as explained by another question

(defpackage :test
  (:use :cl :lisp-unit))

(format t "This is a test.")

chmod文件中包含此代码(称为test.lisp)之后,我尝试执行它。但是,我收到以下错误消息:

Unhandled SB-C::INPUT-ERROR-IN-LOAD in thread #<SB-THREAD:THREAD
                                            "main thread" RUNNING
                                             {1002C16923}>:
  READ error during LOAD:

    Package QL does not exist.

      Line: 4, Column: 15, File-Position: 95

      Stream: #<SB-SYS:FD-STREAM
            for "file /home/koz/Documents/Programming/CL/trees/test.lisp"
            {1002C19A93}>

Backtrace for: #<SB-THREAD:THREAD "main thread" RUNNING {1002C16923}>
0: ((LAMBDA NIL :IN SB-DEBUG::FUNCALL-WITH-DEBUG-IO-SYNTAX))
1: (SB-IMPL::CALL-WITH-SANE-IO-SYNTAX #<CLOSURE (LAMBDA NIL :IN SB-DEBUG::FUNCALL-WITH-DEBUG-IO-SYNTAX) {1002C2498B}>)
2: (SB-IMPL::%WITH-STANDARD-IO-SYNTAX #<CLOSURE (LAMBDA NIL :IN SB-DEBUG::FUNCALL-WITH-DEBUG-IO-SYNTAX) {1002C2495B}>)
3: (PRINT-BACKTRACE :STREAM #<SB-SYS:FD-STREAM for "standard error" {1002C14CF3}> :START 0 :FROM :INTERRUPTED-FRAME :COUNT NIL :PRINT-THREAD T :PRINT-FRAME-SOURCE NIL :METHOD-FRAME-STYLE NIL)
4: (SB-DEBUG::DEBUGGER-DISABLED-HOOK #<SB-C::INPUT-ERROR-IN-LOAD {1002C1CB93}> #<unavailable argument>)
5: (SB-DEBUG::RUN-HOOK *INVOKE-DEBUGGER-HOOK* #<SB-C::INPUT-ERROR-IN-LOAD {1002C1CB93}>)
6: (INVOKE-DEBUGGER #<SB-C::INPUT-ERROR-IN-LOAD {1002C1CB93}>)
7: (ERROR #<SB-C::INPUT-ERROR-IN-LOAD {1002C1CB93}>)
8: (SB-C:COMPILER-ERROR SB-C::INPUT-ERROR-IN-LOAD :CONDITION #<SB-INT:SIMPLE-READER-PACKAGE-ERROR "Package ~A does not exist." {1002C1CAA3}> :STREAM #<SB-SYS:FD-STREAM for "file /home/koz/Documents/Programming/CL/trees/test.lisp" {1002C19A93}>)
9: (SB-C::READ-FOR-COMPILE-FILE #<SB-SYS:FD-STREAM for "file /home/koz/Documents/Programming/CL/trees/test.lisp" {1002C19A93}> 25 SB-C::INPUT-ERROR-IN-LOAD)
10: (SB-INT:LOAD-AS-SOURCE #<SB-SYS:FD-STREAM for "file /home/koz/Documents/Programming/CL/trees/test.lisp" {1002C19A93}> :VERBOSE NIL :PRINT NIL :CONTEXT "loading")
11: ((FLET SB-FASL::LOAD-STREAM :IN LOAD) #<SB-SYS:FD-STREAM for "file /home/koz/Documents/Programming/CL/trees/test.lisp" {1002C19A93}> NIL)
12: (LOAD #<SB-SYS:FD-STREAM for "file /home/koz/Documents/Programming/CL/trees/test.lisp" {1002C19A93}> :VERBOSE NIL :PRINT NIL :IF-DOES-NOT-EXIST T :EXTERNAL-FORMAT :DEFAULT)
13: ((FLET SB-IMPL::LOAD-SCRIPT :IN SB-IMPL::PROCESS-SCRIPT) #<SB-SYS:FD-STREAM for "file /home/koz/Documents/Programming/CL/trees/test.lisp" {1002C19A93}>)
14: ((FLET #:WITHOUT-INTERRUPTS-BODY-140 :IN SB-IMPL::PROCESS-SCRIPT))
15: (SB-IMPL::PROCESS-SCRIPT "./test.lisp")
16: (SB-IMPL::TOPLEVEL-INIT)
17: ((FLET #:WITHOUT-INTERRUPTS-BODY-89 :IN SAVE-LISP-AND-DIE))
18: ((LABELS SB-IMPL::RESTART-LISP :IN SAVE-LISP-AND-DIE))

unhandled condition in --disable-debugger mode, quitting

我不确定这里发生了什么 - 如果我尝试从顶层做类似的事情(即,启动SBCL,使用lisp-unit加载ql:quickload等),我不会得到这样的东西。

2 个答案:

答案 0 :(得分:12)

在SBCL中,--script不会加载您的init文件。如果要使用Quicklisp,则必须安排加载它。在使用与Quicklisp相关的任何内容之前,这通常意味着(load "~/quicklisp/setup.lisp")

我不认为SBCL和Quicklisp非常适合编写脚本任务。当我编写脚本时,我通常不希望他们像ql:quickload那样从互联网上获取内容。 Quicklisp也非常冗长。 SBCL的FASL加载非常慢。总而言之,它并没有带来非常好的脚本体验。

我非常强烈希望将我需要使用的所有内容加载到Common Lisp会话中,然后调用函数来完成任务。当我无法使用它时(比如从cron或Makefile中运行东西),我经常使用buildapp来制作可执行文件。

答案 1 :(得分:1)

您应该考虑使用cl-launch,这是为此目的而制作的。您可以通过传递-Q选项启用Quicklisp。您的示例代码将是这样的:

#!/usr/bin/cl -Q -p lisp-unit

(eval-when (:compile-toplevel :load-toplevel :execute)
  (ql:quickload "lisp-unit")) ;as explained by another question
(defpackage :test (:use :cl :lisp-unit))

(defun main (argv) "Code goes here")