2010-02-14 55 views
10

Mastering Perl的章節之一,布賴恩·d FOY顯示了List::Util這個片段:這個Perl子程序中的use vars是什麼意思?

sub reduce(&@) { 
    my $code = shift; 
    no strict "refs"; 
    return shift unless @_ > 1; 
    use vars qw($a $b); 
    my $caller = caller; 
    local(*{$caller . "::a"}) = \my $a; 
    local(*{$caller . "::b"}) = \my $b; 
    $a = shift; 
    foreach(@_) { 
     $b = $_; 
     $a = &{$code}(); 
    } 
    $a; 
} 

我不明白什麼是use vars qw($a $b)線的點。即使我評論它,我也會得到相同的輸出&警告。

+1

您是否使用'use strict;使用警告;'在所有之前? – Ether 2010-02-14 16:58:40

+4

一個詭辯 - 列出的代碼不是Bryan D Foy的 - 他引用了Graham Barr(List :: Util的創建者)的代碼。 – DVK 2010-02-14 17:11:47

+0

是的,我做過。爲什麼? – Geo 2010-02-14 17:12:29

回答

11

這樣做是因爲List :: Util在內部使用reduce()函數。

use vars的abscence,當使用該函數給出以下警告:

Name "List::MyUtil::a" used only once: possible typo at a.pl line 35. 
Name "List::MyUtil::b" used only once: possible typo at a.pl line 35. 

你可以看到自己這一點通過運行下面的代碼:

use strict; 
use warnings; 

package List::MyUtil; 

sub reduce (&@) { 
    # INSERT THE TEXT FROM SUBROUTINE HERE - deleted to save space in the answer 
} 

sub x { 
    return reduce(sub {$a+$b}, 1,2,3); 
} 

package main; 
my $res = List::MyUtil::x(); 
print "$res\n"; 

,然後運行它再次與use vars禁用。

+0

包使用減少的事實現在是有道理的。沒有這個解釋,我不知道該相信什麼。 – Geo 2010-02-14 17:39:37

+0

還有一個問題,如果我可以。詞彙$ a和$ b有什麼意義?爲什麼他沒有提到全球的? – Geo 2010-02-14 17:42:13

+3

正確答案的提示在於使用變量僅適用於當前包。因此,List :: Utils本身對任何人都沒有用處。 – DVK 2010-02-14 17:45:31

2

正如DVK所注意到的,如果我們運行帶有use vars註釋的代碼,我們將收到關於變量只被使用一次的警告。

抑制警告的另一種方法是在來電方 - 即撥打reduce而不是撥打reduce函數。當使用來自List::UtilList::MoreUtils的代碼參考(例如,pairwise)功能時,必須執行此操作。這兩種方法都適用於呼叫方:

my @sums = pairwise { no warnings 'once'; $a + $b } @x, @y; 

my @sums = pairwise { our($a, $b);  $a + $b } @x, @y; 
+0

正確 - 但如果reduce()實際上在List :: Utils中多次使用,那麼在reduce()內部僅執行一次對於模塊編寫器來說是一種更好的方法,儘管它並不幫助人們使用該模塊: ) – DVK 2010-02-14 17:44:19

0

從段落之後的代碼解釋它。在同一範圍內,包和詞彙變量可以混合使用:

其餘的reduce工作方式類似於將兩個元素放入包變量$ a和$ b中。 Graham使用這些名稱定義詞法變量,並通過使用符號引用立即指派給調用包中$ a和$ b的typeglobs。之後,$ a和$ b的值是詞法版本。當他調用子程序的參數& {$ code}()時,該代碼將查看其包變量,這是我編寫子例程時有效的變量。瞭解? Inside reduce,我使用的是詞法版本,但在$ code內部,我使用了調用包中的軟件包版本。這就是爲什麼格雷厄姆把他們變成彼此的別名。