Fel是轻量级的高效的表达式计算引擎
更多干货
Fel是开放的,引擎执行中的多个模块都可以扩展或替换。Fel的执行主要是通过函数实现,运算符(+、-等都是Fel函数),所有这些函数都是可以替换的,扩展函数也非常简单。
Fel有双引擎,同时支持解释执行和编译执行。可以根据性能要求选择执行方式。编译执行就是将表达式编译成字节码(生成java代码和编译模块都是可以扩展和替换的)
Fel有多快?
通常情况下,Fel-0.7每秒可以执行千万次表达式(不包含编译时间)。速度是Jexl-2.0的20倍以上。
目前还没有发现开源的表达式引擎比Fel快。
具体的测试数据请参见http://code.google.com/p/fast-el/wiki/Performance。
为何要使用Fel?
Fel语法和API非常简单,语法与Java基本相同,几乎没有学习成本。
Fel非常快,上面已经做了简单说明。
Fel整个包只有200多KB。
Fel可以非常方便的访问数组、集合、Map的元素和对象的属性。
Fel可以非常方便的调用对象的方法和类方法(如果这些还不够,可以添加自定义函数)。
Fel支持大数值高精度计算
Fel有良好的安全管理功能
如果Fel不能满足你的要求,扩展和修改Fel很简单。
Fel不能做什么?
Fel只支持表达式,不支持脚本。
Fel适用场景:
Fel适合处理海量数据,Fel良好的扩展性可以更好的帮助用户处理数据。
Fel同样适用于其他需要使用表达式引擎的地方(如果工作流、公式计算、数据有效性校验等等)
安装
1:获取Fel
项目主页:http://code.google.com/p/fast-el/ 下载地址:http://code.google.com/p/fast-el/downloads/list
Fel使用例子:
1:算术表达式:
- FelEngine fel = new FelEngineImpl();
- Object result = fel.eval("5000*12+7500");
- System.out.println(result);
输出结果:67500
2:变量
使用变量,其代码如下所示:
- FelContext ctx = fel.getContext();
- ctx.set("单价", 5000);
- ctx.set("数量", 12);
- ctx.set("运费", 7500);
- Object result = fel.eval("单价*数量+运费");
- System.out.println(result);
输出结果:67500
3:访问对象属性
在Fel中,可能非常方便的访问对象属性,示例代码如下所示
- FelEngine fel = new FelEngineImpl();
- FelContext ctx = fel.getContext();
- Foo foo = new Foo();
- ctx.set("foo", foo);
- Map<String,String> m = new HashMap<String,String>();
- m.put("ElName", "fel");
- ctx.set("m",m);
- //调用foo.getSize()方法。
- Object result = fel.eval("foo.size");
- //调用foo.isSample()方法。
- result = fel.eval("foo.sample");
- //foo没有name、getName、isName方法
- //foo.name会调用foo.get("name")方法。
- result = fel.eval("foo.name");
- //m.ElName会调用m.get("ElName");
- result = fel.eval("m.ElName");
4:访问数组、集合、Map
- FelEngine fel = new FelEngineImpl();
- FelContext ctx = fel.getContext();
- //数组
- int[] intArray = {1,2,3};
- ctx.set("intArray",intArray);
- //获取intArray[0]
- String exp = "intArray[0]";
- System.out.println(exp+"->"+fel.eval(exp));
- //List
- List<Integer> list = Arrays.asList(1,2,3);
- ctx.set("list",list);
- //获取list.get(0)
- exp = "list[0]";
- System.out.println(exp+"->"+fel.eval(exp));
- //集合
- Collection<String> coll = Arrays.asList("a","b","c");
- ctx.set("coll",coll);
- //获取集合最前面的元素。执行结果为"a"
- exp = "coll[0]";
- System.out.println(exp+"->"+fel.eval(exp));
- //迭代器
- Iterator<String> iterator = coll.iterator();
- ctx.set("iterator", iterator);
- //获取迭代器最前面的元素。执行结果为"a"
- exp = "iterator[0]";
- System.out.println(exp+"->"+fel.eval(exp));
- //Map
- Map<String,String> m = new HashMap<String, String>();
- m.put("name", "HashMap");
- ctx.set("map",m);
- exp = "map.name";
- System.out.println(exp+"->"+fel.eval(exp));
- //多维数组
- int[][] intArrays= {{11,12},{21,22}};
- ctx.set("intArrays",intArrays);
- exp = "intArrays[0][0]";
- System.out.println(exp+"->"+fel.eval(exp));
- //多维综合体,支持数组、集合的任意组合。
- List<int[]> listArray = new ArrayList<int[]>();
- listArray.add(new int[]{1,2,3});
- listArray.add(new int[]{4,5,6});
- ctx.set("listArray",listArray);
- exp = "listArray[0][0]";
- System.out.println(exp+"->"+fel.eval(exp));
5:调用JAVA方法
- FelEngine fel = new FelEngineImpl();
- FelContext ctx = fel.getContext();
- ctx.set("out", System.out);
- fel.eval("out.println('Hello Everybody'.substring(6))");
输出结果:Everybody
6:自定义上下文环境
- //负责提供气象服务的上下文环境
- FelContext ctx = new AbstractConetxt() {
- public Object get(Object name) {
- if("天气".equals(name)){
- return "晴";
- }
- if("温度".equals(name)){
- return 25;
- }
- return null;
- }
- };
- FelEngine fel = new FelEngineImpl(ctx);
- Object eval = fel.eval("'天气:'+天气+';温度:'+温度");
- System.out.println(eval);
输出结果:天气:晴;温度:25
7:多层上下文环境(命名空间)
- FelEngine fel = new FelEngineImpl();
- String costStr = "成本";
- String priceStr="价格";
- FelContext baseCtx = fel.getContext();
- //父级上下文中设置成本和价格
- baseCtx.set(costStr, 50);
- baseCtx.set(priceStr,100);
- String exp = priceStr+"-"+costStr;
- Object baseCost = fel.eval(exp);
- System.out.println("期望利润:" + baseCost);
- FelContext ctx = new ContextChain(baseCtx, new MapContext());
- //通货膨胀导致成本增加(子级上下文 中设置成本,会覆盖父级上下文中的成本)
- ctx.set(costStr,50+20 );
- Object allCost = fel.eval(exp, ctx);
- System.out.println("实际利润:" + allCost);
输出结果:
期望利润:50
实际利润:30
8:编译执行
- FelEngine fel = new FelEngineImpl();
- FelContext ctx = fel.getContext();
- ctx.set("单价", 5000);
- ctx.set("数量", 12);
- ctx.set("运费", 7500);
- Expression exp = fel.compile("单价*数量+运费",ctx);
- Object result = exp.eval(ctx);
- System.out.println(result);
执行结果:67500
备注:适合处理海量数据,编译执行的速度基本与Java字节码执行速度一样快。
9:自定义函数
- //定义hello函数
- Function fun = new CommonFunction() {
- public String getName() {
- return "hello";
- }
- /*
- * 调用hello("xxx")时执行的代码
- */
- @Override
- public Object call(Object[] arguments) {
- Object msg = null;
- if(arguments!= null && arguments.length>0){
- msg = arguments[0];
- }
- return ObjectUtils.toString(msg);
- }
- };
- FelEngine e = new FelEngineImpl();
- //添加函数到引擎中。
- e.addFun(fun);
- String exp = "hello('fel')";
- //解释执行
- Object eval = e.eval(exp);
- System.out.println("hello "+eval);
- //编译执行
- Expression compile = e.compile(exp, null);
- eval = compile.eval(null);
- System.out.println("hello "+eval);
执行结果:
hello fel hello fel
10:调用静态方法
如果你觉得上面的自定义函数也麻烦,Fel提供的$函数可以方便的调用工具类的方法 熟悉jQuery的朋友肯定知道"$"函数的威力。Fel东施效颦,也实现了一个"$"函数,其作用是获取class和创建对象。结合点操作符,可以轻易的调用工具类或对象的方法。
- //调用Math.min(1,2)
- FelEngine.instance.eval("$('Math').min(1,2)");
- //调用new Foo().toString();
- FelEngine.instance.eval("$('com.greenpineyu.test.Foo.new').toString());
通过"$('class').method"形式的语法,就可以调用任何等三方类包(commons lang等)及自定义工具类的方法,也可以创建对象,调用对象的方法。如果有需要,还可以直接注册Java Method到函数管理器中。
11 大数值计算(始于0.9版本)
Fel发布后,有些网友希望提供大数值计算功能,于是,大数值计算功能就有了。例子如下:
- FelEngine fel = FelBuilder.bigNumberEngine();
- String input = "111111111111111111111111111111+22222222222222222222222222222222";
- Object value = fel.eval(input);
- Object compileValue = fel.compile(input, fel.getContext()).eval(fel.getContext());
- System.out.println("大数值计算(解释执行):" + value);
- System.out.println("大数值计算(编译执行):" + compileValue);
由上例子可以看出,大数值计算引擎和常规计算引擎在使用方法是相同的。如果表达式数值比较大,要求精度高,可使用大数值计算引擎。不足之处是效率没有常规计算引擎高。
安全(始于0.8版本)
为了防止出现“${'System'}.exit(1)”这样的表达式导致系统崩溃。Fel加入了安全管理器,主要是对方法访问进行控制。安全管理器中通过允许访问的方法列表(白名单)和禁止访问的方法列表(黑名单)来控制方法访问。将"java.lang.System. * "加入到黑名单,表示System类的所有方法都不能访问。将"java.lang.Math. * "加入白名单,表示只能访问Math类中的方法。如果你不喜欢这个安全管理器,可以自己开发一个,非常简单,只需要实现一个方法就可以了。
附基本Java工程源代码:
Example类:
- public class Example {
- public static void main(String[] args) {
- System.out.println("-----------1.入门---------");
- helloworld();
- System.out.println("-----------2.使用变量---------");
- useVariable();
- System.out.println("-----------3.获取对象属性---------");
- getAttr();
- System.out.println("---------4.调用对象的方法-----------");
- callMethod();
- System.out.println("--------5.访问数组、集合------------");
- visitColl();
- System.out.println("--------6.自定义上下文环境------------");
- context();
- System.out.println("--------7.多层次上下文环境(变量命名空间)------------");
- contexts();
- System.out.println("---------8.大数值计算-----------");
- testBigNumber();
- System.out.println("----------9.函数----------");
- userFunction();
- System.out.println("---------10.自定义 解释器-----------");
- userInterpreter();
- System.out.println("----------11.操作符重载----------");
- operatorOverload();
- System.out.println("----------12.速度测试----------");
- testSpeed();
- System.out.println("----------13.静态方法----------");
- staticMethod();
- }
- /**
- * 入门
- */
- public static void helloworld() {
- // FelEngine fel = new FelEngineImpl();
- Object result = FelEngine.instance.eval("5000*12+7500");
- System.out.println(result);
- }
- /**
- * 使用变量
- */
- public static void useVariable() {
- FelEngine fel = getEngine();
- FelContext ctx = fel.getContext();
- ctx.set("单价", 5000);
- ctx.set("数量", 12);
- ctx.set("运费", 7500);
- Object result = fel.eval("单价*数量+运费");
- System.out.println(result);
- }
- /**
- * 获取对象属性
- */
- public static void getAttr() {
- FelEngine fel = getEngine();
- FelContext ctx = fel.getContext();
- Foo foo = new Foo();
- ctx.set("foo", foo);
- Map<String, String> m = new HashMap<String, String>();
- m.put("ElName", "fel");
- ctx.set("m", m);
- // 调用foo.getSize()方法。
- Object result = fel.eval("foo.size");
- System.out.println(result);
- // 调用foo.isSample()方法。
- result = fel.eval("foo.sample");
- System.out.println(result);
- // foo没有name、getName、isName方法
- // foo.name会调用foo.get("name")方法。
- result = fel.eval("foo.name");
- System.out.println(result);
- // m.ElName会调用m.get("ElName");
- result = fel.eval("m.ElName");
- System.out.println(result);
- }
- /**
- * 调用对象的方法
- */
- public static void callMethod() {
- FelEngine fel = getEngine();
- FelContext ctx = fel.getContext();
- ctx.set("out", System.out);
- fel.eval("out.println('Hello Everybody'.substring(6))");
- }
- /**
- * 访问数组、集合
- */
- public static void visitColl() {
- FelEngine fel = getEngine();
- FelContext ctx = fel.getContext();
- // 数组
- int[] intArray = { 1, 2, 3 };
- ctx.set("intArray", intArray);
- // 获取intArray[0]
- String exp = "intArray[0]";
- System.out.println(exp + "->" + fel.eval(exp));
- // List
- List<Integer> list = Arrays.asList(1, 2, 3);
- ctx.set("list", list);
- // 获取list.get(0)
- exp = "list[0]";
- System.out.println(exp + "->" + fel.eval(exp));
- // 集合
- Collection<String> coll = Arrays.asList("a", "b", "c");
- ctx.set("coll", coll);
- // 获取集合最前面的元素。执行结果为"a"
- exp = "coll[0]";
- System.out.println(exp + "->" + fel.eval(exp));
- // 迭代器
- Iterator<String> iterator = coll.iterator();
- ctx.set("iterator", iterator);
- // 获取迭代器最前面的元素。执行结果为"a"
- exp = "iterator[0]";
- System.out.println(exp + "->" + fel.eval(exp));
- // Map
- Map<String, String> m = new HashMap<String, String>();
- m.put("name", "Wangxiaoming");
- ctx.set("map", m);
- exp = "map.name";
- System.out.println(exp + "->" + fel.eval(exp));
- // 多维数组
- int[][] intArrays = { { 11, 12 }, { 21, 22 } };
- ctx.set("intArrays", intArrays);
- exp = "intArrays[0][0]";
- System.out.println(exp + "->" + fel.eval(exp));
- // 多维综合体,支持数组、集合的任意组合。
- List<int[]> listArray = new ArrayList<int[]>();
- listArray.add(new int[] { 1, 2, 3 });
- listArray.add(new int[] { 4, 5, 6 });
- ctx.set("listArray", listArray);
- exp = "listArray[0][0]";
- System.out.println(exp + "->" + fel.eval(exp));
- }
- /**
- * 自定义上下文环境
- */
- public static void context() {
- // 负责提供气象服务的上下文环境
- FelContext ctx = new AbstractContext() {
- @Override
- public Object get(String name) {
- if ("天气".equals(name)) {
- return "晴";
- }
- if ("温度".equals(name)) {
- return 25;
- }
- return null;
- }
- };
- FelEngine fel = new FelEngineImpl(ctx);
- String exp = "'天气-----:'+天气+';温度------:'+温度";
- Object eval = fel.compile(exp, ctx).eval(ctx);
- System.out.println(eval);
- }
- /**
- * 多层次上下文环境(变量命名空间)
- */
- public static void contexts() {
- FelEngine fel = getEngine();
- String costStr = "成本";
- String priceStr = "价格";
- FelContext baseCtx = fel.getContext();
- // 父级上下文中设置成本和价格
- baseCtx.set(costStr, 50);
- baseCtx.set(priceStr, 100);
- String exp = priceStr + "-" + costStr;
- Object baseCost = fel.eval(exp);
- System.out.println("期望利润:" + baseCost);
- FelContext ctx = new ContextChain(baseCtx, new MapContext());
- // 通货膨胀导致成本增加(子级上下文 中设置成本,会覆盖父级上下文中的成本)
- ctx.set(costStr, 50 + 20);
- Object allCost = fel.eval(exp, ctx);
- System.out.println("实际利润:" + allCost);
- }
- /**
- * 大数值计算
- */
- public static void testBigNumber() {
- // 构建大数值计算引擎
- FelEngine fel = FelBuilder.bigNumberEngine();
- String input = "111111111111111111111111111111+22222222222222222222222222222222";
- Object value = fel.eval(input);// 解释执行
- Object compileValue = fel.compile(input, fel.getContext()).eval(
- fel.getContext());// 编译执行
- System.out.println("大数值计算(解释执行):" + value);
- System.out.println("大数值计算(编译执行):" + compileValue);
- }
- /**
- * 函数
- */
- public static void userFunction() {
- // 定义hello函数
- Function fun = new CommonFunction() {
- @Override
- public String getName() {
- return "hello";
- }
- /*
- * 调用hello("xxx")时执行的代码
- */
- @Override
- public Object call(Object[] arguments) {
- Object msg = null;
- if (arguments != null && arguments.length > 0) {
- msg = arguments[0];
- }
- return ObjectUtils.toString(msg);
- }
- };
- FelEngine e = getEngine();
- // 添加函数到引擎中。
- e.addFun(fun);
- String exp = "hello('fel')";
- // 解释执行
- Object eval = e.eval(exp);
- System.out.println("hello " + eval);
- // 编译执行
- Expression compile = e.compile(exp, null);
- eval = compile.eval(null);
- System.out.println("hello " + eval);
- }
- /**
- *
- */
- public static void testCompileX() {
- FelEngine fel = getEngine();
- String exp = "单价*数量";
- final MutableInt index = new MutableInt(0);
- // 数据库中单价列的记录
- final int[] price = new int[] { 2, 3, 4 };
- // 数据库中数量列的记录
- final double[] number = new double[] { 10.99, 20.99, 9.9 };
- FelContext context = new AbstractContext() {
- @Override
- public Object get(String name) {
- if ("单价".equals(name)) {
- return price[index.intValue()];
- }
- if ("数量".equals(name)) {
- return number[index.intValue()];
- }
- return null;
- }
- };
- Expression compExp = fel.compile(exp, context);
- for (int i = 0; i < number.length; i++) {
- index.setValue(i);
- Object eval = compExp.eval(context);
- System.out.println("总价[" + price[i] + "*" + number[i] + "=" + eval
- + "]");
- }
- }
- /**
- * 自定义 解释器
- */
- public static void userInterpreter() {
- FelEngine fel = getEngine();
- String costStr = "成本";
- FelContext rootContext = fel.getContext();
- rootContext.set(costStr, "60000");
- FelNode node = fel.parse(costStr);
- // 将变量解析成常量
- node.setInterpreter(new ConstInterpreter(rootContext, node));
- System.out.println(node.eval(rootContext));
- }
- /**
- * 操作符重载,使用自定义解释器实现操作符重载
- */
- public static void operatorOverload() {
- /*
- * 扩展Fel的+运算符,使其支持数组+数组
- */
- FelEngine fel = getEngine();
- // 单价
- double[] price = new double[] { 2, 3, 4 };
- // 费用
- double[] cost = new double[] { 0.3, 0.3, 0.4 };
- FelContext ctx = fel.getContext();
- ctx.set("单价", price);
- ctx.set("费用", cost);
- String exp = "单价+费用";
- Interpreters interpreters = new Interpreters();
- // 定义"+"操作符的解释方法。
- interpreters.add("+", new Interpreter() {
- @Override
- public Object interpret(FelContext context, FelNode node) {
- List<FelNode> args = node.getChildren();
- double[] leftArg = (double[]) args.get(0).eval(context);
- double[] rightArg = (double[]) args.get(1).eval(context);
- return sum(leftArg) + sum(rightArg);
- }
- // 对数组进行求和
- public double sum(double[] array) {
- double d = 0;
- for (int i = 0; i < array.length; i++) {
- d += array[i];
- }
- return d;
- }
- });
- // 使用自定义解释器作为编译选项进行进行编译
- Expression expObj = fel.compile(exp, null, interpreters);
- Object eval = expObj.eval(ctx);
- System.out.println("数组相加:" + eval);
- }
- /**
- * 速度测试
- */
- public static void testSpeed() {
- FelEngine fel = getEngine();
- String exp = "40.52334+60*(21.8144+17*32.663)";
- FelNode node = fel.parse(exp);
- int times = 1000;
- long s1 = System.currentTimeMillis();
- for (int i = 0; i < times; i++) {
- // double j = 40.52334 + 60 * (21.8144 + 17 * 32.663);
- node.eval(null);
- }
- long s2 = System.currentTimeMillis();
- System.out.println("花费的时间:" + (s2 - s1));
- }
- /**
- * 大数据量计算(计算1千万次)
- */
- public static void massData() {
- FelEngine fel = getEngine();
- final Interpreters opti = new Interpreters();
- final MutableInt index = new MutableInt(0);
- int count = 10 * 1000 * 1000;
- final double[] counts = new double[count];
- final double[] prices = new double[count];
- Arrays.fill(counts, 10d);
- Arrays.fill(prices, 2.5d);
- opti.add("单价", new Interpreter() {
- @Override
- public Object interpret(FelContext context, FelNode node) {
- return prices[index.intValue()];
- }
- });
- opti.add("数量", new Interpreter() {
- @Override
- public Object interpret(FelContext context, FelNode node) {
- return counts[index.intValue()];
- }
- });
- Expression expObj = fel.compile("单价*数量", null, opti);
- long start = System.currentTimeMillis();
- Object result = null;
- for (int i = 0; i < count; i++) {
- result = expObj.eval(null);
- index.increment();
- }
- long end = System.currentTimeMillis();
- System.out.println("大数据量计算:" + result + ";耗时:" + (end - start));
- }
- /**
- * 静态方法
- *
- *
- * 如果你觉得上面的自定义函数也麻烦,Fel提供的$函数可以方便的调用工具类的方法 熟悉jQuery的朋友肯定知道"$"函数的威力。
- * Fel东施效颦,也实现了一个"$"函数,其作用是获取class和创建对象。结合点操作符,可以轻易的调用工具类或对象的方法。
- * 通过"$('class').method"形式的语法,就可以调用任何等三方类包(commons lang等)及自定义工具类的方法,
- * 也可以创建对象,调用对象的方法。如果有需要,还可以直接注册Java Method到函数管理器中。
- */
- public static void staticMethod() {
- // 调用Math.min(1,2)
- System.out.println(FelEngine.instance.eval("$('Math').max(1,3)"));
- // 调用new Foo().toString();
- System.out.println(FelEngine.instance
- .eval("$('com.ebiz.fel.Foo.new').toString()"));
- }
- private static FelEngine getEngine() {
- return FelBuilder.engine();
- }
- }
- class ColumnInterpreter implements Interpreter {
- MutableInt index;
- double[] records;
- ColumnInterpreter(MutableInt index, double[] records) {
- this.index = index;
- this.records = records;
- }
- @Override
- public Object interpret(FelContext context, FelNode node) {
- return records[index.intValue()];
- }
- }
- class MutableInt {
- private int value;
- public MutableInt(int i) {
- this.value = i;
- }
- public int intValue() {
- return value;
- }
- public void setValue(int i) {
- this.value = i;
- }
- public void increment() {
- value++;
- }
- }
Foo类:
- import java.util.ArrayList;
- import java.util.Iterator;
- import java.util.List;
- public class Foo {
- private final String name;
- private Foo foo = null;
- static private Foo[] f = new Foo[] { new Foo("array0"), new Foo("array1") };
- static private Foo[] fooes = f;
- public Foo[] getFooes() {
- return fooes;
- }
- public void setFooes(Foo[] fooes) {
- this.fooes = fooes;
- }
- private boolean beenModified = false;
- private String property1 = "some value";
- public Foo(String name) {
- this.name = name;
- }
- public Foo() {
- this("anonymity");
- }
- public static String sayHello(String str) {
- return "hello" + str;
- }
- public class Cheezy {
- public Iterator<String> iterator() {
- return getCheeseList().iterator();
- }
- }
- public String get(String arg) {
- if ("name".equals(arg)) {
- return name;
- }
- return "can't find " + arg;
- }
- public String convertBoolean(boolean b) {
- return "Boolean : " + b;
- }
- public int getCount() {
- return 5;
- }
- public String contact(String a, String b, String c, String d) {
- return a + b + c + c;
- }
- public List<String> getCheeseList() {
- ArrayList<String> answer = new ArrayList<String>();
- answer.add("cheddar");
- answer.add("edam");
- answer.add("brie");
- return answer;
- }
- public Cheezy getCheezy() {
- return new Cheezy();
- }
- public boolean isSimple() {
- return true;
- }
- public int square(int value) {
- return value * value;
- }
- public boolean getTrueAndModify() {
- beenModified = true;
- return true;
- }
- public boolean getModified() {
- return beenModified;
- }
- public int getSize() {
- return 22;
- }
- public String getProperty1() {
- return property1;
- }
- public void setProperty1(String newValue) {
- property1 = newValue;
- }
- public Foo getFoo() {
- return this.foo;
- }
- public void setFoo(Foo foo) {
- this.foo = foo;
- }
- @Override
- public String toString() {
- return this.name;
- }
- }
运行结果:
- -----------1.入门---------
- 67500
- -----------2.使用变量---------
- 67500
- -----------3.获取对象属性---------
- 22
- can't find sample
- anonymity
- fel
- ---------4.调用对象的方法-----------
- Everybody
- --------5.访问数组、集合------------
- intArray[0]->1
- list[0]->1
- coll[0]->a
- iterator[0]->a
- map.name->Wangxiaoming
- intArrays[0][0]->11
- listArray[0][0]->1
- --------6.自定义上下文环境------------
- 天气-----:晴;温度------:25
- --------7.多层次上下文环境(变量命名空间)------------
- 期望利润:50
- 实际利润:30
- ---------8.大数值计算-----------
- 大数值计算(解释执行):22333333333333333333333333333333
- 大数值计算(编译执行):22333333333333333333333333333333
- ----------9.函数----------
- hello fel
- hello fel
- ---------10.自定义 解释器-----------
- 60000
- ----------11.操作符重载----------
- 数组相加:10.0
- ----------12.速度测试----------
- 花费的时间:91
- ----------13.静态方法----------
- 3
- anonymity