2012-04-11 20 views
7

Jestem początkującym Lispiem próbującym zrozumieć, jak poprawnie używać pakietu Lisp podczas nauki LTK dla programowania GUI, używając SBCL 1.0.55.0.debian i Limp 0.3.4 (i Debian Wheezy, jeśli to ma znaczenie). Zainstalowałem ASDF za pomocą aptitude package manager (pakiety cl-asdf & cl-common-lisp-controller), następnie zainstalowałem Quicklisp używając instrukcji na stronie Quicklisp (http://www.quicklisp.org/beta/index.html) (nie z repozytorium Debiana), a następnie zainstalowałem LTK z (ql:quickload 'ltk) w konsoli SBCL.Właściwy sposób definiowania pakietów za pomocą asdf: defsystem i quickproject

hello-1.lisp (bezpośrednio z samouczka LTK):

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

Jeśli mogę skompilować to prosto w nowym SBCL Lisp obrazu, pojawia się komunikat, że WITH-LTK i PACK funkcje są niezdefiniowane i 'BUTTON jest niezdefiniowana zmienna.

Tak, okazało się, że muszę załadować 'ltk pierwszy, a następnie użyć in-package .I aby móc go uruchomić, najpierw trzeba używać (ql:quickload 'ltk) i (in-package :ltk) w konsoli SBCL. Jednak nadal wyświetlany jest komunikat o błędzie, że 'BUTTON jest niezdefiniowaną zmienną.

* (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 
* 

Potem, jak to nie wyszło jak chciałem, ja też próbowali definiować własne definicje opakowania według odpowiedzi innego pytanie (Problems with ltk (common lisp)), wpisu na blogu Xach za „dokonując niewielkiej Lisp projekt z Quickproject i Quicklisp "http://xach.livejournal.com/278047.html?thread=674335 i ASDF Manual (http://common-lisp.net/project/asdf/asdf/The-defsystem-form.html) używając quickproject:make-project, ale bez powodzenia. Obecnie mam następujące pliki:

package.lisp (kompiluje czysto gdybym najpierw (ql:quickload 'ltk) SBCL REPL):

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

hello-world-ltk.asd (kompiluje czysto po tym, jak po raz pierwszy opracowuje 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"))) 

hello-world-ltk.lisp (otrzymuję błąd kompilacji 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))))   

Gdy próbuję skompilować ten hello-world-ltk.lisp po pomyślnym kompilacji package.lisp i hello-world-ltk.asd (które znajdują się w tym samym katalogu) pojawia się następujący błąd:

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

Tak, jestem zupełnie zagubiony tutaj ze wszystkimi różnych sposobów definiowania pakietów, ASDF, Quicklisp, package.lisp, quickproject, asdf:defsystem, require i ql:quickload ... quickproject:make-project wygląda obiecująco, ale ja naprawdę nie zrobić wiem, co jest nadal nie tak z moimi plikami źródłowymi. Szukam rozwiązania, które powinno obsłużyć wszystkie kompilacje i ładowanie pakietów w jednym poleceniu dla całego projektu i które powinno być rozszerzalne również dla większych projektów.

Dziękuję za pomoc :)

+0

