2013-05-28 17 views
6

我有一個返回散列的子例程。子程序的最後幾行:返回散列的子例程 - 將其分解成單獨的變量

print Dumper(\%fileDetails); 
return %fileDetails; 

在這種情況下,翻車機打印:

$VAR1 = { 
      'somthing' => 0, 
      'somthingelse' => 7.68016712043654, 
      'else' => 'burst' 
} 

但是,當我試圖轉儲它調用子程序這一行:

print Dumper(\fileDetailsSub($files[$i])); 

的自卸車打印:

$VAR1 = \'somthing'; 
$VAR2 = \0; 
$VAR3 = \'somthingelse'; 
$VAR4 = \7.68016712043654; 
$VAR5 = \'else'; 
$VAR6 = \'burst'; 

開如果散列被破壞,我不能再使用它了。 爲什麼會發生?我怎樣才能保留子程序返回的正確結構?

感謝, 馬克。

+0

答案出現在你機械地插入你的Dumper()調用的'\\'中:-) –

回答

9

有沒有這樣的事情,在Perl中返回一個散列。

子程序以列表作爲他們的參數,他們可以返回列表作爲他們的結果。請注意,列表與數組是非常不同的生物。

當你寫

return %fileDetails; 

這相當於:

return ('something', 0, 'somethingelse', 7.68016712043654, 'else', 'burst'); 

當調用子程序,並得到該列表後面,有一兩件事你可以做的是將其分配給新的散列:

my %result = fileDetailsSub(); 

做是因爲一個哈希可以用列表進行初始化鍵值對的。 (請記住,(foo => 42, bar => 43)是同樣的事情('foo', 42, 'bar', 43)

現在,當您使用反斜槓參考操作上的哈希,如\%fileDetails,你會得到一個散列引用這是一個標量指向一個哈希值。

同樣,如果你寫\@array,你會得到一個數組引用。

但是當你使用引用運營商名單上,你沒有得到一個列表的引用(因爲名單是不變量(它們是短暫的),它們不能被引用。)相反,參考操作分佈在列表中的項目,所以

\('foo', 'bar', 'baz'); 

使得一個新的列表:

(\'foo', \'bar', \'baz'); 

(在這種情況下,我們得到一個完整的標量引用的列表。)這就是你所看到的當你嘗試Dumper你的子程序的結果:一個引用運算符分佈在你的子程序返回的項目列表上。

因此,一種解決方案是在使用Dumper之前將結果列表分配給實際的散列變量。另一種方法是從子返回散列引用(你反正Dumpering什麼):

return \%fileDetails; 

... 

my $details_ref = fileDetailsSub(); 
print Dumper($details_ref); 

# access it like this: 
my $elem = $details_ref->{something}; 
my %copy = %{ $details_ref }; 

對於更多的樂趣,請參閱:

8

爲什麼不改用散列引用呢?

return \%fileDetails; 

只要它是一個詞彙變量,它不會使其他用途的子例程複雜化。 I:.:

sub fileDetails { 
    my %fileDetails; 
    ... # assign stuff 
    return \%fileDetails; 
} 

當執行離開子程序時,變量超出範圍,但內存中包含的數據仍然存在。

Dumper輸出看起來像這樣的原因是你餵它參考列表。子例程不能返回數組或散列,它們只能返回標量列表。你在做什麼是這樣的:

print Dumper \(qw(something 0 somethingelse 7.123 else burst)); 
0

在列表上下文中,Perl不區分散列和鍵/值對列表。也就是說,如果一個子程序return是一個散列,它真正返回的是一個(key1, value1, key2, value2...)的列表。幸運的是,這兩種方式都有效。如果你把這樣一份名單,並將其分配到一個哈希,你原來的忠實副本:

my %fileDetailsCopy = subroutineName(); 

但是,如果它不會破壞其他代碼,它可能會更有意義,有子回正如TLP所說的那樣,而不是引用散列。

1

您不能直接返回散列,但perl可以根據需要自動在散列和列表之間進行轉換。所以perl將它轉換爲一個列表,並且將它作爲一個列表捕獲。即

Dumper(filedetail()) # list 
my %fd = filedetail(); Dumper(\%fd); #hash 
3

Perl函數不能返回散列,只有列表。 A return %foo聲明將將%foo展平並放入列表並返回展平列表。要獲得被解釋爲一個哈希的返回值,你可以將它分配給一個名爲哈希

%new_hash = fileDetailsSub(...); 
print Dumper(\%new_hash); 

cast it(不知道這是它最好的詞)與操作的%{{...}}序列:

print Dumper(\%{ {fileDetailsSub(...)} }); 

TLP指出的另一種方法是從函數中返回一個散列引用。

相關問題