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)

[Git 文章收集] Differences between git merge and git rebase

Source From  Here Preface Merging and rebasing are the two most popular way to applying changes from one branch into another one. They bot...