2012-04-11 3 views
7

Ich bin ein Lisp Anfänger, der versucht Lisp zu verstehen, während ich LTK für GUI Programmierung erlerne, mit SBCL 1.0.55.0.debian und Limp 0.3.4 (und Debian Wheezy, wenn das wichtig ist). Ich habe ASDF mit aptitude Paket-Manager installiert (Pakete cl-asdf & cl-common-lisp-controller), dann installierte ich Quicklisp mit den Anweisungen auf der Quicklisp-Website (http://www.quicklisp.org/beta/index.html) (nicht aus dem Debian-Repository) und dann habe ich LTK mit (ql:quickload 'ltk) installiert in der SBCL-Konsole.Korrekte Art Pakete mit asdf zu definieren: defsystem und quickproject

hallo-1.lisp (direkt vom LTK Tutorial):

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

Wenn ich diese geradeaus in einem neuen SBCL Lisp Bild zu kompilieren, erhalte ich die Meldung, dass WITH-LTK und PACK undefinierte Funktionen und 'BUTTON ist undefinierte Variable.

So fand ich heraus, dass ich 'ltk und dann verwenden in-package .Ich laden müssen, um sie auszuführen zu können, muss ich zuerst (ql:quickload 'ltk) und (in-package :ltk) in SBCL Konsole verwenden. Allerdings habe ich immer noch eine Fehlermeldung, dass 'BUTTON undefinierte Variable ist.

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

Dann wird, wie dies nicht funktioniert, wie ich wollte, ich auch versucht, auf die Antworten einer anderen Frage nach meiner eigenen Paketdefinitionen zu definieren (Problems with ltk (common lisp)), Xach Blogeintrag „Einen kleinen Lisp-Projekt mit quickproject und Quicklisp "http://xach.livejournal.com/278047.html?thread=674335 und ASDF Handbuch (http://common-lisp.net/project/asdf/asdf/The-defsystem-form.html) mit quickproject:make-project, aber ohne Erfolg. Zur Zeit habe ich die folgenden Dateien:

package.lisp (kompiliert sauber, wenn ich zum ersten Mal (ql:quickload 'ltk) SBCL REPL):

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

Hallo-Welt-ltk.asd (kompiliert sauber, nachdem ich zum ersten Mal package.lisp zusammengestellt):

(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"))) 

Hallo-Welt-ltk.lisp (I kompilieren erhalten Fehler 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))))   

Wenn ich versuche, dieses hallo-Welt-ltk.lisp zu kompilieren nach dem erfolgreichen Kompilieren package.lisp und Hallo-Welt-ltk.asd (die alle im selben Verzeichnis befinden) bekomme ich folgende Fehlermeldung:

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

Also, ich bin hier ganz mit allen verschiedenen Möglichkeiten, verlorene Pakete zu definieren, ASDF, Quicklisp, package.lisp, quickproject, asdf:defsystem, require und ql:quickload ... quickproject:make-project sieht vielversprechend aus, aber ich weiß nicht wirklich Ich weiß, was mit meinen Quelldateien noch nicht stimmt. Ich suche nach einer Lösung, die alle Zusammenstellungen und Paketladungen vorzugsweise in einem einzigen Befehl für das gesamte Projekt behandeln sollte und die auch für größere Projekte erweiterbar sein sollte.

Vielen Dank für jede Hilfe :)

+0

