Java使用Aviator表达式 学习记录(十七)

2,786 阅读3分钟

这是我参与8月更文挑战的第19天,活动详情查看:8月更文挑战

MODULE_

在被加载模块中,可以通过 __MODULE__ 获取当前模块的信息,包括:

  • path ,当前模块的代码路径
  • exports ,当前模块导出的函数或者变量列表。

只有被 load 或者 require 的模块才有这 exports 和 __MODULE__ 这两个特殊变量,其中 __MODULE__.exports 指向了 exports 。

因此可以直接赋值给 __MODULE__.exports 来整体导出一个方法列表:

## examples/module.av

## a test module

let m = seq.map();

m.add = lambda(x, y) ->
  x + y
end;
m.sub = lambda(x, y) ->
  x - y
end;

println("module path: " + __MODULE__.path);

__MODULE__.exports = m;

我们创建了一个 map 实例 m ,并给 m 设置了两个变量 m.add  和 m.sub 分别赋值了两个函数。最后将整个 m 赋值给了 __MODULE__.exports ,这样这个测试模块导出了两个方法 add 和 sub ,我们可以这样使用它们:

## examples/test_module.av

let t = require('examples/module.av');

println(t.add(1, 2));
println(t.sub(1, 2));

这样将打印:

module path: examples/module.av
3
-1

其中第一行是在 module.av 里打印的,而 3 和 -1 是分别执行 t.add(1, 2) 和 t.sub(1, 2) 的结果。

请注意,不要直接去执行 module.av 文件,它只能被引用并使用,如果你直接执行将报错:

Exception in thread "main" com.googlecode.aviator.exception.ExpressionRuntimeException: Could not find variable __MODULE__.path
	at com.googlecode.aviator.runtime.type.AviatorJavaType.getProperty(AviatorJavaType.java:405)
	at com.googlecode.aviator.runtime.type.AviatorJavaType.getValueFromEnv(AviatorJavaType.java:316)
	at com.googlecode.aviator.runtime.type.AviatorJavaType.getValue(AviatorJavaType.java:308)
	at com.googlecode.aviator.runtime.type.AviatorString.add(AviatorString.java:58)
	at Script_1586622095774_0/931919113.execute0(Unknown Source)
	at com.googlecode.aviator.ClassExpression.executeDirectly(ClassExpression.java:65)
	at com.googlecode.aviator.BaseExpression.execute(BaseExpression.java:92)
	at com.googlecode.aviator.BaseExpression.execute(BaseExpression.java:144)
	at com.googlecode.aviator.example.RunScriptExample.main(RunScriptExample.java:19)

数组和集合

数组

Tuple

tuple 函数可以创建一个固定大小的数组,等价 java 的类型为 Object [] :

## examples/tuple.av

let t = tuple(1, 2, "hello", 3.14);

println("type of t: " + type(t));

for x in t {
  println(x);
}

println("count of t: "+ count(t));

println("t[0] = " + t[0]);

t[0] = 100;
println("t[0] = " + t[0]);

这个例子演示了 tuple 的基本操作: for 用来遍历数组, count 可以获取数组长度t[x]  可以访问索引位置 x 的元素,同样也可以赋值特定位置的元素:

type of t: Object[]
1
2
hello
3.14
count of t: 4
t[0] = 1
t[0] = 100

tuple 可以放入任意类型的元素,如果要创建特定类型的,就需要用到其他函数。

创建类型数组并填充

可以通过 seq.array(type, ..args) 可以创建 type 类型的数组:

## examples/array.av

let a = seq.array(int, 1, 2, 3, 4);

println("type(a) is : " + type(a));
println("count(a) is: " + count(a));

比如上面创建了一个 int[] 数组,他的长度是 4,元素分别为 1, 2, 3, 4 。

如果传入错误的类型,创建将报错:

let a = seq.array(int, 1, 2, "hello", 4);

报错  Unexpected param type, expected: int, given: java.lang.String 。

但是如果可以转化为目标类型,比如 double 可以转成 int ,那么还是可以创建的:

let a = seq.array(int, 1, 2, 3.3, 4);

map(a, println)

3.3 将被转为 3:

1
2
3
4

seq.array 的 type 可以是基本类型,如 short 、 byte 、 char 、 bool 、 float 、 double 、 int 、 long  以及 void 。

也可以是对象,但是需要给完整的类名,比如创建字符串数组:

let s = seq.array(java.lang.String, "hello", "world", "aviator");

println(string.join(s, ","));

string.join 函数将第一个参数的字符串集合用第二个参数的字符串起来,这里将输出 hello,world,aviator 。

创建空数组

如果要创建一个“空”数组,只确定类型和长度,可以用 seq.array_of(type,  len) ,这样就创建了一个 type[len] 的数组,每个元素都将是该类型的默认值,比如整数就是 0,对象就是 null:

let a = let a = seq.array_of(int, 3);
println("type(a) is : " + type(a));
println("count(a) is: " + count(a));

println("before assignment:");
for x in a {
  println(x);
}

for i in range(0, 3) {
  a[i] = i;
}

println("after assignment:");
for x in a {
  println(x);
}

输出:

type(a) is : int[]
count(a) is: 3
before assignment:
0
0
0
after assignment:
0
1
2

创建多维数组

seq.array_of(Class, &dimensions) 也可以用于创建多维数组,举例来说:

## create multidimensional array

let a = seq.array_of(long, 3, 2);

assert(3 == count(a));
assert(2 == count(a[0]));

let x = 0;
for i in range(0, 3) {
  for j in range(0, 2) {
     a[i][j] = x;
     x = x + 1;
  }
}

for i in range(0, 3) {
  for j in range(0, 2) {
    p("a[#{i}][#{j}] = #{a[i][j]}");
  }
}

我们创建了一个 2 x 3 的二维数组,并遍历初始化,最终打印数组:

a[0][0] = 0
a[0][1] = 1
a[1][0] = 2
a[1][1] = 3
a[2][0] = 4
a[2][1] = 5