38.2. 操作符

操作符是语言的基本组成部分,在ELite中的操作符有:

38.2.1. 赋值操作符

ELite中的赋值操作符是“=”,其赋值表达式的语法结构为 lhs = rhs(lhs: left-hand side,rhs:right-hand side),其结果是对右操作数求值,并将结果赋予左操作数。右操作数的求值结果同时也是赋值表达式的求值结果,因此多个赋值表达式可以串接起来,例如 x = y = 0。需要注意的是:左操作数必须是一个左值,即它的值能够被改变,左值包括变量和对象属性,而算术表达式和函数调用等都不是左值。

在ELite中,根据右操作数的性质,赋值表达式具备不同的含义。右操作数可以是一个对象(或返回一个对象),也可以是基本类型。当右操作数是一个对象时, 则意味着将该对象的“引用”赋给左操作数;当右操作数是基本类型时,意味着左操作数获得了右操作数的一份copy,这和Java语言中的情境是类似的。

如下例所示:

右操作数是对象:

> define x = new ArrayList();
> x.size();
0
> define y = x;
> y.size();
0
> x.add("1");
true
> x.size();
1
> y.size();
1
>

右操作数是基本类型:

> define x = "String x";
> define y = x;
> x = "another String";
another String
> y;
String x
>

但需要引起我们注意的是,如前文所提及到的,ELite本质上是一种函数式语言,函数在ELite中占据了前所未有的重要地位,有时,我们需要将函数的返回值( 无论它是返回对象或是基本类型)作为一种“引用”赋给某个变量,因此,为了解决此问题,在ELite中,还有一种称为“引用赋值”的概念, 此时,需要在右值前面加一个“&”符号。请比较下面两种赋值表达式:

1) define x = y;

2) define x = &y;

第一种形式实际上是将赋值和定义缩写在同一条指令里,因此x的值是对y立即求值的结果, 如果y是基本类型,那么,y值的改变将不再对x产生任何影响。第二种形式下, x所定义的是对y的引用,或者可以认为是y的别名,因此当y的值改变时,无论y是对象引用还是基本类型,x的值都会发生相应变化,而如果对 x赋值也会影响y的值。

请看下面的例子:

> define y = "Hello World";
> define x = y;
> y = "Me too!";
Me too!
> x.print();
Hello World
>

将上面的例子改一下:

> define y = "Hello World";
> define x = &y;
> x.print();
Hello World
> y = "Me too!";
Me too!
> x.print();
Me too!
>

您看出其中的差异了吗?

同样,如果将右值中的 & 符直接加在常量上,则意味着声明的变量为不可变的。

> define x = &1;
> x = 2;
类型null的'null'属性不可写。
        at __toplevel__(1)
-------------------------
>

引用赋值的概念,借鉴了C++的语法,适合于解决某些特定场合下的问题。

38.2.2. 算术操作符

算术操作符有:+、-、*、/、%、mod,其中,%和mod是等价的。笔者并不试图在这里浪费过多的纸墨,只是列几个简单的例子予以示例:

> define x = 1;
1
> define y = 2;
2
> print(x+y);
3
> print(x-y);
-1
> print(x*y);
2
> print(x/y);
0.5
> print(x%y);
1
> print(x mod y);
1

在ELite中,也可以使用简略标记形式,让某种运算符和赋值动作同时运行。这种简略标记法是在运算符之后紧跟着等号,适用于上述所有运算符。如:

> define x = 1;
> x+=1;
2

38.2.3. 自增自减操作符

熟悉C、Java等语系的同学,对++、--之类的自然也很熟悉。

> define x = 1;
> print(x++);
1
> x=1;
1
> print(++x);
2
> x=1;
1
> print(x--);
1
> x=1;
1
> print(--x);
0
>

38.2.4. 关系操作符

关系操作符无非就是大于、小于、大于等于、小于等于、等于、不等于这些,这是咱们小学时学的东西,在这里就不予以赘述了。

为了方便您在xml文件中使用ELite,我们提供了这些关系操作符的等价英文形式。如您需要在 xml 中写这样一段逻辑,您大可不必将 “>” 转义成”>”,只需使用其等价的英文形式“gt”即可

<c:if test="#{x gt y}"/>

