现在看看代码,上述操作得到的代码如下所示:
(in-package "COMMON-LISP-USER")
(capi:define-interface hello ()
()
(:panes
(label
capi:title-pane
:text "Input an integer:")
(input
capi:text-input-pane)
(calc
capi:push-button
:text "Calculate")
(output
capi:editor-pane)
(:layouts
(column-layout
capi:column-layout
'(row-layout output))
(row-layout
capi:row-layout
'(label input calc)
:y-adjust :center))
(:menu-bar file help)
(:menus
(help
"Help"
("About"))
(file
"File"
("Quit")))
(:default-initargs
:best-height 110
:best-width 244
:layout 'column-layout
:title "LispWorks/CAPI"))
这是一个扩展了的 Common Lisp 类定义,其中红色的部分定义了窗体里的每一个控件,绿色的部分定义了 Layout 也就是控件之间的位置关系,而黄色的部分定义了菜单。这个演示程序的目的是计算阶乘,通过文本输入框输入的一个整数,在点击按钮后,其阶乘结果将显示在下方的文本编辑框里,核心功能就是这个 N! 函数,使用尾递归方法计算函数 f(n) = n * f(n-1):
(defun n! (n)
(declare (type bignum n))
(labels ((iter (i acc)
(if (zerop i)
acc
(iter (1- i) (* i acc)))))
(the bignum (iter n 1))))上面的 Interface Builder 窗口中的成果使用菜单 File 中的 Save 可以保存所有代码到一个文件里,然后我们修改代码,添加所有必要的参数和回调函数,最后的结果是下面这个样子,我用彩色标示所有添加了的代码部分:
(in-package "COMMON-LISP-USER")
(defun n! (n)
(labels ((iter (i acc)
(if (zerop i)
acc
(iter (1- i) (* i acc)))))
(iter n 1)))
(capi:define-interface hello ()
()
(:panes
(label
capi:title-pane
:text "Input an integer:")
(input
capi:text-input-pane
:reader hello-input)
(calc
capi:push-button
:text "Calculate"
:callback-type :interface
:selection-callback 'cal-callback
:default-p t)
(output
capi:editor-pane
:reader hello-output
:buffer-name "hello"
:line-wrap-marker nil))
(:layouts
(column-layout
capi:column-layout
'(row-layout output))
(row-layout
capi:row-layout
'(label input calc)
:y-adjust :center))
(:menu-bar file help)
(:menus
(help
"Help"
(("About" :selection-callback 'show-about
:callback-type :none)))
(file
"File"
(("Quit" :selection-callback 'quit
:callback-type :none))))
(:default-initargs
:best-height 110
:best-width 244
:layout 'column-layout
:title "LispWorks/CAPI"))
(defun cal-callback (interface)
(let ((input (parse-integer (capi:text-input-pane-text
(hello-input interface))
:junk-allowed t)))
(when input
(setf (capi:editor-pane-text (hello-output interface))
(format nil "~A~%" (n! input))))))
(defun show-about ()
(capi:display-message "Copyright 2008, Chun Tian (binghe)"))
(defun hello ()
(capi:display (make-instance 'hello)))
下面分别介绍一下所有新增代码的用处。
红色部分是计算阶乘的核心函数以及其唯一一次被调用的位置;
绿色部分为 input 和 output 控件定义了 reader 函数,它们被使用的位置也用相同的颜色标识出来,作用是快速访问一个 Interface 示例中的成员;
天蓝色部分定义了回调函数 (callback),回调函数是联系 UI 和功能的纽带,用户点击按钮以后相应的回调函数将会被调用,而回调类型 (callback-type) 则决定了在调用回调函数时使用哪些参数,这里只使用窗体示例作为参数。除了 Lisp 以外我没有见到任何一种 UI 库支持这种特性:可以灵活调整回调函数的参数表。
橙色部分为 editor 文本编辑控件关联了一个新的 buffer 以保存文本,并且将折行时显示的默认字符设置为空;最后黄色部分是回调函数代码 cal-callback 首先得到文本编辑框里的字符串,转化成整数以后调用阶乘函数,然后将结果输出到编辑框里;show-about 函数则在用户点击了菜单的 about 项之后显示一个弹出式消息。最后,
粉色部分是整个代码的入口函数,调用 HELLO 之后整个窗口显示,程序开始运行:
LispWorks 不但可以在编译加载了上述程序以后通过调用 HELLO 函数的方式启动程序,也有能力将这个程序编译成独立的可执行文件。编译过程稍有繁琐,不在这里给出了,运行独立可执行程序的过程见下图:

更难能可贵的是,上述程序在源代码级别是跨操作系统可移植的,在 Mac OS 和 Linux 版的 LispWorks 下运行或者导出成这两个平台下的独立可执行程序也是可以的。下面两张图分别是在 Mac OS X 和 Linux 下运行程序后的样子:(注意 Mac OS 的菜单统一显示在屏幕最上方,所以这里看不到应用程序的菜单)


这就是我所说的──专业级开发工具。现在大家可以理解我为何要砸锅卖铁买 LispWorks 了吧?
(本文相关资料,以及 Windows 版的独立可执行文件,如有需要者请发邮件给我)
后记:函数 n! 的定义中去掉了对参数和返回值的类型声明。
评论