Класс 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:, и упростить код.