2012-04-11 18 views
7

Tôi là người mới bắt đầu Lisp cố gắng hiểu cách sử dụng đúng hệ thống gói Lisp trong khi học LTK để lập trình GUI, sử dụng SBCL 1.0.55.0.debian và Limp 0.3.4 (và Debian Wheezy nếu điều đó quan trọng). Tôi đã cài đặt ASDF bằng cách sử dụng trình quản lý gói aptitude (gói cl-asdf & cl-common-lisp-controller), sau đó tôi cài đặt Quicklisp bằng cách sử dụng các hướng dẫn trên trang web Quicklisp (http://www.quicklisp.org/beta/index.html) (không phải từ kho Debian) và sau đó tôi đã cài đặt LTK với (ql:quickload 'ltk) trong giao diện điều khiển SBCL.Cách xác định gói bằng cách sử dụng asdf: defsystem và quickproject

hello-1.lisp (trực tiếp từ LTK hướng dẫn):

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

Nếu tôi biên dịch này thẳng vào trong một hình ảnh SBCL Lisp mới, tôi nhận được thông điệp rằng WITH-LTKPACK là chức năng không xác định và 'BUTTON là biến không xác định. Vì vậy, tôi phát hiện ra rằng tôi cần phải tải 'ltk trước và sau đó sử dụng in-package. Tôi để có thể chạy nó, trước tiên tôi phải sử dụng (ql:quickload 'ltk)(in-package :ltk) trong bảng điều khiển SBCL. Tuy nhiên, tôi vẫn là một thông báo lỗi rằng 'BUTTON là biến không xác định.

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

Sau đó, vì điều này đã không diễn ra như tôi muốn, tôi cũng đã cố gắng để xác định định nghĩa gói của riêng tôi theo câu trả lời của một câu hỏi khác (Problems with ltk (common lisp)), blog entry xách của "Làm một dự án Lisp nhỏ với quickproject và Quicklisp "http://xach.livejournal.com/278047.html?thread=674335 và Hướng dẫn sử dụng ASDF (http://common-lisp.net/project/asdf/asdf/The-defsystem-form.html) sử dụng quickproject:make-project, nhưng không thành công. Hiện nay tôi có các tập tin sau đây:

package.lisp (biên dịch sạch nếu tôi lần đầu tiên (ql:quickload 'ltk) SBCL REPL):

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

hello-thế giới ltk.asd-(biên dịch sạch sau khi tôi đã lần đầu tiên biên soạn 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 (Tôi nhận được lỗi biên dịch 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))))   

Khi tôi cố gắng để biên dịch này hello-thế giới ltk.lisp-sau khi biên dịch thành công package.lisp và hello-thế giới ltk.asd-(mà tất cả nằm trong cùng một thư mục) tôi nhận được lỗi sau:

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

Vì vậy, tôi hoàn toàn bị mất ở đây với tất cả các cách khác nhau để xác định gói, asdf, Quicklisp, package.lisp, quickproject, asdf:defsystem, requireql:quickload ... quickproject:make-project trông đầy hứa hẹn, nhưng tôi thực sự không biết những gì vẫn còn sai với các tập tin nguồn của tôi. Tôi đang tìm một giải pháp mà nên xử lý tất cả các compilations và tải gói tốt hơn trong một lệnh duy nhất cho toàn bộ dự án và đó nên được mở rộng cho các dự án lớn hơn quá.

Cảm ơn bạn cho bất kỳ sự giúp đỡ :)

+0

Đây không phải là câu trả lời, nhưng có thể là tài nguyên: Tôi tìm thấy [chương về đóng gói] (http://www.gigamonkeys.com/book/programming-in-the-large-packages-and-symbols.html) từ cuốn sách [Thực tế thường gặp Lisp] (http://www.gigamonkeys.com/book/) để giúp ích trong việc giúp tôi hiểu rõ hơn về cách thức hoạt động của những thứ này. Có lẽ nó sẽ hữu ích cho bạn và/hoặc những người khác tìm thấy câu hỏi này, là tốt. – lindes

+0

Tôi cũng đã đọc chương đó và tôi thấy nó hữu ích. Tuy nhiên, [Thực tế thường gặp Lisp] (http://www.gigamonkeys.com/book/) không xử lý các hệ thống được tạo ra với 'asdf: defsystem' cũng như không sử dụng 'quickproject'. Câu trả lời của Vsevolod (bên dưới) đã giúp tôi hiểu sự khác biệt giữa các gói và hệ thống. – nrz

+0

thực sự, nó chỉ là để được giúp đỡ với sự hiểu biết bên gói của sự vật. Vì vậy, chỉ là một phần của câu đố. Vui mừng đó là một phần hữu ích, mặc dù, ít nhất. :) – lindes

Trả lời

9

Vấn đề đầu tiên trong mã của bạn là bạn sử dụng dấu nháy đơn () thay vì đánh dấu ('). Đó là lý do tại sao bạn nhận được lỗi biến không xác định, vì ’button được đọc là tên biến (nó không được trích dẫn).

Hiện tại liên quan đến góihệ thống. Gói được định nghĩa với defpackage và đó là tập hợp các biểu tượng được sử dụng sau biểu mẫu in-package bên trong tệp (hoặc trong phiên tương tác). Một gói có các biểu tượng bên trong và bên ngoài (xuất khẩu), có thể được truy cập tương ứng là package::internal-symbolpackage:external-symbol. Các gói cũng có thể import các biểu tượng từ các gói khác. Nếu bạn use-package, bạn nhập tất cả các ký hiệu bên ngoài của nó. Trong khi in-package chuyển gói hiện tại sang gói được chỉ định và bạn bắt đầu xác định các ký hiệu trong đó (và không muốn thực hiện những thứ như vậy trong gói của bên thứ ba, chẳng hạn như LTK). Vì vậy, nếu bạn muốn sử dụng LTK biểu tượng, như with-ltk hoặc button, bạn chỉ cần một trong hai use-packageLTK hoặc nhập khẩu các biểu tượng từ LTK ở dạng defpackage của bạn:

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

hoặc đơn giản là nhập khẩu tất cả các LTK biểu tượng (với use khoản) :

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

Cuối cùng, hệ thống gói là hoàn toàn unre những thứ lated. Hệ thống là phiên bản của lớp ASDF:SYSTEM, chứa thông tin về tệp vật lý và quan hệ của chúng, để chúng có thể được biên dịch và tải một cách thích hợp. Đối với ứng dụng hello-world của bạn, tôi sẽ đề nghị, rằng bạn không bận tâm về hệ thống cho bây giờ, và viết tất cả các mã của bạn trong một tập tin. Tệp này phải bắt đầu bằng biểu mẫu defpackage, tiếp theo là in-package và sau đó là phần còn lại của mã của bạn.

Khi tệp này sẽ phát triển đủ lớn, bạn sẽ thấy các phần rõ ràng trong đó, bạn có thể tính các phần đó thành các tệp riêng biệt. Sau đó, bạn sẽ phải tạo tệp định nghĩa hệ thống, sẽ trông giống như sau:

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

Tệp "package.lisp" giờ đây sẽ giữ định nghĩa gói của bạn.

+0

Tôi đã chuyển định nghĩa gói thành cùng hello-world-ltk.lisp cùng với phần còn lại của định nghĩa gói nguồn và cố định, như bạn đã đề xuất và định nghĩa gói cố định: '(defpackage: hello-world-ltk-system' ' (: use: cl) ' ' (: import-from: ltk: with-ltk: button: pack) ' ' (: xuất khẩu: hello-world-1)) ' ' (trong gói: hello-world-ltk-system) ' Nó vẫn yêu cầu' (qt: quickload 'ltk) 'trước khi biên dịch nhưng bây giờ mọi thứ hoạt động chính xác. Cảm ơn bạn đã trả lời chi tiết. – nrz

+0

Vâng, đó là sự thật. Tôi quên đề cập đến, rằng bạn phải bằng cách nào đó tải phụ thuộc của bạn (đó là hệ thống) trước khi bạn tải mã của riêng bạn. Vì vậy, bạn phải chèn '(qt: quickload 'ltk)' vào đầu tệp của bạn. Điều tương tự cũng áp dụng cho các phụ thuộc khác. Khi ứng dụng của bạn sẽ phát triển và bạn sẽ sử dụng nhiều thư viện hơn (đó là các hệ thống), bạn sẽ có một tệp '.asd' định nghĩa hệ thống, trong đó bạn sẽ chỉ định những phụ thuộc đó. –

+0

'(qt: quickload 'ltk)' dường như không hoạt động, bởi vì nó không được đánh giá khi biên dịch, nhưng nó hoạt động: '(eval-when (: compile-toplevel) (ql: quickload' ltk))' [link] (http://stackoverflow.com/questions/9832378/where-should-a-quicklisp-quickload-go-in-my-source-nowhere). Tôi nghĩ rằng đây là một giải pháp làm việc cho các thử nghiệm và các dự án nhỏ. – nrz

Các vấn đề liên quan