To nie jest odpowiedź, ale możliwy zasób: Znalazłem [rozdział na opakowaniu] (http://www.gigamonkeys.com/book/programming-in-the-large-packages-and-symbols.html) z książki [Practical Common Lisp] (http://www.gigamonkeys.com/book/), aby pomóc mi lepiej zrozumieć, jak działają te rzeczy. Może to być pomocne dla Ciebie i/lub innych, którzy również znajdą to pytanie. – lindes

+0

Czytałem również ten rozdział i uważam, że jest przydatny. Jednak [Practical Common Lisp] (http://www.gigamonkeys.com/book/) nie zajmuje się systemami utworzonymi z 'asdf: defsystem' ani użyciem' quickproject'. Odpowiedź Vsevoloda (poniżej) pomogła mi zrozumieć różnicę między pakietami i systemami. – nrz

+0

w rzeczy samej, jest to tylko pomoc w zrozumieniu strony pakietu rzeczy. Więc tylko część układanki. Cieszę się, że to przydatna część. :) – lindes

Odpowiedz

9

Pierwszy problem w kodzie jest używanie apostrofu () zamiast kleszcza ('). Z tego powodu otrzymujemy niezdefiniowany błąd zmienny, ponieważ ’button jest odczytywany jako nazwa zmiennej (nie jest cytowany).

Teraz dotyczy pakietów i systemów. Pakiet jest zdefiniowany jako defpackage i jest zbiorem symboli, które są używane po formularzu in-package w pliku (lub w sesji interaktywnej). Pakiet ma wewnętrzne i zewnętrzne (eksportowane) symbole, do których można uzyskać dostęp odpowiednio: package::internal-symbol i package:external-symbol. Pakiety mogą również zawierać symbole z innych pakietów. Jeśli przetworzysz use-package, zaimportujesz wszystkie jego zewnętrzne symbole. Podczas gdy in-package przełącza bieżący pakiet na określony i zaczynasz definiować symbole w nim (i nie jest pożądane, aby robić takie rzeczy w pakietach zewnętrznych, takich jak LTK). Więc jeśli chcesz używać LTK symbole, jak with-ltk lub button, wystarczy albo use-packageLTK lub importować te symbole z LTK w formularzu defpackage:

(defpackage :hello-world-ltk-system 
    (:use :cl) 
    (:import-from :ltk :with-ltk :button)) 

lub po prostu zaimportować wszystkie LTK symboli (z use klauzuli) :

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

Wreszcie systemy i pakiety są całkowicie unre Lated rzeczy. System system jest instancją klasy ASDF:SYSTEM, która przechowuje informacje o plikach fizycznych i ich relacjach, dzięki czemu można je odpowiednio skompilować i załadować. Dla twojej aplikacji na cześć świata sugerowałbym, że na razie nie zawracasz sobie głowy systemami i piszesz cały swój kod w jednym pliku. Ten plik powinien rozpoczynać się od formularza defpackage, a następnie in-package, a następnie resztę kodu.

Kiedy ten plik będzie wystarczająco duży, że zobaczysz w nim wyraźne części, możesz je zrekompensować w oddzielnych plikach. Następnie musisz utworzyć plik definicji systemu, który będzie wyglądać następująco:

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

Plik "package.lisp" będą teraz trzymać definicję pakietu.

+0

Przenieśliłem definicje pakietów do tego samego hello-world-ltk.seplenie wraz z resztą źródłowych i stałych definicji pakietów, zgodnie z sugestiami i ustalonymi definicjami pakietów: (defpackage: hello-world-ltk-system' '(: use: cl)' '(: import-from: ltk: with-ltk: button: pack) ' ' (: export: hello-world-1)) ' ' (w pakiecie: hello-world-ltk-system) ' Wymaga jeszcze' (qt: quickload 'ltk) 'przed kompilacją, ale teraz wszystko działa poprawnie. Dziękuję za szczegółową odpowiedź. – nrz

+0

Tak, to prawda. Zapomniałem wspomnieć, że musisz załadować swoje zależności (które są systemami) zanim załadujesz swój własny kod. Musisz więc wstawić '(qt: quickload 'ltk)' na początku pliku. To samo dotyczy innych zależności. Ponieważ aplikacja będzie się rozwijać, a będziesz korzystać z większej liczby bibliotek (które są systemami), będziesz miał plik definicji ".asd", w którym będziesz określał te zależności. –

+0

'(qt: quickload 'ltk)' wydaje się nie działać, ponieważ nie jest oceniane podczas kompilacji, ale działa to: '(eval-when (: compile-toplevel) (ql: quickload' ltk))' [link] (http://stackoverflow.com/questions/9832378/where-should-a-quicklisp-quickload-go-in-my-source-nowhere). Myślę, że to działające rozwiązanie do testów i małych projektów. – nrz

Powiązane problemy