2016-08-25 123 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足夠清楚明白!