Cusp 是 Common Lisp 编程语言的开发环境。使用 Lisp 可以开发所有类型的应用程序,包括 Web 应用程序。Lisp 是目前仍在使用的第二种最古老的编程语言(在 Fortran 之后)并被称为第一种函数语言。Lisp 的创建开始于二十世纪五十年代后期,并且于 1958 年由 MIT 人工智能 (AI) 项目首次实现。它的强大之处在于处理列表:AI 和符号数学。实际上,Lisp 是 “list processor” 的简写,正是出于对列表处理器的需求创建了这种编程语言,您将在稍后的段落中看到相关说明(有关 Lisp 的历史信息,请参阅 参考资料)。
您将会发现 Lisp 与其他普通的编程语言根本不同。例如,在大多数普通编程语言中,执行乘法就像您在纸上作运算一样:int times = 5 * 5;。
使用 Lisp,将通过代码 (* 5 5 3) 得到 75。要获得此列表中的最大值,使用 (MAX 9 8 7 6 20) 将返回 20。
注意,这里所说的 “第一种函数语言” 十分贴切,因为一切都基于函数。每个函数都可以有若干数目不定的参数。使用递归和诸如 car 和 cdr 之类的 Lisp 函数处理这些列表是使用 Lisp 处理列表的强大之处。
由于 Lisp 历史较久,因此您可以找到许多适用于 Lisp 的开发环境,但是,也存在旧编程语言固有的问题,工具支持大部分都是基于文本的,并且对于新手来说不够直观。因此,尝试使用 Cusp 的一个原因是它提供了供新手了解和开发 Lisp 的直观 GUI,而不使用基于文本的 “尝试记住所有这些命令” 类型的界面。它还比 Eclipse GUI 框架固有的 superb 项目管理功能更具优势。
继续之前,您需要从 Eclipse.org 下载最新的 Eclipse 标准包。然后了解如何安装和设置 Cusp。
现在应当有一个经过压缩的 Eclipse 标准包归档。请将其解压缩并运行 eclipse.exe。
要获得最新版本的 Cusp,请单击 Help > Software Updates > Find and Install。单击 Search
for new features to install 选项。现在单击 New Remote Site 按钮。键入名称 Cusp update site 和 URL http://www.sergeykolos.com/cusp/update,然后单击 OK(参见图 1)。
图 1. 为 Cusp 输入远程站点信息
单击已添加的新远程站点旁边的复选框并单击 Finish(参见图 2)。
图 2. 选择 Cusp Eclipse Update Site
系统将显示另一个窗口,在该窗口中需要展开 Cusp Eclipse Update Site 并选择 Cusp,如下所示:
图 3. 选择要安装的功能
单击 Next。然后阅读许可证协议并单击 I accept the terms in the license agreement 接受许可证协议,然后单击 Next。确保选中所有库,如下所示,然后再次单击 Next。
图 4. 选择可选功能
最后一个页面将显示要安装功能的安装汇总。单击 Finish。插件及其组件将下载并安装。下载后,您将收到一则警告,表明将要安装一个未签名的功能。单击 Install all。在安装结束时,系统将询问您是否要重新启动 Eclipse;请单击 Yes。
您已经安装了 Eclipse Cusp 插件。接下来,将创建一个 Lisp 项目。
在开始进行 Lisp 开发之前,必须先创建一个新的 Lisp 项目。您可以通过转到 File > New > Project 来完成此操作。展开 Lisp 文件夹,单击 Lisp Project,然后单击 Next。为新项目选择一个名称 my_new_lisp_project,如下所示,然后单击 Finish。
图 5. 命名新 Lisp 项目
单击 Finish 后,将创建新项目并打开 Lisp 透视图,如下所示:
图 6. Lisp 透视图
查看 Lisp 透视图。Lisp Navigator 窗口显示打开的项目及其相关文件。Outline 窗口显示当前打开文件的概要。位于右上侧显示 main.lisp 的窗口是 Lisp 开发窗口。位于右下侧的窗口 REPL 是 Lisp 的命令行 Lisp 解析程序,您可以在这里运行 Lisp 命令。
如果关闭并重新打开 Eclipse,则需要装入项目的 .asd 文件,如下所示:
图 7. 装入 ASD 文件
注意,需要在 my_new_lisp_project 文件夹下的 my_new_lisp_project.asd 文件上右键单击,然后选择 Load asd。这实际上就是在 REPL 窗口中编译 Lisp 项目,允许您输入可以使用新代码的 Lisp 命令。
接下来,将尝试使用 Cusp 进行一些 Lisp 开发。
首先,还是定义并测试一个简单的自定义函数。打开 main.lisp 文件,并使用 defun(定义函数)命令,然后添加以下内容:
... (defun first_howdy_function () "howdy ho") |
保存该文件。要从包中导出函数,请在 defpackage.lisp 中键入以下代码:
... ;; Exported symbols go here first_howdy_function )) |
可以从包的外部使用该函数。要测试新函数,请在 REPL 中位置靠下的窗口中键入以下代码:(my_new_lisp_project:first_howdy_function)。
注意,在您所处的范围内,这样做与输入 (my_new_lisp_project::first_howdy_function) 等效。如果未在 defpackage.lisp 中导出函数,则这是您必须键入的代码。
单击 Send,然后查看输出。输入上面任意一条命令所得到的输出都是:
COMMON-LISP-USER> (my_new_lisp_project:first_howdy_function) "howdy ho" |
您已经得到它了:第一个 Lisp Howdy 函数。
尝试为 echo 函数提供一个输入:
... (defun first_echo_function (echoval) echoval) |
同上一个函数一样,将其导出到 defpackage.lisp 中。在 REPL 窗口中位置靠下的部分中键入以下代码 (my_new_lisp_project:first_echo_function '("howd" "y h" "o")) 来测试这个 first_echo_function。注意,'("howd" "y h" "o") 部分是用于定义列表的语法。首先,单引号必须放在括号之前,然后在括号内定义列表元素。输出如下所示:
COMMON-LISP-USER>
(my_new_lisp_project:first_echo_function '("howd" "y h" "o"))
("howd" "y h" "o")
|
您将创建一种分别处理每个列表元素的方法,这是 Lisp 的真正强大之处。定义如下:
(defmethod concat2 ((str1 string) (str2 string)) (concatenate 'string str1 str2)) |
注意,以上方法实际上定义了一个类型字符串。到现在为止,您一直在使用 Lisp 作为一种大型的无类型语言。虽然双引号隐式地把数据类型定义为字符串,但是以上方法显式地把 concat2 函数的输入和输出类型定义为字符串。此方法还使用内置的 concatenate 函数把两个字符串组合在一起,并将其作为单个字符串返回。
要测试 concat2,请将其导出,然后键入 (my_new_lisp_project:concat2 "howd" "y ho")。输出如下:
清单 7. 连接两个字符串的输出
COMMON-LISP-USER>
(my_new_lisp_project:concat2 "howd" "y ho")
"howdy ho"
|
完成。字符串 "howd" 和 "y ho" 变成 "howdy ho"。现在您将使用两个著名的 Lisp car 和 cdr 函数创建更通用化的 concatenation 函数。
清单 1. 连接列表中的三个元素
(defun concat3 (args_list)
(concat2 (car args_list)
(concat2 (car (cdr args_list))
(car (cdr (cdr args_list))))))
|
注,此函数仍使用 concat2 函数,但是使用参数列表作为输入。注意如何从 args_list 检索连接的各个部分。car 将从列表中获取第一个元素。cdr 将返回减去第一个元素的列表。只需对列表调用 car 函数就可以看到如何获得第一个元素。获得第二个元素要求对列表调用 cdr,然后对新列表调用 car。通过对列表两次调用 cdr 并对得到的列表调用 car 获取第三个元素。
导出后以上函数的输出为:
COMMON-LISP-USER>
(my_new_lisp_project:concat3 '("howd" "y h" "o"))
"howdy ho"
|
就是这样。已正确连接了三个字符串来生成 "howdy ho"。接下来,创建递归函数。
将要创建的最后一个函数要执行一些递归操作,这是使用 Lisp 进行列表处理的真正强大之处。迭代是可能实现的(逐个遍历所有条目),但是不同于诸如 Java 语言之类的普通语言,递归是到现在为止 Lisp 中处理列表的最简单方法。在本节的末尾,您将明确了解递归的含义。
首先创建递归的 concat 函数。
清单 2. 递归连接(无限制的参数)
1 (defun concat_recursive (args_list)
2 (if (equal (cdr args_list) nil)
3 (car args_list)
4 (concat2 (car args_list)
5 (concat_recursive (cdr args_list)))))
|
递归是十分难于处理的概念,因此让我们一起来查看这个概念:
- 假定将任意参数列表传递给上面的函数。
- 如果列表中只有一个元素(第 2 行中的
(cdr args_list)部分返回 nil),则返回单个元素(第 3 行中的(car args_list))。 - 如果列表中有多个元素(意味着第 2 行中的
(cdr args_list)部分未返回 nil),则返回使用(cdr args_list)的结果作为参数(参见第 5 行)连接(使用concat2)列表的第一个元素(参见第 4 行)与递归调用concat_recursive的结果的结果。
当传递列表 '("ho" "wd" "y" "h" "o") 作为参数时,下面是递归输出:
- 第一次执行到第 2 行时,
if语句为 false,并用"ho"和(concat_recursive '("wd" "y" " h" "o"))调用concat2。 - 第二次执行到第 2 行时,
if语句又为 false,并用"wd"和(concat_recursive '("y" " h" "o"))调用concat2。 - 第三次执行到第 2 行时,
if语句又为 false,并用"y"和(concat_recursive '(" h" "o"))调用concat2。 - 第四次执行到第 2 行时,
if语句又为 false,并用" h"和(concat_recursive '("o"))调用concat2。 - 第五次递归结束。这是因为这一次,第 2 行中的
if语句现在为 true,并且简单地返回了"o"。递归解开为:
- 第四次:连接并返回
"h"和"o"。 - 第三次:连接并返回
"y"和"ho"。 - 第二次:连接并返回
"wd"和"y ho"。 - 第一次:连接并返回
"ho"和"wdy ho"作为最终结果。
- 第四次:连接并返回
这时就完成了递归 —— "howdy ho" 最终被返回,如下所示:
COMMON-LISP-USER>
(my_new_lisp_project:concat_recursive '("ho" "wd" "y" " h" "o"))
"howdy ho"
|
已经将递归添加到了 Cusp 开发工具库中。接下来请尝试调试器。
考虑输入条件可能会导致 concat_recursive 失败,因此调试器可能会派得上用场。一种情况是可以发送一个混有数字的字符串来查看会发生什么情况。记住,使用 concat2 进行连接要求使用两个字符串,因此数字将导致此函数在递归之间中断。
键入以下命令:(my_new_lisp_project:concat_recursive
'("ho" "wd" "y" 55 " h" "o"))。注意没有用双引号引起的数字 55 不是字符串并将导致显示调试器,如下所示:
图 8. 触发调试器
注意,触发调试器的主要错误是无法对列表 (55 "
ho") 调用 concat2。另请注意,在触发该错误之前已经连接了 "h" 和 "o"。
在调试器窗口中,您还可以看到 ==Backtrace==,如图 8 所示。调试器下部的每行(本例中为 0 至 19 行)给出了从单击 Send 到发生错误的详细跟踪。在这里,您还可以查看并跟踪在触发了错误的数字 55 之前的递归。
现在做什么?遇到上面的情况,您有三种选择退出调试器并修改和验证函数输入:可以中止命令并返回到正常的 REPL 窗口;可以关闭连接(通过测试发现,如果选择此选项,则需要重新引导 Eclipse 来重新启动 Lisp 处理器);可以简单地中止调试器并返回到正常的 REPL 窗口。退出调试器的最佳选项始终是中止命令并返回到正常的 REPL 窗口。
就是这样。您已经在 Lisp 中实现了递归函数。
您已经成功地使用 Cusp Eclipse 插件完成了 Lisp 开发。现在应当知道 Lisp 为什么如此强大。通过简单的递归语句,可以轻松地推动处理符号和数据列表。Cusp 为 Lisp 的功能补充了内置 Cusp 调试器、拥有项目管理功能的可靠 GUI、交互式 Lisp 编辑器以及可以输入命令和测试代码的 Lisp 处理器命令行接口。要获得更多信息,请一定要查看 参考资料。
| 描述 | 名字 | 大小 | 下载方法 |
|---|---|---|---|
| Cusp 文章的样例代码 | os-eclipse-lispcusp.code.zip | 28KB | HTTP |
学习
- 您可以参阅本文在 developerWorks 全球站点上的 英文原文。
- 在 Cusp, a Lisp Plug-in for Eclipse 中了解更多信息。
- 阅读斯坦福大学人工智能实验室的 John McCarthy 于 1979 年 2 月 12 日撰写的 “History of Lisp”。
- 阅读由 Sergey Kolos 撰写的标题为 “Programming In Lisp With Cusp” 的文档,了解如何从 Cusp 中使用 HyperSpec 和 LispDoc。
- 在 Wikipedia 了解关于 Common Lisp 的更多信息。
- 阅读 Paul Graham 对 Lisp 的评论 了解其历史和用法。
- “Developing Eclipse plug-ins” 介绍了 Eclipse 插件架构的基本信息以及如何创建 Eclipse 插件架构。
- 有关插件开发的更多信息,请访问 Eclipse.org。
- Eric Clayberg 和 Dan Rubel 合著的
Eclipse: Building Commercial-Quality plug-ins
一书中详细介绍了如何创建 Eclipse 插件。
- 浏览 Eclipse 插件的完整列表。
- 可以从 Eclipse Project 获得 Eclipse 的文档、文章和下载。
- 查阅 “Eclipse 推荐读物列表”。
- 浏览 developerWorks 上的全部 Eclipse 文章和Eclipse 教程。
- 您是 Eclipse 新用户?阅读 developerWorks 文章 “Eclipse 平台入门” 以了解它的起源和架构,以及如何用插件扩展 Eclipse。
- 查阅 IBM developerWorks 的 Eclipse 项目资源 扩展 Eclipse 技巧。
- 收听针对软件开发人员的有趣访谈和讨论,一定要访问 developerWorks podcast。
- 要获得关于 Eclipse 平台的介绍性文章,请参阅 “Eclipse 平台入门”。
- 随时关注 developerWorks 的 技术事件和网络广播。
- 查看免费的 developerWorks On demand demo 观看并了解 IBM 及开源技术和产品功能。
- 查阅最近将在全球举办的面向 IBM 开放源码开发人员的研讨会、交易展览、网络广播和其他 活动。
- 访问 developerWorks 开放源码专区,获得丰富的 how-to 信息、工具和项目更新,帮助您用开放源码技术进行开发,并与 IBM 产品结合使用。
获得产品和技术
- 访问 Cusp Eclipse Update Site 下载 Cusp。
- 从 Eclipse.org 下载 Eclipse。
- 在 IBM alphaWorks 查阅最新的 Eclipse 技术下载。
- 从 Eclipse Foundation 下载 Eclipse Platform 和其他项目。
- 下载 IBM 产品评估版,并开始使用 DB2®、Lotus®、Rational®、Tivoli® 和 WebSphere® 的应用程序开发工具和中间件产品。
- 使用 IBM 试用软件 改进您的下一个开发项目,这些软件可以通过下载或从 DVD 中获得。
讨论
-
Eclipse Platform 新闻组 应当是讨论关于 Eclipse 的问题的第一站(选择此链接将启动默认的 Usenet 新闻阅读器应用程序并打开 eclipse.platform)。
-
Eclipse 新闻组 中有很多参考资料适用于对使用和扩展 Eclipse 感兴趣的人员。
- 参与 developerWorks blog 并加入 developerWorks 社区。