最近看了一本叫做《黑客与画家》的书,其中对于Lisp语言大加褒奖。自己试着用了一下,虽然确实有反人类之嫌,但是确实是一门不错的语言,New Architect杂志上有一篇介绍ITA软件公司的文章,里面说"一行Lisp代码相当于20行C代码"。Lisp的强大,从中就可见一斑了。另外,Lisp还有理论上最高的计算能力。还有一个笑话是这么讲的:“任何C或Fortran程序复杂到一定程度之后,都会包含一个临时开发的、不合规范的、充满程序错误的、运行速度很慢的、只有一半功能的Common Lisp实现。"

但是Lisp是一种解释性语言,不能直接执行。所以,将其嵌入一个稳定的框架是个不错的选择。Java与Lisp就可以这样整合,其接口有很多,但我认为abcl(Armed Bear Common Lisp)是最好的选择,这个接口的性能表现是我觉得最优的。与其说它是一个接口,不如说是一个JAVA上的Common Lisp实现。本文将分两部分讲述,其一是怎么在JAVA里调用Lisp,其二是怎么在Lisp里调用JAVA,这有助于提高Lisp的扩展性。

Part One 在JAVA里用Lisp:

  首先要安装abcl。在abcl官网下载其binary版本。解压出abcl.jar后,把它移动到jdk\lib目录下。并在环境变量CLASSPATH后加上一段话:%JAVA_HOME%\lib\abcl.jar(假设JAVA_HOME已经设置,指向jdk目录)。这样,abcl就算是安装好了。(与那些需要编译的C++库,安装过程简直太简单了,--我不是在吐槽boost!)

安装完毕后,就可以使用此接口了。在JAVA里用Lisp时,通常不把Lisp源码硬编码在JAVA程序中,而是另外建一个.lisp文件,在其中写上一些函数。这样易于修改,也不会致使你的JAVA源代码又臭又长!(想象一下,把Lisp源码以行为分割,打在方法的参数里,程序实在是太美观了)要加载外部的Lisp程序,可以这么做:

    Interpreter interpreter = Interpreter.createInstance();

    interpreter.eval("(load \"my-lisp-code.lisp\")");

  “my-lisp-code.lisp”是外部lisp文件的文件名。那么加载后,怎么调用这段Lisp代码中的程序呢?首先,我们要得到一个abcl的Package:

    org.armedbear.lisp.Package defaultPackage = Packages.findPackage("CL-USER");

  在这个package里,我们要寻找Lisp代码中的函数,假设该函数叫做lispfunction,那么,代码应该这样写:

    Symbol myFunctionSym=defaultPackage.findAccessibleSymbol("LISPFUNCTION");

  根据这个Symbol对象,我们可以创建一个Fucntion对象并且运行,这里假设目标函数没有输入参数:

    Function myFunction=(Function)myFunctionSym.getSymbolFunction();
    myFunction.execute();

  如果有参数呢?只要在execute中类似正常函数传参的方式,按次序写入参数即可。但要注意的是,不能直接填写,而要new一个JavaObject后传入,且Lisp代码中要用(jobject-lisp-value x)来转换。

  如果又返回值呢?execute本来返回一个LispObject,可以通过其各种成员方法转换成相应的类型。

  下面给出一个官方提供的例子,实现两个数的加法运算:点此下载

Part Two 在Lisp里用JAVA:

  第一步依然是安装。提前声明:而且本部分的内容基于Part One。

  通常的实现模式是按上面的方法在JAVA里调用Lisp,并且传入一个类。在Lisp里,通过一系列的转换,然后就可以调用了。

  这里主要讲Lisp里的代码实现,JAVA部分只要写好函数,然后还需要在调用过程里这么写:

    myFunction.execute(New Class1());

  这就是传入的参数了,是一个类的实例。例如这个类有一个成员函数:addTwoNumbers(a,b)——表示两个数相加的和,a与b均为int类型,返回值也是int类型。传入后,在Lisp部分应该这么写(传入的参数为param):

  (let* ((class (jclass "Main"))
(intclass (jclass "int"))
(method (jmethod class "addTwoNumbers" intclass intclass))
(result (jcall method param 2 4)))
(format t "in void-function, result of calling addTwoNumbers(2, 4): ~a~%" result)))

  其实很简单,在使用时,可以遵循此模式,先转换JAVA中的类型,再计算。

  给出官方提供的例子代码:点此下载

附录:

  这里讲些题外话,像abcl的运行速度,其他的Lisp->JAVA接口及如何打开abcl并把其作为一个外部独立运行的实现以学习Lisp的方法.

  速度:许多Lisp用户就是奔着它有着理论上最高的运行速度去的。根据实验测试发现,其运行时间分两部分,分别是预载和实际计算。获取解释器实例(预载)时比较慢,命令行下为5-6s,Eclipse下更长。实际计算时间倒是在可以接受的范围内。

  独立外部实现:下载了abcl.jar并且安装后,可以这样来运行它,将其作为一个外部的解释器——学习Lisp:

    java -jar abcl.jar

  另外的Lisp->JAVA接口现在概括如下:

    1.abcl不支持Android,但目前仍在持续开发中,不排除2.0版本会对Android进行支持。
    2.ecl支持Android,看github上的进度很久没有commit了,所以不建议优先考虑,但是这个接口还支持C语言。
    3.clojure的Android支持性比较好,有nightcode这个集成的IDE,而且比较流行。
    4.mocl,一个收费的common lisp的Android接口,具体性能也无法评定。

