第38章 ELite教程

38.1. Getting Started
38.1.1. 什么是ELite
38.1.2. ELite的起源
38.1.3. 安装ELite
38.1.4. 运行ELite
38.1.5. 第一个ELite程序:Hello World
38.2. 操作符
38.2.1. 赋值操作符
38.2.2. 算术操作符
38.2.3. 自增自减操作符
38.2.4. 关系操作符
38.2.5. 逻辑操作符
38.2.6. 类型转换操作符
38.2.7. instanceof操作符
38.2.8. 三元问号表达式
38.2.9. 字符串操作符
38.2.10. 其它操作符
38.2.10.1. defined
38.2.10.2. undef
38.2.10.3. #
38.3. 创建Java对象
38.4. Lambda表达式
38.5. 函数
38.6. 闭包
38.7. 元组
38.8. 列表
38.9. 区间
38.10. Java中的集合对象
38.11. 集合操作
38.12. 关联表
38.13. 流程控制
38.14. 创建自己的对象
38.14.1. 封装
38.14.2. 继承
38.14.3. 多态
38.15. Use ELite in your application
38.15.1. 在AOM中使用
38.15.2. 在自己的程序中使用ELite

38.1. Getting Started

38.1.1. 什么是ELite

ELite,脱胎于 Apusic OperaMasks中的EL(Expression Language)实现。 从字面意义上来看,ELite是指精华、精英的意思,其前两个字母大写,寓意着ELite是从Expression Language中发展过来的,而lite这个词根,又代表着轻量、敏捷之意。

从计算机作为一门正式的学科被确立,至今已有半个多世纪的发展历程,而计算机语言也经历了“机器语言”、“汇编语言”,一直到目前所谓的“高级语言”等多个形态。1954 年,第一个完全脱离机器硬件的高级语言—FORTRAN问世了,50多年来,共有几百种高级语言出现,时至今日,掌握某一种或某几种语言,已经成为了每一个IT开发人员必备的技能。

如果对计算机语言进行分类,根据不同的衡量基准,有不同的分类方法,如前文所提到的机器语言、汇编语言、高级语言等; 再如根据语言的执行方式,又可分编译执行、解释执行或半编译、半解释型(Java的JIT—Just In Time技术即是如此)。

无论怎样分类,一个不容置疑的是,计算机语言本身是为“程序员”—计算机程序的撰写者—服务的,换言之,计算机语言只是程序员分析问题、求解问题的一种媒介,一种表达方式。 因此,如果我们从“程序员的思维”这个角度来看待计算机语言,我们会看到这样两种不同的语言形态。一种是命令式语言(Imperative Language):如Java、C、C++、Pascal等均属于命令式语言。此处的“命令式”的含义是指:用这类语言编写的程序,是由一系列的“指令”(Command)组成的, 这些指令按照用户指定的顺序严格执行。事实上,目前,绝大部分的程序员所使用的语言,都是命令式语言,而这类语言,也符合人们分析问题的惯用思维, 因此,我们通常把这类语言称为“帝王”使用的语言(想一想,帝王虽然离我们有些远,但毕竟不是那么高不可攀的东西,掌握一门命令式语言同样如此)。

那么,有没有“神仙”所使用的语言呢?有,这就是函数式语言(Functional Language),如LISP、ErLang、Haskell等。什么是函数式语言?恐怕这不是一句话两句话能够说清楚的,但从字面意义上来看,在函数式编程中, “函数”被放到了一等地位(再想一下,在你所熟悉的Java中,函数,或者更确切的名称应该叫方法—Method,能够单独存在吗?它必须依附于对象而存在), 基于函数式语言编写的程序完全由函数组成。主程序本身是一个函数,它能够以参数形式接收程序输入,并以函数结果作为程序的最终输出, 而典型的主函数是由其他函数定义的,而这些函数反过头来又是由其他更多的函数定义的,直到语言内建的那些函数为止。 如果您以前没有接触过函数式编程的概念,恐怕看到这里,会有些头大,不妨让我们看一个简单的例子,以体会函数式编程与命令式编程的区别。

