Common Lisp 中动态作用域变量

2012-06-23
      本来起的标题是《Lisp 变量》,但是我目前并不知到Lisp其他实现的变量体系,这样的话就名不符实了,做人,还是实事求是好。 类型:lexical  scope,dynamic scope。Common Lisp提供了两种创建全局变量的方式:DEFVAR DEFPARAMETER(总是赋初始值)。这个倒是好理解,难点在于动态作用域和静态作用域。
      静态作用域是现行绝大部分编程语言采用的方式。例如C、Java,在一个函数/方法中有一个变量,如果不是属于当前方法内部的,就是属于上层的。C语言中没有namespace,把一个文件作为一个module,所以先会在当前的C 文件中找,然后在extern 中寻找,在Java中还简单一些,基本上只会往上到class 属性变量中查找。这是对代码做静态分析。我们可以明确知道一个变量是否已经被定义,在哪儿被定义。
      动态作用域就比较有意思了。变量的寻找过程发生在程序运行时期。在某个时间点,程序要对变量 varA 求值,此时的函数调用stack是 funcA ->   funcB -> funcC -> funcD,会反向的往上的每层函数实体中寻找,直到找到为止,也有可能找不到(这种情况在静态作用域语言中是不可能出现的)。如果程序在funcD中这个varA 出错了,是非常难以debug 的。因为funC 可以是 funcE, fucnF, funcG, funcH, 同样funcB 也可以是任意一个函数,如果调用层次有个10层,每层有十种分支,那就是10^10 中组合的可能性,你上哪儿去中对varA操作错误的点呢?
      动态作用域并不等同于全局作用域,对于当前不被运行的代码是无法感知到的。我不知道为什么Common Lisp 还支持动态作用域,这么容易出错,看起来好鸡肋啊。
Apr 24, 2014
      现在动态作用域语言基本上都消失了,我们需要更加可控的语言。在工程中,需要取得一种平衡,需要综合考虑多方面的因素。而不是根据自己的喜好来选择工具。
如果有任何意见,欢迎留言讨论。


[ 主页 ]
COMMENTS
POST A COMMENT

(optional)



(optional)