后记:

  因为要期中迎考与本人较懒的缘故,本文后两部分写的较为粗略。可能无法从中清晰地了解到我所想讲述的。如果有什么疑问,可以评论或短消息我,我会竭尽所能地帮助。

Lisp与JAVA的酷毙结合——abcl的更多相关文章

  1. C,C++,Lisp,Java,Perl,Python

    (译注:圣经记载:在远古的时候,人类都使用一种语言,全世界的人决定一起造一座通天的塔,就是巴别塔,后来被上帝知道了,上帝就让人们使用不同的语言,这个塔就没能造起来. 巴别塔不建自毁,与其说上帝的分化将 ...

  2. lisp学习总结(二)-----lisp应该探索发展的方向

    现在流行一种语言叫做Clojure,他是lisp直接嫁接到java的结果,但是我就感觉这却成为lisp的失败. 因为lisp最强大最有优势的能力是构造抽象,构造设计思想,而不是运行期以确定的方式运行, ...

  3. Automake

    Automake是用来根据Makefile.am生成Makefile.in的工具 标准Makefile目标 'make all' Build programs, libraries, document ...

  4. 【转】人工智能(AI)资料大全

    这里收集的是关于人工智能(AI)的教程.书籍.视频演讲和论文. 欢迎提供更多的信息. 在线教程 麻省理工学院人工智能视频教程 – 麻省理工人工智能课程 人工智能入门 – 人工智能基础学习.Peter ...

  5. python 面向对象设计思想发展史

    这篇主要说的是程序设计思想发展历史,分为概述和详细发展历史 一,概述 1940年以前:面向机器 最早的程序设计都是采用机器语言来编写的,直接使用二进制码来表示机器能够识别和执行的 指令和数 据.简单来 ...

  6. history program(language)

    1950与1960年代 有三个现代编程语言于1950年代被设计出来,这三者所衍生的语言直到今日仍旧广泛地被采用: Fortran (1955),名称取自"FORmula TRANslator ...

  7. (转)A curated list of Artificial Intelligence (AI) courses, books, video lectures and papers

    A curated list of Artificial Intelligence (AI) courses, books, video lectures and papers. Updated 20 ...

  8. Python 入门基础1 --语言介绍

    本节目录: 一.编程语言介绍 二.python解释器介绍 三.安装python解释器 四.运行python程序的两种方式 五.变量 六.后期补充内容 一.编程语言介绍 1.机器语言: 直接用二进制编程 ...

  9. Can you share some Scala List class examples?

    Scala List FAQ: Can you share some Scala List class examples? The Scala List class may be the most c ...

随机推荐

  1. [转]windows下srand48()和drand48()的问题

    转自:windows下srand48()和drand48()的问题 #ifndef DRAND48_H #define DRAND48_H #include <stdlib.h> #def ...

  2. hdu 4607 (树形DP)

    当时比赛的时候我们找出来只要求出树的最长的边的节点数ans,如果要访问点的个数n小于ans距离直接就是n-1 如果大于的话就是(n-ans)*2+ans-1,当时求树的直径难倒我们了,都不会树形dp ...

  3. Latex 中宽度的设置和理解

    \textwidth, 文本区域的全部宽度 \columnwidth, 文本中一列的宽度,单栏或者多栏的情况下,值是不同的 但是,一旦\textwidth, \columnwidth, \linewi ...

  4. Widget only supports Widgets as children

    Widget only supports Widgets as children https://www.baidu.com/s?wd=Widget%20only%20supports%20Widge ...

  5. 有如下Student 对象,  private String name;       private int age;       private int score;   private String classNum;  其中,classNum

    package homework003; import java.util.ArrayList; import java.util.List; public class Text { public s ...

  6. cocos2d-x 添加纹理自动回收机制

    转自:http://www.cnblogs.com/lancidie/archive/2013/04/13/3019375.html 1.不是一个完整的模块,所以不提供完整代码,只提供思路和核心代码. ...

  7. android驱动[置顶] 我的DIY Android之旅--驱动并控制你的Android开发板蜂鸣器

    改章节个人在深圳游玩的时候突然想到的...这几周就有想写几篇关于android驱动的博客,所以回家到之后就奋笔疾书的写出来发布了 这些天一直在想Android驱动框架层的实现,本文借助老罗教师的博客和 ...

  8. HDU 1330 Nearest Common Ancestors(求两个点的近期公共祖先)

    题目链接:id=1330">传送门 在线算法: #include <iostream> #include <cstdio> #include <cstri ...

  9. CircleProgressBar

    http://www.eoeandroid.com/thread-333984-1-1.html CircleProgressBar.rar

  10. android学习日记21--消息提示之Toast和Notification

    1.Toast Toast译为土司,类似切片面包,用于弹出比较快速的及时提示信息.当Toast被显示时,虽然它悬浮应用程序最上方,但是并未获得焦点.它的设计就是为了提示有用的信息,而不打扰用户其他操作 ...