首先我们看一段程序:
程序的输出会是1,还是5呢?答案是5,那原因是?
C语言采用的是静态作用域,即词法作用域,变量与值的绑定是通过检查程序的正文,在编译时期完成的,而与程序的运行流程无关。它扫描程序正文,选取最近遇到的那个绑定。
在采用动态作用域的语言里,变量与值的绑定是依赖于程序执行流程的,它是选取在运行的过程中所遇到的最近绑定。象上面的例子,如果C语言采用动态作用域的话,那输出结果将是1。
动态作用域易于实现,它只需顺势查找栈帧,查到谁,谁就和自己绑定。另外,有了动态作用域,可以随时拦截,改变程序的行为。在灵活的同时,随之而来的就是麻烦。为了确定程序的行为,必须仔细查看程序的具体执行流程,稍不小心就有可能引入bug。
既然提到了动态作用域,有没有实际的例子呢?非常幸运,Perl既支持静态作用域,也支持动态作用域。还有,对Perl语言,我平时还是用过,知道点皮毛。
程序的输出结果:
in f after g: x=f, y=g, z=g
at top after f: x=g, y=top, z=g
以上讲静态作用域与动态作用域,是为了引出随后的闭包
#include
<
stdio.h
>
int x = 5 ;
int f() {
return x;
}
int g() {
int x = 1;
return f();
}
int main( int argc, char * argv[]) {
printf("%d ",g());
}
int x = 5 ;
int f() {
return x;
}
int g() {
int x = 1;
return f();
}
int main( int argc, char * argv[]) {
printf("%d ",g());
}
C语言采用的是静态作用域,即词法作用域,变量与值的绑定是通过检查程序的正文,在编译时期完成的,而与程序的运行流程无关。它扫描程序正文,选取最近遇到的那个绑定。
在采用动态作用域的语言里,变量与值的绑定是依赖于程序执行流程的,它是选取在运行的过程中所遇到的最近绑定。象上面的例子,如果C语言采用动态作用域的话,那输出结果将是1。
动态作用域易于实现,它只需顺势查找栈帧,查到谁,谁就和自己绑定。另外,有了动态作用域,可以随时拦截,改变程序的行为。在灵活的同时,随之而来的就是麻烦。为了确定程序的行为,必须仔细查看程序的具体执行流程,稍不小心就有可能引入bug。
既然提到了动态作用域,有没有实际的例子呢?非常幸运,Perl既支持静态作用域,也支持动态作用域。还有,对Perl语言,我平时还是用过,知道点皮毛。
#
!/usr/bin/perl
sub f {
my $x = ' f ' ; # lexical
local $y = ' f ' ; # dynamic
$z = ' f ' ; # global
g();
print " in f after g: x=$x, y=$y, z=$z " ;
}
sub g {
( $x , $y , $z ) = ( ' g ' , ' g ' , ' g ' );
}
( $x , $y , $z ) = ( ' top ' , ' top ' , ' top ' );
f();
print " at top after f: x=$x, y=$y, z=$z " ;
sub f {
my $x = ' f ' ; # lexical
local $y = ' f ' ; # dynamic
$z = ' f ' ; # global
g();
print " in f after g: x=$x, y=$y, z=$z " ;
}
sub g {
( $x , $y , $z ) = ( ' g ' , ' g ' , ' g ' );
}
( $x , $y , $z ) = ( ' top ' , ' top ' , ' top ' );
f();
print " at top after f: x=$x, y=$y, z=$z " ;
in f after g: x=f, y=g, z=g
at top after f: x=g, y=top, z=g
以上讲静态作用域与动态作用域,是为了引出随后的闭包