Dies ist keine Antwort, aber eine mögliche Ressource: Ich fand das [Kapitel auf der Verpackung] (http://www.gigamonkeys.com/book/programming-in-the-large-packages-and-symbols.html)) aus dem Buch [Practical Common Lisp] (http://www.gigamonkeys.com/book/), um mir zu helfen, ein besseres Verständnis dafür zu bekommen, wie diese Dinge funktionieren. Vielleicht ist es hilfreich für Sie und/oder andere, die diese Frage ebenfalls finden. – lindes

+0

Ich habe auch dieses Kapitel gelesen, und ich finde es nützlich. Allerdings befasst sich [Practical Common Lisp] (http://www.gigamonkeys.com/book/) nicht mit Systemen, die mit 'asdf: defsystem' erstellt wurden, noch mit der Verwendung von' quickproject'. Vsevolods Antwort (unten) hat mir geholfen, den Unterschied zwischen Paketen und Systemen zu verstehen. – nrz

+0

in der Tat, es ist nur zur Hilfe beim Verständnis der Paketseite der Dinge. Also nur ein Teil des Puzzles. Froh, dass es zumindest ein nützlicher Teil ist. :) – lindes

Antwort

9

Das erste Problem in Ihrem Code ist, dass Sie Apostroph verwenden () statt tick ('). Aus diesem Grund erhalten Sie einen undefinierten Variablenfehler, da ’button als Variablenname gelesen wird (nicht angegeben).

Jetzt in Bezug auf Pakete und Systeme. A Paket ist mit defpackage definiert und es ist eine Sammlung von Symbolen, die nach dem in-package Formular innerhalb einer Datei (oder in interaktiven Sitzung) verwendet werden. Ein Paket hat interne und externe (exportierte) Symbole, auf die als package::internal-symbol bzw. package:external-symbol zugegriffen werden kann. Pakete können auch import Symbole aus anderen Paketen enthalten. Wenn Sie use-package eingeben, importieren Sie alle seine externen Symbole. Während in-package wechselt das aktuelle Paket auf die angegebene und Sie beginnen, Symbole darin zu definieren (und es ist nicht wünschenswert, solche Dinge in 3rd-Party-Pakete zu tun, wie LTK). Also, wenn Sie LTK Symbole verwenden möchten, wie with-ltk oder button, müssen Sie nur entweder use-packageLTK oder diese Symbole importieren aus LTK in Ihrer defpackage Form:

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

oder einfach importieren alle LTK Symbole (mit use Klausel) :

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

Systeme und Pakete Schließlich sind völlig unre Dinge. Ein System ist eine Instanz einer Klasse ASDF:SYSTEM, die Informationen über physische Dateien und ihre Beziehungen enthält, damit sie entsprechend kompiliert und geladen werden können. Für Ihre Hello-World-Anwendung würde ich vorschlagen, dass Sie sich erst einmal nicht um Systeme kümmern und Ihren gesamten Code in eine Datei schreiben. Diese Datei sollte mit einem defpackage Formular beginnen, gefolgt von in-package, und dann den Rest Ihres Codes.

Wenn diese Datei groß genug wird, dass Sie klare Teile darin sehen, können Sie diese Teile in separate Dateien zerlegen. Dann werden Sie eine Systemdefinitionsdatei erstellen müssen, die wie folgt aussehen:

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

Die "package.lisp" Datei wird nun die Paketdefinition halten.

+0

beantwortet. Ich habe Paketdefinitionen in den gleichen Hallo-Welt-ltk verschoben.lisp zusammen mit dem Rest der Quelle und festen Paketdefinitionen, wie Sie vorgeschlagen und feste Paketdefinitionen: '(defpackage: hallo-world-ltk-system' ' (: verwenden: cl) ' ' (: import-from: ltk: mit-ltk: button: pack) ' ' (: export: hallo-world-1)) ' ' (in-paket: hello-world-ltk-system) ' Es erfordert noch' (qt: quickload 'ltk) 'vor dem Kompilieren, aber jetzt funktioniert alles korrekt. Danke für die ausführliche Antwort. – nrz

+0

Ja, das stimmt. Ich habe vergessen zu erwähnen, dass Sie Ihre Abhängigkeiten (welche Systeme sind) irgendwie laden müssen, bevor Sie Ihren eigenen Code laden. Sie müssen '(qt: quickload 'ltk)' am Anfang Ihrer Datei einfügen. Gleiches gilt für andere Abhängigkeiten. Wenn Ihre Anwendung wächst und Sie mehr Bibliotheken verwenden (also Systeme), haben Sie sowieso eine Systemdefinition '.asd' Datei, in der Sie diese Abhängigkeiten angeben. –

+0

'(qt: quickload 'ltk)' scheint nicht zu funktionieren, weil es beim Kompilieren nicht ausgewertet wird, aber das funktioniert: '(eval-when (: compile-toplevel) (ql: quickload' ltk))' [link] (http://stackoverflow.com/questions/9832378/where-should-a-quicklisp-quickload-go-in-my-source-nowhere). Ich denke, das ist eine funktionierende Lösung für Tests und kleine Projekte. – nrz

Verwandte Themen