作者回复: 非常好!
遇到看似不正常的东西的时候,其实就是让认知深化的契机。
作者回复: 但只对这个闭包有用。再调用一次函数,新生成一个闭包,就会再生成另一个变量。
作者回复: 那更方便了!
作者回复: 看一下closure.play示例程序:
int a = 0;
function int() fun1(){
int b = 0; //函数内的局部变量
int inner(){ //内部的一个函数
a = a+1;
b = b+1;
return b; //返回内部的成员
}
return inner; //返回一个函数
}
function int() fun2 = fun1();
这时候,fun2是个变量,这个变量就是fun1()中的inner()函数的receiver。这个时候,inner()函数的运行时坐在的作用域是fun2这个变量的。
receiver这个机制是我创造的,不用拘泥于这种实现方式。只要能够实现闭包的原理,就都可以。
作者回复: 你运行antlr命令的时候,通过带不同的参数,会生成数量不等的java文件。工具生成的头上都带有注释,说明是Antlr生成的。
在playscript-java项目中,应该是有6个。1个lexer,1个parser,2个是支持listener,2个是支持visitor的。
其他是手动写的:-)
作者回复: 我这几年对复杂系统有关的理论很感兴趣,曾经在校友的一次聚会上分享了一个主题,其中的主要意思,就是从科学甚至可以推导出哲学,印证古老智慧。
作者回复: 应该说,this本来就用来指代当前作用域的。对象就是一个作用域。所以this总在变是应该的。this不需要我们在代码里去声明,它是一个内在的机制。
动态作用域,是指我们在代码里显式声明的变量,其值不是声明时的作用域里的值,而是运行环境的作用域里的值。
作者回复: :-)
作者回复: 非常好,你注意到了这个细节。
实际上,我在运行时用到了一个小技巧。首先是按照作用域查找变量,这个时候就会找到那个全局变量。在作用域里找不到的时候,再到FunctionObject中去找。所以,其实运行期里,全局变量存了两份。一份是在顶层的栈桢里,一份在FunctionObject里。只不过后者不起作用罢了。
当存在多层函数嵌套的时候,上面的算法可以根据运行时所在的作用域,访问正确的变量。
这个方法有些偷懒,因为毕竟FunctionObject里冗余了一份,浪费空间了。你也可以找其他机制来实现。只要支持闭包的原理就行!
你可以参考ASTEvaluator.java中的getLValue()方法,里面有注释,说了这个思路。
作者回复: lex和yacc都没计划讲。因为这些工具都差不多。掌握原理后,用哪个应该都没问题。
lex(或flex)比较简单,所以会用Antlr一定也会用lex。
yacc(或bison)是LR算法的,我们讲完LR算法以后,你理解这个工具的原理应该也没啥问题。