Common Lisp ltk 'button' class 未找到

Common Lisp ltk 'button' class not found

我正在 Mac 上学习 Common Lisp (Clozure CL) 并在此处慷慨的贡献者的帮助下安装了 quicklisp。 'ltk' 库在 运行ning (ltk::ltk-eyes) 或 (ltk:ltktest) 时工作​​。

运行 (ql:quickload "ltk") 似乎可以正常工作 return 以下内容:

Load 1 ASDF system:
ltk
; Loading "ltk"

我在使用 运行 从 '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))))

然而,当我 运行 (hello-1) 我得到这个:

Error: Class named BUTTON not found. While executing: FIND-CLASS, in process Listener(4). Type cmd-/ to continue, cmd-. to abort, cmd-\ for a list of available restarts. If continued: Try finding the class again Type :? for other options.

我的猜测是 '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 canvas 也出现了,GUI 提醒我这个错误。

感谢您的帮助。

解决方案(感谢@jkiiski 提到 : 运算符):仔细阅读控制台中的错误消息后,我能够解决问题。编译器无法访问 'ltk' 函数 (with-ltk ...) 和 (pack ...) 以及按钮 class。

更正后的代码如下(使用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++ 中找到与 'using namespace' 类似的方法,这样我就不需要继续使用 let: 并简化代码。

Common Lisp 操作属于包的符号。 Lisp reader 负责将对符号的非限定引用解析为实际的限定符号。这取决于当前包绑定到 *PACKAGE* when reading code. As suggested in comments, you should read §21. Programming in the Large: Packages and Symbols from P. Seibel's Practical Common Lisp.

您可以定义自己的包如下:

(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!~&"))))))