Класс Lisp ltk 'button' не найден

Я изучаю Common Lisp (Clozure CL) на Mac и установил quicklisp, с помощью щедрого участника здесь. Библиотека 'ltk' работает при запуске (ltk::ltk-eyes) или (ltk:ltktest).

Запуск (ql:quickload "ltk"), кажется, работает, поскольку он возвращает следующее:

Загрузка 1 системы ASDF:
ЛТК
; Загрузка "ЛТК"

У меня проблема с запуском следующего кода, взятого из документации 'ltk'. Вот сценарий:

(ql:quickload "ltk") ;my addition to the script

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

Однако, когда я бегу (привет-1) я получаю это:

Ошибка: класс с именем КНОПКА не найден. При выполнении: FIND-CLASS, в процессе Listener(4). Введите cmd-/ для продолжения, cmd-. прервать, cmd-\ для получения списка доступных перезапусков. Если продолжение: попробуйте снова найти класс. для других вариантов.

Я думаю, что библиотека 'ltk' не правильно доступна в определении функции? Я попытался решить проблему с помощью ltk:with-ltk, так как это похоже на функцию ltk.

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

Но это привело к следующей ошибке. Кажется, я все ближе к ее исправлению, так как 2D-холст также появился с графическим интерфейсом, предупреждающим меня об ошибке.

Спасибо за вашу помощь.

2 ответа

Решение

Common Lisp манипулирует символами, которые принадлежат пакетам. Читатель Lisp отвечает за разрешение безусловной ссылки на символ на фактический, квалифицированный символ. Это зависит от текущей привязки пакета к *PACKAGE*при чтении кода. Как предлагается в комментариях, вы должны прочитать §21. Программирование в целом: пакеты и символы из практического общего лиспа П. Сейбеля.

Вы можете определить свой собственный пакет следующим образом:

(defpackage :test-ltk
  (:use :cl :ltk))

:use пункт является декларативным эквивалентом USE-PACKAGE, Вышесказанное делает test-ltk Пакет наследует все внешние символы из пакетов Common Lisp и LTK. Как правило, вы не можете использовать слишком много пакетов вместе, потому что у вас, скорее всего, будут конфликты: два символа, принадлежащие разным пакетам, но имеющие одно и то же имя, не могут быть получены безоговорочно. Это немного похоже на C++, где вам не рекомендуется делать using namespace std,

Чтобы выборочно импортировать одни символы, а не другие, вы используете :import-from вместо. Например, вы можете определить предыдущий пакет следующим образом:

(defpackage :test-ltk
  (:use :cl)
  (:import-from :ltk #:with-ltk #:button #:pack))

Здесь вы только перечислите 3 символа, к которым у вас есть доступ. #:symbol нотация представляет собой непостоянные символы, то есть символы, которые не принадлежат ни к какому пакету и используются только для их имен. Вы могли бы использовать строки (в верхнем регистре) вместо этого.

Затем вы меняете текущий пакет с помощью IN-PACKAGE, Неквалифицированный доступ к символам разрешается в соответствии с определениями текущего пакета:

(in-package :test-ltk)

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

Решение (спасибо @jkiiski за то, что обратились к оператору:): После тщательного прочтения сообщений об ошибках в консоли я смог решить проблему. Компилятору не удалось получить доступ к функциям 'ltk' (with-ltk ...) и (pack ...), а также к классу кнопки.

Исправленный код приведен ниже (использование Quicklisp для использования библиотеки ltk):

(load #P"/Users/myDirectory/quicklisp/setup.lisp")
(ql:quickload "ltk")

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

Мой следующий шаг - посмотреть, смогу ли я найти метод, аналогичный "использованию пространства имен" в C++, чтобы мне не нужно было продолжать использовать let:, и упростить код.

Другие вопросы по тегам