2012-04-11 1 views
7

Я начинаю Lisp, пытаясь понять, как правильно использовать систему пакетов Lisp, изучая LTK для программирования GUI, используя SBCL 1.0.55.0.debian и Limp 0.3.4 (и Debian Wheezy, если это имеет значение). Я установил ASDF с помощью диспетчера пакетов aptitude (пакеты cl-asdf & cl-common-lisp-controller), затем я установил Quicklisp, используя инструкции на веб-сайте Quicklisp (http://www.quicklisp.org/beta/index.html) (не из репозитория Debian), а затем я установил LTK с (ql:quickload 'ltk) в консоли SBCL.Правильный способ определения пакетов с использованием asdf: defsystem и quickproject

привет-1.lisp (непосредственно из ЛОК учебника):

(defun hello-1() 
    (with-ltk() 
       (let ((b (make-instance ’button 
             :master nil 
             :text "Press Me" 
             :command (lambda() 
                 (format t "Hello World!~&"))))) 
        (pack b)))) 

Если я компилирую это прямо в новом SBCL Лисп изображения, я получаю сообщение, что WITH-LTK и PACK являются неопределенными функциями и 'BUTTON является Неопределенная переменная.

Итак, я узнал, что мне нужно, чтобы загрузить 'ltk первый, а затем использовать in-package .I, чтобы иметь возможность запустить его, я сначала использовать (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 
* 

Тогда, как это не сработало так, как я хотел, я также пытался определить свои собственные определения пакета в соответствии с ответами другим вопроса (Problems with ltk (common lisp)), запись в блог Xach в «Создании небольшого лисповского проекта с quickproject и Quicklisp "http://xach.livejournal.com/278047.html?thread=674335 и ASDF Manual (http://common-lisp.net/project/asdf/asdf/The-defsystem-form.html) с использованием quickproject:make-project, но безуспешно. В настоящее время у меня есть следующие файлы:

package.lisp (компилируется, если я первый (ql:quickload 'ltk) SBCL РЕПЛ):

(defpackage :hello-world-ltk-system 
    (:use :cl :asdf :ltk)) 

привет-мир-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 <[email protected]>" 
    :license "Specify license here" 
    :depends-on (:cl :asdf :ltk) 
    :components ((:file "package") 
      (:file "hello-world-ltk"))) 

привет-мир-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))))   

При попытке скомпилировать этот привет-мир-ltk.lisp после успешной компиляции package.lisp и привет-мир-ltk.asd (которые все находятся в том же каталоге) Я получаю следующее сообщение об ошибке:

; 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] 

Итак, я совершенно потерял здесь со всеми различными способами, чтобы определить пакеты, ASDF, Quicklisp, package.lisp, quickproject, asdf:defsystem, require и ql:quickload ... quickproject:make-project выглядит многообещающим, но я действительно не узнайте, что еще не так с моими исходными файлами. Я ищу решение, которое должно обрабатывать все компиляции и загрузки пакетов предпочтительно в одной команде для всего проекта, и это должно быть расширяемо для больших проектов.

Спасибо за любую помощь :)

+0

Это не ответ, а возможный ресурс: я нашел [главу на упаковке] (http://www.gigamonkeys.com/book/programming-in-the-large-packages-and-symbols.html) из книги [Practical Common Lisp] (http://www.gigamonkeys.com/book/), чтобы помочь мне лучше понять, как это работает. Возможно, это будет полезно для вас и/или других людей, которые найдут этот вопрос. – lindes

+0

Я тоже читал эту главу, и я считаю ее полезной. Тем не менее, [Practical Common Lisp] (http://www.gigamonkeys.com/book/) не касается систем, созданных с помощью 'asdf: defsystem' или использования' quickproject'. Ответ Всеволода (внизу) помог мне понять разницу между пакетами и системами. – nrz

+0

действительно, это только для помощи с пониманием стороны пакета вещей. Так что только часть головоломки. Рад, что это полезная часть, хотя, по крайней мере. :) – lindes

ответ

9

Первая проблема в вашем коде является то, что вы используете апостроф () вместо клеща ('). Вот почему вы получаете неопределенную переменную ошибку, так как ’button читается как имя переменной (она не цитируется).

Относительно упаковки и системы. A пакет определяется с помощью defpackage и представляет собой набор символов, которые используются после формы in-package внутри файла (или в интерактивном сеансе). Пакет имеет внутренние и внешние (экспортированные) символы, к которым можно получить доступ как package::internal-symbol и package:external-symbol соответственно. Пакеты также могут содержать import символы из других пакетов. Если вы используете use-package, вы импортируете все его внешние символы. В то время как in-package переключает текущий пакет на указанный, и вы начинаете определять в нем символы (и нежелательно делать такие вещи в сторонних пакетах, например LTK). Так что если вы хотите использовать LTK символы, как with-ltk или button, вам просто нужно либо use-packageLTK или импортировать эти символы из 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)) 

Наконец, системы и пакеты полностью unre . Система - это экземпляр класса 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" Файл теперь будет держать ваше определение пакета.

+0

Я переместил определения пакетов на тот же hello-world-ltk.lisp вместе с остальными исходными и фиксированными определениями пакетов, как вы предложили, и фиксированными определениями пакетов: '(defpackage: hello-world-ltk-system' ' (: use: cl) ' ' (: import-from: ltk: с-ltk: button: pack) ' ' (: export: hello-world-1)) ' ' (in-package: hello-world-ltk-system) ' Он по-прежнему требует' (qt: quickload 'ltk) 'перед компиляцией, но теперь все работает правильно. Благодарим вас за подробный ответ. – nrz

+0

Да, это правда. Я забыл упомянуть, что вы должны как-то загружать свои зависимости (которые являются системами), прежде чем загружать свой собственный код. Поэтому вам нужно вставить '(qt: quickload 'ltk)' в начале вашего файла. То же самое относится к другим зависимостям. Поскольку ваше приложение будет расти, и вы будете использовать больше библиотек (которые являются системами), у вас все равно будет файл '.asd' определения системы, в котором вы укажете эти зависимости. –

+0

'(qt: quickload 'ltk)', похоже, не работает, потому что он не получает оценку при компиляции, но это работает: '(eval-when (: compile-toplevel) (ql: quickload' ltk))' [ссылка] (http://stackoverflow.com/questions/9832378/where-should-a-quicklisp-quickload-go-in-my-source-nowhere). Я думаю, что это рабочее решение для тестов и небольших проектов. – nrz

Смежные вопросы