lexical variable 词法变量

LISP定义

A lexical variable is a variable that can be referenced only within the lexical scope of the form that establishes that variable; lexical variables have lexical scope. Each time a form creates a lexical binding of a variable, a fresh binding is established.

Within the scope of a binding for a lexical variable name, uses of that name as a variable are considered to be references to that binding except where the variable is shadowed[2] by a form that establishes a fresh binding for that variable name, or by a form that locally declares the name special.

A lexical variable always has a value. There is no operator that introduces a binding for a lexical variable without giving it an initial value, nor is there any operator that can make a lexical variable be unbound.

Bindings of lexical variables are found in the lexical environment.

bind v.t. (a variable) to establish a binding for the variable.

binding n. an association between a name and that which the name denotes. “A lexical binding is a lexical association between a name and its value.” When the term binding is qualified by the name of a namespace, such as “variable” or “function,” it restricts the binding to the indicated namespace, as in: “let establishes variable bindings.” or “let establishes bindings of variables.”

维基百科

电脑程序设计中,作用域(scope,或译作有效范围)是名字(name)与实体(entity)的绑定(binding)保持有效的那部分计算机程序。不同的编程语言可能有不同的作用域名字解析。而同一语言内也可能存在多种作用域,随实体类型变化而不同。作用域类别影响变量绑定方式,根据语言使用静态作用域还是动态作用域变量的取值可能会有不同的结果。

静态作用域又叫做词法作用域,采用词法作用域的变量叫词法变量。词法变量有一个在编译时静态确定的作用域。词法变量的作用域可以是一个函数或一段代码,该变量在这段代码区域内可见(visibility);在这段区域以外该变量不可见(或无法访问)。词法作用域里,取变量的值时,会检查函数定义时的文本环境,捕捉函数定义时对该变量的绑定。

大多数现在程序设计语言都是采用静态作用域规则,如C/C++C#PythonJavaJavaScript……

相反,采用动态作用域的变量叫做动态变量。只要程序正在执行定义了动态变量的代码段,那么在这段时间内,该变量一直存在;代码段执行结束,该变量便消失。这意味着如果有个函数f,里面调用了函数g,那么在执行g的时候,f里的所有局部变量都会被g访问到。而在静态作用域的情况下,g不能访问f的变量。动态作用域里,取变量的值时,会由内向外逐层检查函数的调用链,并打印第一次遇到的那个绑定的值。显然,最外层的绑定即是全局状态下的那个值。

采用动态作用域的语言有PascalEmacs LispCommon Lisp(兼有静态作用域)、Perl(兼有静态作用域)。C/C++是静态作用域语言,但在宏中用到的名字,也是动态作用域。

总结

静态作用域和静态变量是没有关系的,不要搞混淆。

静态作用域表达的是“绑定”的方式,再直白一点讲就是描述怎么样找到变量:

  • common lisp兼有静态作用域。在foo中寻找y的绑定时,它检查函数foo的定义环境
  • emacs lisp采用的是动态作用域。在foo中寻找y的绑定时,它检查函数foo的执行环境

在词法作用域内,对于函数体中的一个符号,不会逐层检查函数的调用链,而是检查函数定义时的外部环境,即捕捉的是函数定义时该符号的绑定。

C, C++, Python, Java, JavaScript, Lua,大多数现在程序设计语言都是采用静态作用域规则。

发表评论

电子邮件地址不会被公开。