lexical scoping翻譯為詞法作用域或靜態(tài)作用域
dynamic scoping翻譯為動(dòng)態(tài)作用域
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.
它們是編程語(yǔ)言中變量可見(jiàn)性作用域的兩種不同的方式涩蜘。簡(jiǎn)單來(lái)說(shuō)部脚,詞法作用域和你書(shū)寫(xiě)程序時(shí)變量定義的位置有關(guān),而動(dòng)態(tài)作用域和程序執(zhí)行時(shí)的上下文有關(guān)故俐。舉例說(shuō)明:
#!/bin/bash
x=1
function g()
{
echo $x
x=2
}
function f()
{
local x=3
g
}
f
echo $x
執(zhí)行輸出:
[yellia lua]$ ./scope.sh
3
1
由此可見(jiàn)bash采用的動(dòng)態(tài)作用域揉阎。
下面再來(lái)看下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)
執(zhí)行的結(jié)果:
[yellia lua]$ ./scope.lua
1
2
3
2
由此可見(jiàn)lua采用的靜態(tài)作用域寝贡,1银酗,2的結(jié)果是因?yàn)間()函數(shù)的定義在f()定義之外堰酿,因此不能訪問(wèn)到x膜毁。當(dāng)g()的函數(shù)定義到f()之內(nèi)時(shí)昭卓,x可以被訪問(wèn)到。
靜態(tài)作用域和first class(第一類值)的特性為實(shí)現(xiàn)閉包提供了支持瘟滨。
再來(lái)看下expect呢候醒,我們發(fā)現(xiàn)expect中的直接報(bào)錯(cuò),為什么呢杂瘸?原來(lái)expect中變量的實(shí)現(xiàn)很簡(jiǎn)單倒淫,根本沒(méi)有全局變量和局部變量的概念,所有的變量只在當(dāng)前命令的執(zhí)行上下文中可見(jiàn)败玉,這也就是為什么proc 定義的函數(shù)不能訪問(wèn)其之外定義變量的原因敌土。
有興趣的還可以看下javascript的實(shí)現(xiàn),它也是支持閉包的語(yǔ)言运翼。