程式扎記: [Perl 文章收集] 如何在 perl 子函數中傳遞 hash

標籤

2012年1月31日 星期二

[Perl 文章收集] 如何在 perl 子函數中傳遞 hash

使用方法一 : 
如果是只有一個參數要傳,且是hash,最直接想到的辦法就是像傳其他類型參數一樣直接傳如 %relhash = count_word(%relhash); 但 : 
1. too expensive. 整個 hash 是被拷貝到函數中, 因此就算你在函數中對該 hash 進行操作, 原本的 hash 並不受影響, 因此需要將修改後的 hash 回傳. 
2. 如果有超過一個參數要傳,而把hash放到最前面,結果在子函數中會合併到第一個hash上面去,如 : 
  1. %relhash = (  
  2.     1=>"one",  
  3.     2=>"two",  
  4.     3=>"three"  
  5. );  
  6.   
  7. $test = "test";  
  8.   
  9. sub printHash()  
  10. {  
  11.     my($var1, %hash2) = @_;  
  12.     print "\t[Test] var1=$var1\n";  
  13.     for my $key (keys %hash2)  
  14.     {  
  15.         my $value = $hash2{$key};  
  16.         print "\t[Test] Hash($key) -> $value\n";  
  17.     }  
  18.     return %hash2;  
  19. }  
  20.   
  21. &printHash($test, %relhash);  
執行結果 : 
[Test] var1=test
[Test] Hash(1) -> one
[Test] Hash(3) -> three
[Test] Hash(2) -> two

以上雖然可以運行,但是複制了整個hash,代價比較大. 而且下面用法傳遞參數會出錯,sub中$var1為空 : 
  1. ...  
  2. sub printHash()  
  3. {  
  4.     my(%hash2, $var1) = @_;  
  5.     ...  
  6. }  
  7.   
  8. &printHash(%relhash, $test);  
執行結果 : 
[Test] var1=
[Test] Hash(test) ->
[Test] Hash(1) -> one
[Test] Hash(3) -> thr
[Test] Hash(2) -> two

3. 如果同時傳了兩個 hash 或 array,在子函數中也會合併到第一個中去,而第二個就會傳不進來! 

使用方法二 : 
一種解決方法是透過傳遞 hash 的 Reference (要傳兩個或以上hash也可以這樣做): 
  1. %relhash = (  
  2.     1=>"one",  
  3.     2=>"two",  
  4.     3=>"three"  
  5. );  
  6.   
  7. $test = "test";  
  8.   
  9. sub printHash()  
  10. {  
  11.     my($var1, $hash2) = @_;  
  12.     print "\t[printHash] var1=$$var1\n";  
  13.     for $key (keys %$hash2)  
  14.     {  
  15.         $value = $hash2->{$key};  
  16.         print "\t[printHash] hash2($key) -> $value\n";  
  17.     }  
  18.     $hash2->{4} = "four";  
  19. }  
  20.   
  21. &printHash($test, \%relhash); # 傳遞 hash 的 reference  
  22.   
  23. while( my($k, $v) = each %relhash)  
  24. {  
  25.     print "\t[Main] relhash($k) -> $v\n";  
  26. }  
執行結果 : 
[printHash] var1=test
[printHash] hash2(1) -> one
[printHash] hash2(3) -> three
[printHash] hash2(2) -> two
[Main] relhash(4) -> four
[Main] relhash(1) -> one
[Main] relhash(3) -> three
[Main] relhash(2) -> two

可以發現在函式中修改 hash, 原本函式外的 hash (傳入的 hash) 也會改變 ! 同理如果要傳多個array : 
  1. ...  
  2. processarrays(\@array1, \@array2);  
  3.   
  4. $sub processarrays{  
  5.    my($a1, $a2) = @_;  
  6.    foreach(@$a1){    # dereferences $a1  
  7.       print $_;  
  8.    }  
  9.    for($i=0; $i<@$a2; $i++){  
  10.        print $a2->[$i];    #get at a particular index within array  
  11.    }  
  12. }  
使用方法三 : 
如果不是有特別需要的話,呼呼,還是直接定義為全局變量,而不傳遞是最方便的啦! 

參考連結 : 
如何在perl子函數中傳遞hash 
Perl 函數傳引用 (Scalar, Array and Hash)

沒有留言:

張貼留言

網誌存檔

關於我自己

我的相片
Where there is a will, there is a way!