1

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

运行 (ql:quickload "ltk") 似乎可以工作,因为它返回以下内容:

加载 1 个 ASDF 系统:
ltk
;加载“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) 时,我得到了这个:

错误:找不到名为 BUTTON 的类。执行时: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 画布也出现了,GUI 提醒我错误。

在此处输入图像描述

谢谢你的帮助。

4

2 回答 2

2

Common Lisp 处理属于包的符号。Lisp 阅读器负责将对符号的非限定引用解析为实际的限定符号。这取决于*PACKAGE*阅读代码时绑定的当前包。正如评论中所建议的,您应该阅读§21。大型编程: P. Seibel 的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!~&"))))))
于 2018-03-11T10:37:32.530 回答
1

解决方案(感谢@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: 了,并简化了代码。

于 2018-03-08T23:34:03.140 回答