1. Dynamic Scoping 解释:
对应的是static scoping。我们现在熟悉的大部分语言都是static scoping的(C,Python,Java)
static scoping意思是变量在声明之后只能在它所在的block中可见
dynamic scoping则是在对应的subfunction中也可见
2. 用perl(允许dynamic scoping)举个例子:
一共有两个package——AdvancedTournament 和 AdvancedFighter:
我们首先看看变量的声明方:
sub update_fighter_properties_and_award_coins{
#coins_to_obtain等变量是AdvancedFighter这个包中变量
#在这里我们用local关键字将他们变成本地的一个变量
my($self,$fighter,$flag_defeat,$flag_rest) = @_;
local $AdvancedFighter::coins_to_obtain = $AdvancedFighter::coins_to_obtain;
local $AdvancedFighter::delta_attack = $AdvancedFighter::delta_attack;
local $AdvancedFighter::delta_defense = $AdvancedFighter::delta_defense;
local $AdvancedFighter::delta_speed = $AdvancedFighter::delta_speed;
my $history = $fighter->{history_record};
my @history_record = @$history;
my $length = @history_record;
#对这几个本地变量修改
if ($flag_rest){
$AdvancedFighter::coins_to_obtain /= 2;
$AdvancedFighter::delta_attack = 1;
$AdvancedFighter::delta_defense = 1;
$AdvancedFighter::delta_speed = 1;
}
#这里使用两个函数:上面的local变量会自动传入这两个函数
$fighter->update_properties();
$fighter->obtain_coins();
return;
}
函数调用方——update_properties(), obtain_coins():
sub update_properties{
my($self) = @_;
#这里的delta_attack 就是来自于调用这个函数的父函数中的变量
$self->{"attack"} += $delta_attack;
if($self->{"attack"} < 1){
$self->{"attack"} = 1;
}
$self->{"defense"} += $delta_defense;
if($self->{"defense"} < 1){
$self->{"defense"} = 1;
}
$self->{"speed"} += $delta_speed;
if($self->{"speed"} < 1){
$self->{"speed"} = 1;
}
return;
}
这样的话就是典型的dynamic scoping了:update_properties使用的变量可以来自于它的父函数
注意:local修饰的变量允许dynamic scoping,而my是不允许的
3. Dynamic Scoping的优缺点
Advantage:用户可以像使用参数一样使用来自父函数的变量,使得变量的传输更加直接
Disadvantage: 在现在这个时代,代码量非常巨大,如果使用dynamic scoping的话会大大降低代码的可读性已经理解性。因此dynamic scoping已经极少使用了。