一个用C或者Java等命令式语言实现的快速排序的算法可能会如下所示:

void qsort(int a[], int lo, int hi) {
  int h, l, p, t;

  if (lo < hi) {
    l = lo;
    h = hi;
    p = a[hi];

    do {
      while ((l < h) && (a[l] <= p)) 
          l = l+1;
      while ((h > l) && (a[h] >= p))
          h = h-1;
      if (l < h) {
          t = a[l];
          a[l] = a[h];
          a[h] = t;
      }
    } while (l < h);

    t = a[l];
    a[l] = a[hi];
    a[hi] = t;

    qsort( a, lo, l-1 );
    qsort( a, l+1, hi );
  }
}

一个用函数式编程完成的快速排序如下(请注意,以下代码是用ELite完成的):

define qsort(ls) {
    : [] => []
    : [x:xs] => qsort([y where y in xs, y < x])
                + x +
                qsort([y where y in xs, y >= x])
}

我们并不试图从上述示例的行数来判断命令式编程与函数式编程的区别(但不可否认的是,这可能是您的第一感觉), 如前文所述,我们从“程序员的思维”来看待命令式编程与函数式编程的差异,可以简单概述为: 基于命令式编程,你要告诉计算机执行序列,换言之,你的算法思想体现在这堆执行序列上,你告诉计算机的是“How to do”;而函数式编程,则是以函数的形式描述你的算法思想,你只是告诉机算机“What to do”,而并不关心计算机的具体执行过程。

听上去似乎有点“神奇”。笔者个人认为,正是由于这种所谓的“神奇”性,函数式编程目前的使用范围并不广泛,它更多的被一些高等院校在理论教学等场合下使用, 因此,我们不妨把这种语言称为“神仙”所用的语言(确实,函数式编程离广大程序员有些远,有些“高不可攀”的感觉)。

[注意]注意

笔者注:基于函数式编程并不流行的原因,有许多分析,各有各的道理。但一个比较重要的因素是:命令式编程相比函数式编程,更贴近冯.诺依曼架构, 所以效率较高,而函数式编程则使用较高级的数学抽象,效率较低,这在上世纪的商业系统开发中,是很难接受的。 但随着计算机硬件的发展,笔者个人认为,此因素的比重已经逐步降低,而此时函数式编程的一些优点,则开始体现,如它的无副作用(Side Effect)等特性,对于目前大规模的软件架构,似乎更有优势一些,但这些内容,已经超过了本书即将讨论的内容。

有了“帝王”用的语言,也有了“神仙”用的语言,笔者希望告诉你的是:这个世上还存在一种“半人半兽”的语言。 这类语言,既有函数式编程的精髓,又披着命令式语言的外衣,ELite就是其中的代表。

38.1.2. ELite的起源

我们在前一章节中谈到过AOM与JSF之间的关系,AOM遵循JSF规范,并且是站在JSF规范的基础上,做了大量的扩展。

在JSF Specification中,提出了EL的概念,即:Expression Language,我们在前文中也有提及。但严格说来,EL并不是一门真正独立的,具备完整意义的语言,更确切的定义是:EL是一种受限的脚本。在JSF规范中,EL的目的也是简单且明确的 :

[1]The EL is a simple language designed to meet the needs of the presentation layer in web applications. It features:

  • A simple syntax restricted to the evaluation of expressions

  • Variables and nested properties

  • Relational, logical, arithmetic, conditional, and empty operators

  • Functions implemented as static methods on Java classes

  • Lenient semantics where appropriate default values and type conversions are provided to minimize exposing errors to end users

翻译成中文如下:

EL是一种简单的语言,它的设计目的是为了满足Web应用中展现层的需求。它具备以下特性:

  • 一种对表达式进行求值的受限语法

  • 提供变量与嵌套属性

  • 提供关系、逻辑、计算、条件、为空等操作符

  • 通过Java对象的静态方法以实现函数功能

  • 提供宽松的类型转换及默认缺省值等行为,以对用户屏蔽可能出现的错误

