2016-08-25 79 views
0

我是Perl新手,对子例程中变量的用法有疑问。Perl中的变量范围

#! /usr/bin/perl 

    $x=4; 
    &routine; 
    print "value of x in main is $x\n"; 

    sub routine 
    { 
     local $x = 10; 
     print "value of x in routine is $x\n"; 
     print "value of x in main is $x\n";  #what should be replaced in $x to get correct answer 
    } 

由于在节目中,我应该在这条线

print "value of x in main is $x\n"; 

得到$ x变量在main函数值来代替?

+1

你期望打印'10'和'4'的值吗? –

回答

1

“本地”语句有效地隐藏了全局变量的原始值。如果您需要原始值,你将有“本地”声明之前进行复制:

$x=4; 
&routine; 
print "value of x in main is $x\n"; 

sub routine 
{ 
    my $originalX = $x; 
    local $x = 10; 
    print "value of x in routine is $x\n"; 
    print "value of x in main is $originalX\n"; 
} 

最有用的属性格式“本地”,而不是“我”是当地的价值仍然可见从局部变量范围内调用的函数。

our $x=4; 
foo(); 
print "value of x in main is $x\n"; 

sub foo { 
    local $x = 10; 
    print "value of x in foo is $x\n"; 
    bar(); 
} 

sub bar { 
    print "value of x in bar is $x\n"; 
} 

结果

value of x in foo is 10 
value of x in bar is 10 
value of x in main is 4 
1

有几件事情需要在这里了解关于变量,以及Perl中,并使用它们。

当您声明$x并指定值4时,您实际上是在定义一个包变量。如果不使用strict编译指示(通过使用use strict 'vars'use strict启用),则不必在变量声明前面加上myour。因此,Perl将默认初始化为$x作为包变量。软件包通过package关键字设置,如果省略,那么perl默认为main软件包。这意味着您创建了一个名为$main::x的包变量,其值为4。在保留包main的同时,您可以使用别名$x来表示$main::x

包变量可以在你的主包范围内的任何地方使用的(通常被称为全局变量),这就是为什么你可以在子程序routine()访问$x

local将在声明的范围期间存储$x的值,直到它声明的范围结束。因此,在您的示例中,local声明的范围适用于整个范围routine()(之间使用local,并在routine()声明中关闭}大括号)。离开示波器时,它将$x重新初始化为存储值。这就是为什么调用routine()后的打印语句显示$x4

首先回答你眼前的问题:

因为local是特定于它是利用在封闭,可以在routine()创建一个单独的用。这样,您就可以在该范围内的定位$x,但你的子程序中保留的$x包变量:

#! /usr/bin/perl 

$x=4; # declare a package variable $main::x 
routine(); 
print "value of x in main is $x\n"; 

sub routine { 
    # now create a closure, so we can localize the package variable 
    # within its own scope 
    { 
     local $x = 10; 
     print "value of x routine, within locally scoped closure is $x\n"; 
    } 
    print "value of x _from_ main is $x\n"; #will now print 4 
} 

在其他的答案谈到,在Perl的最佳做法是使用strict标记,以及要求警告当检测到错误的编码:

use strict; 
use warnings 'all'; 

这样运行你的代码,然后给出:

Global symbol "$x" requires explicit package name

我们可以用几种方法解决这个问题,我们可以用一个包名声明它:

$main::x = 4; 

然后还要implictly引用它在代码的其余部分为$main::x

或者,如果我们愿意有机会获得别名,我们可以使用关键字our声明$main::x作为一个包变量,然后把它称为$x在我们代码的其余部分。

our $x=4;  # (is the same as writing $main::x = 4, but you also 
       # can refer to it by its alias $x from this point onwards). 

有了这些点覆盖,那么你可以有最终的推荐方案:

#! /usr/bin/perl 

use strict; 
use warnings 'all'; 

our $x=4; # declare a package variable $main::x 
routine(); 
print "value of x in main is $x\n"; 

sub routine { 
    # now create a closure, so we can localize the package variable 
    # within its own scope 
    { 
     local $x = 10; 
     print "value of x routine, within locally scoped closure is $x\n"; 
    } 
    print "value of x _from_ main is $x\n"; # will now print 4 
} 

额外信息

注意局部变量保持在范围内,即使其他子程序中调用那范围:

our $x=4; 
routine(); 

sub routine { 
    { 
     local $x = 10; 
     print "routine() localized, x is $x\n"; 
     another_routine(); 
    } 
    print "routine() x is $x\n"; 
} 

sub another_routine { 
    print "another_routine() still localized, x is $x\n"; 
} 

将输出:

routine() localized, x is 10 
another_routine() still localized, x is 10 
routine() x is 4 

我们都没有碰过开放词法变量my关键字(有时被称为私有变量我的变量)声明。这些行为是不同的,他们只活过他们在范围内的期限(技术上直到他们的引用计数变为0,但这是另一个话题!)。这使我们能够宣布其(例如)只得到您的routine()子程序期间创建和使用的变量:

sub routine { 
    my $y = 20; 

    print "y is set to $y during the duration of routine()\n"; 
} 

my也有让我们重新使用包变量名的潜移默化的影响,并使用私人 。该变量,因为他们在被宣布范围的持续时间值注意,他们没有表现得像局部变量和范围内调用其他程序会默认使用包变量值:

our $x=4; 
routine(); 

sub routine { 
    my $x = 20; 

    print "routine() x is $x\n"; 
    another_routine(); 
} 

sub another_routine { 
    print "another_routine() x is $x\n"; 
} 

将输出:

routine() x is 20 
another_routine() x is 4 

$xroutine()私人routine()只有routine()

我希望lanuague足够清楚明白!