lexical scoping vs dynamic scoping

lexical scoping翻译为词法作用域或静态作用域

dynamic scoping翻译为动态作用域

With lexical scope, a name always refers to its local lexical environment. This is a property of the program text and is made indenpendent of the runtime call stack by the language implementation. Because this matching only requires analysis of the static program text, this type of scoping is also called static scoping. Lexical scoping is standard in all ALGOL-based languages such as Pascal, Modula2 and Ada as well as in modern functional language such as ML and Haskell. It is also used in the C language and its syntactic and semantic relatives, although with different kinds of limitations. Static scoping allows the programmer to reason about object references such as parameters, variables, constants, types, functions, etc. as simple name substitutions. This makes it much easier to make modular code and reason about it, since the local naming structure can be understood in isolation. In contrast, dynamic scope forces the programmer to anticipate all possible dynamic contexts in whihc module's code my be invoked.

With dynamic scope, each identifier has a global stack of bindings. Introducing a local variable with name x pushes a binding onto the global x stack (which may have been empty), which is popped off when the control flow leaves the scope. Evaluating x in any context always yields the top binding. In other words, a global identifier refers to the identifier associated with the most recent envirenment. Note that this cannot be done at compile-time because the binding stack only exists at run-time, which is why this type of scoping is callled dynamic scoping.

它们是编程语言中变量可见性作用域的两种不同的方式。简单来说,词法作用域和你书写程序时变量定义的位置有关,而动态作用域和程序执行时的上下文有关。举例说明:

#!/bin/bash

x=1

function g()

{

echo $x

x=2

}

function f()

{

local x=3

g

}

f

echo $x

执行输出:

[yellia lua]$ ./scope.sh

3

1

由此可见bash采用的动态作用域。

下面再来看下lua的

#!/usr/local/bin/lua

x=1

local function g()

print(x)

x=2

end

local function f()

local x=3

g()

end

local function f2()

local x=3

local function g2()

print(x)

x=2

end

g2()

end

f()

print(x)

f2()

print(x)

执行的结果:

[yellia lua]$ ./scope.lua

1

2

3

2

由此可见lua采用的静态作用域,1,2的结果是因为g()函数的定义在f()定义之外,因此不能访问到x。当g()的函数定义到f()之内时,x可以被访问到。

静态作用域和first class(第一类值)的特性为实现闭包提供了支持。

再来看下expect呢,我们发现expect中的直接报错,为什么呢?原来expect中变量的实现很简单,根本没有全局变量和局部变量的概念,所有的变量只在当前命令的执行上下文中可见,这也就是为什么proc 定义的函数不能访问其之外定义变量的原因。

有兴趣的还可以看下javascript的实现,它也是支持闭包的语言。

推荐阅读更多精彩内容

  • 最近集中写字,看得东西也就自然地多起来。有以下三点感触: 1.每每看到多号重复的推送(有时换个题目),换汤不换药的...
    红豆hr阅读 84评论 0 0
  • 世界是一同一个地球,却会因为地域,时间,情绪,的不同而不同。 这篇文章是因睁眼―闭眼―睁眼的过程中看到的春...
    叶栖阅读 105评论 0 0
  • 本文定位于理解和总结<Effective Java>的所讲内容,而不是翻译,因此不当之处,还请广大网友指出。 复杂...
    MrCoding阅读 1,382评论 5 14
  • 概览 Tophat回贴基因组 Cufflinks拼接转录本 Cuffmerge整合转录本 Cuffdiff计算转录...
    yangmqglobe阅读 4,535评论 0 6