AOM的发展初期,只是简单的对EL规范予以实现,但随着AOM功能特性的不断增强,AOM 团队发觉:EL本身的功能已经不足以支撑 AOM 的功能需求,有必要对EL进行大幅修订与完善。在这里不得不提及的是,这种挑战,也激发了金蝶中间件公司创始人、首席架构师袁红岗先生的创作激情与热情,于是, 在袁红岗先生的努力下,一种具备完整形态的语言:ELite,就此诞生。

读到这里,笔者隐约感觉到您的心里有些许失望。

似乎某种“创新”的背后,总会有一个动人的传说,或者来自于某种外界的神秘启示。不是被苹果砸了一下脑袋(牛顿根据苹果落地发现了万有引力), 就是梦到蛇吃尾巴(凯库勒梦到蛇吃自己的尾巴从而推导出苯环结构),ELite的发明过程似乎太无趣了一些。

历史上,许多发明的过程本身,就是这样无趣,甚至是无聊、枯燥。但笔者始终无法忘记的是,当袁红岗先生来到公司会议室,在白板上写下 ELite 这几个字时,那种极度的愉悦与成就感。

接下来,不妨请您和我们一起,开始ELite之旅。

38.1.3. 安装ELite

在开始讨论ELite之前,我们将先帮助您在您的计算机上安装好ELite的运行环境,这样,您就可以一边学习一边运行示例代码,我们相信,这样的学习方式对您是极有裨益的。

由于ELite自身也是建立在Java的基础之上,因此,您首先需要在您的机器上安装好JDK,我们建议的版本为JDK 5.0。在本文中,我们假设您的JDK 安装在 C:\jdk1.5.0。

  • 二进制版本

    ELite的二进制版本很容易安装,您只需要下载此zip包,解压缩即可。

    ELite的主页在:http://www.sourceforge.net/projects/aom-elite

    其zip包下载地址:http://sourceforge.net/project/showfiles.php?group_id=214934

    将zip包解压缩后,我们建议您修改 bin 目录下的 setenv.cmd 文件(如果是Linux平台,则修改setenv文件),在该文件中设置 JAVA_HOME(请将第二行的rem去掉,并设置正确的JDK安装路径)。

    rem set JAVA_HOME variable here, for example:
    rem set JAVA_HOME=C:\jdk1.5.0
  • 从源码中编译

    您也可以直接连上ELite的cvs,获取源码,其cvs连接串为:

    :pserver:anonymous@aom-elite.cvs.sourceforge.net:/cvsroot/aom-elite

    获取源码后,您可以通过工程根目录下的 build.xml,执行release任务,即可以在当前工程下的release目录,生成二进制包。

38.1.4. 运行ELite

基本上来说,您可以在三种情况下运行ELite。

