2012-08-30 27 views
4

之前我读过“Effective Perl Programming”一书中的相关内容,但并没有真正理解它。今天,我遇到了这个问题,如下面的代码。“我的”和“本地”的区别与符号引用有什么不同?

my $vname = "a"; 
my @a = qw(1 2 3); 
local @array = @$vname; 
foreach(@array) { print "$_\n"; }; 

它什么都没输出。然后我修改这一行:

local @a = qw(1 2 3); 

只是取代了“我”与“地方”,那么它现在的作品。所以我想弄清楚它们之间的区别。

+0

请尝试[perldoc here](http://perldoc.perl.org/functions/local.html) –

+1

谢谢,但我不认为perldoc显示了与编译器视角的本质区别。也许我今晚必须重读Perl书。 – thinkhy

+0

Duplicate:http://stackoverflow.com/questions/3603466/how-is-my-faster-than-local-in-perl和http://stackoverflow.com/questions/129607/what-is-the-difference -between-my-and-local-in-perl – jm666

回答

8

有两种变量的作用域在Perl:

  • 全局变量:他们居住在当前包,可以从外部访问,并且可以拥有“本地”的价值观。该名称可以用作“隐藏”中的密钥,即包变量散列/符号表。
  • 词法变量:它们驻留在当前范围内(大致用大括号分隔)。没有可以检查的符号表。

词法变量和全局变量不会干涉,可以有两个不同的变量具有相同的名称。

大多数Perl变量魔术都会发生在全局变量上。以下语法适用于全局变量:

our $var; 
$::var; 
$main::var; 
${'var'}; 
local $var; 

但不是my $var

因此,我们可以这样写:

@::array = qw(a b c); 
my @secondArray = @{array}; 

哪个副本的阵列。我们还可以看一下阵列与存储在一个变量名:

@::array = qw(a b c); 
my $name = "array"; 
my @secondArray = @{$name}; 

最后一行缩写为… = @$name

这对于词汇变化不可行,因为它们不驻留在藏匿处。

local函数将一个“本地”值赋给当前范围内的全局变量(仅适用于全局变量)以及在此范围内调用的所有子范围内(“动态范围”)。

最初(在Perl 4中)插入变量名称和存储是模拟引用的唯一方法。这些用法现在大都过时了大约20年,因为有参考文献(更安全)。

+0

这是我正在寻找的答案。非常感谢。 – thinkhy

+2

你的文章的关键部分是错误的。 'local $ var'甚至不等于任何其他的。 'local $ var'是唯一一个改变'$ var'的。 ('local local $ var','local $ :: var','local $ main :: var',...将是大致相同的版本。) – ikegami

+0

这被称为“软参考”,是“严格”让你无法做到的事情。 –

9

my创建一个新变量。它只能在声明它的词汇范围内看到。

local创建对范围出口恢复的全局变量的临时备份,但不减少它的范围(它仍然可以整体地看)。它不会创建一个新的变量。

如果可能,您总是希望使用my,但如果您必须处理全局变量(例如$_),则local是一个体面的近似值。

+3

本地'也适用于散列和数组元素,所以它也可以用于临时更改这些元素。 – ikegami

14

有一个perldoc项,回答在perlfaq7这样一个问题:

什么是动态和词汇(静态)作用域有什么区别?在local()my()之间?

local($x)节省掉全局变量$x的原值和 分配的子程序的持续时间是从子程序调用的其他功能 可见一个新值。这在运行时完成 ,所以称为动态作用域。 local()总是影响 全局变量,也称为包变量或动态变量。 my($x)将创建一个新变量,该变量仅在当前的 子例程中可见。这是在编译时完成的,因此称为词法或静态作用域。 my()总是会影响私有变量,也称为 词法变量或(不正确)静态(范围)变量。

例如:

sub visible { 
    print "var has value $var\n"; 
} 

sub dynamic { 
    local $var = 'local'; # new temporary value for the still-global 
    visible();    # variable called $var 
} 

sub lexical { 
    my $var = 'private'; # new private variable, $var 
    visible();    # (invisible outside of sub scope) 
} 

$var = 'global'; 
visible();    # prints global 
dynamic();    # prints local 
lexical();    # prints global 

注意如何在任何时候确实值“私人”获得印刷。这是 ,因为$var只在lexical() 函数的块内具有该值,并且它对被调用的子例程是隐藏的。

综上所述,local()并不会让你认为是私人的,本地的 变量。它给一个全局变量一个临时值。如果你想要私有变量,我的()是你正在寻找的 。

请参阅Private Variables via my() in perlsubTemporary Values via local() in perlsub 的令人难以置信的细节。

+0

纯粹而准确的答案。投票! – gaussblurinc

2

我想专注于主要情况时,你会使用它们:

  • 应该是你的“默认”为您希望保留限制到特定的块变量。这应该是大部分时间
  • 本地是有用的,如果你想使用一个全局变量,特定的一个特殊变量。例如

    local $/;       # enable "slurp" mode 
    local $_ = <$some_file_handle>; # whole file now here 
    

    使用本地防止影响其他代码的变化(包括模块,你没有写)

0

在你的情况,所不同的是local符号表和my解决的一个变量才不是。这是因为,如何使用它重要的:

local @array = @$vname; 

是,你使用$vnamesymbolic reference那(有问题的做法缺席no strict 'refs'告诉我们,你知道自己在做什么)。 Quotha:

只有包变量(全局变量,即使本地化)对于 符号引用可见。词汇变量(用my()声明)不在 符号表中,因此对于此机制是不可见的。

所以符号引用只能引用符号表中的变量。无论您将@a声明为my还是全球local@$vname仅指@main::a。当你说

local @a = qw(1 2 3); 

,你给@main::a一个新的值。当你说

my @a = qw(1 2 3); 

,要创建一个新的词法变量@a,给它一个价值,但离开@main::a不确定。当

local @array = @$vname; 

然后访问的@main::a的值,如果发现它是未定义的,并设置的@array给它的值。

如果这一切似乎令人困惑,那是因为它。这就是为什么你强烈建议你使用strictwarnings(它会在这段代码中引起很大的兴趣),并且不鼓励使用符号引用,除非你知道你在做什么真的是

相关问题