同时,需要提醒您的是,这些等价的英文替代词,我们称之为“伪关键字”。所谓伪关键字,意思就是说:当它出现在表达式中,那么,它就是关键字;而在其它地方,它也可以成为变量的名称。

表 38.1. 关系操作符

关系操作符等价的伪关键字
>gt
<lt
>=ge
<=le
==eq
!=ne

一个简单的例子:

> define x = new Random().nextInt();
> define y = new Random().nextInt();
> if(x lt y) print("${x} < ${y}");\
2) else print("${x} >= ${y}");
-12261297 < 1281014482
>//定义变量lt(如果你一定要这么做的话)
> define lt = "Hello World";
> lt;
Hello World
>

38.2.5. 逻辑操作符

这也没有什么好说的,同样需要提醒的是,我们提供了等价的两种形式:

表 38.2. 逻辑操作符

关系操作符等价的伪关键字
&&and
||or
!not

一个简单的例子:

> define x = new Random().nextInt();
> define y = new Random().nextInt();
> if( x < 0 && x < y) print("${x} < 0, and ${x} < ${y}");\
2) else print("${x} > 0 or ${x} >= ${y}");
-1758887219 < 0, and -1758887219 < -1029574503
>

38.2.6. 类型转换操作符

可以使用class(expression)这样的语法进行强制类型转换。具体实现上,ELite会调用class对象的valueOf方法。换言之,如果一个类拥有valueOf方法,则可以通过 class(expression)形式将expression强制转换为该对象。

特别地,表达式void(e)将丢弃表达式 e 的计算结果。

> define pi = 3.14;
> print( Integer(pi) );
3
>

38.2.7. instanceof操作符

instanceof 操作符用来判断一个实例(instance)是否属于某个类(class)的实例,类似于Java中的instanceof,同时,ELite也为您提供了另外一种更简单的方式:is。很自然的,is也是一种伪关键字。

> define x = 1;
> x instanceof Integer
true
> define class A{};
> define a = A.new();
> a is A
true
> a is Object
true
> a is String
false
>

38.2.8. 三元问号表达式

三元问号运符符有三个运算对象,其表达式采取下述形式:

布尔表达式 ? 值0:值1

如果“布尔表达式”的结果为true,就计算“值0”,而且它的结果成为最终由运算符产生的值;如果 “布尔表达式”的结果为false,计算的就是“值1”,而且它的结果成为最终由运算符产生的值。

当然,也可以换用普通的if-else语句(在后面介绍),但三元运算符更加简洁。

> define x = new Random().nextInt();
> x > 0 ? print("x>0") : print("x <=0");
x <=0
> x;
-1847987592
>

38.2.9. 字符串操作符

在ELite中声明一个字符串,可以有多种方式,即可以用双引号" "声明,也可以用单引号''声明,如:

> define x = "Hello World";
> x
Hello World
> define y = 'Hello World';
> y
Hello World
>

同时,在ELite中,可以像Java那样使用加号(+)拼接字符串,这在常规的JSF EL中是不允许的。

> define x = "Hello " + "World";
> print(x);
Hello World
>

在ELite中还有另外一种更简便的构造字符串的方式:在一个使用双引号的字符串中可以包含子表达式(以${}或#{}括起来),当对这样的字符串求值时,这些子表达式的求值结果将替换字符串中它们所处的位置。对用单引号''括起来的字符串时,此规则不起作用。

> define x = "World";
> define y = "Hello ${x}";
> print(y);
Hello World
>
> define y2 = 'Hello ${x}';
> y2
Hello ${x}
>

38.2.10. 其它操作符

ELite中还有其它一些操作符。

38.2.10.1. defined

defined用来判断是否声明过指定的变量。如:

> defined(para);
false
> define para = "Test";
> defined(para);
true
>

38.2.10.2. undef

undef用来将声明过的变量无效。如:

> define x = 1;
> x
1
> undef x;
> x
标识符未定义: x
        at __toplevel__(1)
-------------------------
>

38.2.10.3. #

在ELite中,声明单个字符可以用 # 后面跟一个字符,它等价于Java中类似于char c = 'a'的语句。

> define x = #a;
> x
a
> x.class
class java.lang.Character
>