首先,ELite自身为您提供了一个交互式执行的Shell程序,您可以通过这个Shell程序来执行ELite脚本,并了解ELite的功能; 其次,由于ELite是从AOM项目中发展起来的,无庸置疑的是,您可以在AOM中执行ELite,并用ELite完成展现层逻辑; 最后,您还可以将ELite集成到您自己的程序中,以解决某些特定业务场景问题。在本章节中,我们强烈推荐您以交互式的 Shell 程序作为您学习ELite的助手,在本教程的最后部分,我们将向您介绍如何将ELite集成到您自己的程序,并且,我们将花大量的篇幅介绍在AOM中如何使用ELite, 以及ELite适合解决AOM中遇到的哪些问题。现在,请让我们从交互式的Shell程序开始入手。

  • 交互式 Shell

    ELite提供了一个简单的 shell 程序,以供您以交互式方式了解并学习ELite。该 shell程序位于安装包的bin目录下,以Windows平台为例,您只需运行bin\elite.cmd即可,窗口如下:

    Welcome to ELite (Version 0.5.0)
    Copyright (c) 2006-2009 Operamasks Community.
    ELite comes with ABSOLUTELY NO WARRANTY. This is free software,
    and you are welcome to redistribute it under certain conditions.
    Please visit http://www.operamasks.org for details.
    >

    同时需要提醒您注意的是:该 shell 程序有一个特点:如果您输入一个表达式,那么,当您按下“回车”符时,会自动回显该表达式的值。

    譬如,您输入一个阿拉伯数字:8,会自动回显8,因为ELite会认为这是一个表达式,其值为8。

    Welcome to ELite (Version 0.5.0)
    Copyright (c) 2006-2009 Operamasks Community.
    ELite comes with ABSOLUTELY NO WARRANTY. This is free software,
    and you are welcome to redistribute it under certain conditions.
    Please visit http://www.operamasks.org for details.
    > 8
    8
    >

    如果您的语句过长,需要换行处理,那么,请您使用换行符“\”。

    > print("Hello" \
    2)  + " World");
    Hello World

    如果您需要以执行外部的elite脚本,那么,请您使用 require 指令:

    >require "../sample/hello.xel";
    Hello, World!
    Hello, World!
    Hello, World!
    Hello, World!
    Hello, World!
    Hello, World!
    Hello, World!
    Hello, World!
    >
    

    再或者,您还可以在命令行窗口下(Windows下是cmd.exe),直接调用elite命令,用以执行外部脚本文件:

    F:\elite-0.5.0\bin>elite ../sample/hello.xel
    Hello, World!
    Hello, World!
    Hello, World!
    Hello, World!
    Hello, World!
    Hello, World!
    Hello, World!
    Hello, World!
    
    F:\elite-0.5.0\bin>
    

    这里需要提醒您的是, 通常,我们将“xel”作为ELite脚本的扩展名,当然,这只是惯例而非强制。

    如果您要退出此Shell,只需键入:quit。

    > quit
    Bye!
    
    G:\elite-0.5.0\bin>

38.1.5. 第一个ELite程序:Hello World

现在,让我们完成第一个ELite程序。打开 ELite 控制台,输入:

> print("Hello World");
Hello World
>

OK,至此,ELite已经能够向您问好了。

有点过于简单?简单的不够真实?那好,让我们换另外一种方式 say Hello。

输入:

> System.out.println(“Hello World”);
Hello World
>

熟悉Java的同学肯定会说了:这哪是什么ELite,这明明就是Java啊?

不错,ELite能够和Java紧密集成,在您没有对ELite了解清楚之前,您完全可以用类似于Java的语法,编写您的ELite程序。

咱们再换一种写法:

> stdout << "Hello, World!" << endl;
Hello, World!
java.io.PrintStream@16f0472
>

似乎又变成C++风格了。(注意,上文中出现的java.io.PrintStream@16f0472是由于在交互式 shell 程序中表达式回显的原因,现阶段,请您暂且忽略)。

事实上,ELite的语法是如此之灵活多变,我们还可以列举出更多的变化:

> /* 对象风格 */
> "Hello, World!".print();
Hello, World!
>
> /* 消息传递风格 */
"Hello, World!" -> print;
> Hello, World!
>
> /* 各种风格的组合调用,虽然风格不一但都是等价的 */
> define sayHello(thing) => "Hello, ${thing}!";
> print(sayHello('World'));   // 括号太多
Hello, World!
> 'World'.sayHello().print(); // 好一点
Hello, World!
> 'World'->sayHello->print;   // 还不错
Hello, World!
>

至此,恐怕您有些眼花缭乱,一个再简单不过的“Hello World”,在ELite中竟然拥有这样多的变化。 无论您对ELite这种多变灵活的语法感到惊喜,或是感到迷惘,现阶段,都请让我们把这些种种变化抛到一旁,从头开始。笔者将依次为您介绍ELite的一些基础知识。



[1] 摘自JSR-245