Lisp的作用域和生存期(scope and extent in lisp)

来源:互联网 发布:华为大数据在贵州 编辑:程序博客网 时间:2024/06/05 19:56
在lisp语言中,scope和extent的概念非常常见。作用域和生存期说的是对象或者是结构在程序的什么时候被引用。作用域指的是空间或者文本域。生存期指的是引用的时间间隔。这两个概念是紧密联系的概念。作用域关注空间而生存期关注于时间。

让我们看一个简单的例子:

(defun copy-cell (x) (cons (car x) (cdr x)))

变量x的作用域是defun 形式的体。 除非在defun的body之中引用,否则没有办法引用这个变量x。同样的, x的生存期(任何对copy-cell的调用)指的是函数调用开始到它退出。

生存期和作用域有以下几种:

Lexical scope.   
例如: 函数的形参通常就是词法作用域的。
Indefinite scope.  指的是可以在程序的任何地方引用。

Dynamic extent .  指的是对象的可以在entiy 建立和显式的销毁对象之前任何时候引用。动态生存期遵类栈规则。
例如: with-open-file 结构打开了一个文件连接并且创造了一个流代表这个连接对象。流对象有不确定的生存期,(Indefinite extent),但是打开文件的连接却是动态生存期的,当控制退出with-open-file结构的时候,不管是正常或者非正常的,流就会自动关闭。

例如: 特殊变量都是有动态的生存期。
Indefinite extent.  entity可以存在任何的时间只要引用仍然保留。
例如:大多数的common lisp 数据对象有 不确定的生存期。


下面我们来举例说明:

一个函数的词法作用域的变量有着不确定的生存期。 例如:

(defun compose (f g )
     #'(lambda (x )
               (funcall f  (funcall g x ))))

这个函数返回参数的函数作为其值。 参数  f g的绑定不会因为函数返回而消失,当调用的时候,它们仍然指向绑定。 因此,
(funcall (compose #'sqrt  #'abs )  -9.0)
将会得到3.0的结果。

除了上面的四个定义外,dynamic scope 指的是 不确定的作用域和动态的生存期。这是一个容易让人引起误会的不好的命名。这是一个传统的叫法。 因此, special variables (特殊变量)有着动态作用域,指的是它有不确定的作用域和动态的生存期。一个特殊变量可以在任何地方被引用只要它有效。

Common lisp中 重要的作用域和生存期规则如下:

1.变量绑定通常具有词法作用域和不确定的生存期。

(Variable bindings for which there is a dynamic-extent declaration also have lexical scope and indefinite extent, but objects that are the values of such bindings may have dynamic extent. (The declaration is the programmer's guarantee that the program will behave correctly even if certain of the data objects have only dynamic extent rather than the usual indefinite extent.)
Bindings of variable names to symbol macros by symbol-macrolet have lexical scope and indefinite extent.)
2.被声明为特殊变量绑定具有动态作用域dynamic scope (指的是不确定的作用域和动态的生存期)。

Bindings of function names established, for example, by flet and labels have lexical scope and indefinite extent.
Bindings of function names for which there is a dynamic-extent declaration also have lexical scope and indefinite extent, but function objects that are the values of such bindings may have dynamic extent.
Bindings of function names to macros as established by macrolet have lexical scope and indefinite extent.
Condition handlers and restarts have dynamic scope (see chapter 29).
3. 通过catch 或者unwind-protect 特殊形式建立的catcher具有dynamic scope。
A catcher established by a catch or unwind-protect special form has dynamic scope.
4,通过block 构造建立的退出点具有词法作用域和动态生存期。
An exit point established by a block construct has lexical scope and dynamic extent. (Such exit points are also established by do, prog, and other iteration constructs.)
5. 通过tagbody建立的go target,通过go引用的tagbody 具有词法作用域和动态生存期。
The go targets established by a tagbody, named by the tags in the tagbody, and referred to by go have lexical scope and dynamic extent. (Such go targets may also appear as tags in the bodies of do, prog, and other iteration constructs.)
6.命名的常量例如nil和pi具有不确定的作用域和不确定的生存期。
Named constants such as nil and pi have indefinite scope and indefinite extent.



参考:
http://www.slideshare.net/lispcontent/scope-and-extent-in-lisp-3446131
http://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node43.html