perl學習筆記(7)

weixin_34219944發表於2012-03-14

開始學習函式。

函式的返回值是最後一個表示式的值,或者是return語句顯式返回的值。
挺有意思的,perl函式的引數不需要宣告,用@_,$_[0],$_[1],$_[2],$_[3],...來引用。

做個練習(f71.pl):
1)看看是傳值還是傳引用
2)順便掌握內插函式的寫法${\&Test($v1,$v2)} 。為什麼需要${\}轉義沒明白。練習的環境是5.8.8,希望更高版本能更省事一些。
3)$v2傳進去了,但是沒使用。這說明perl在傳引數這件事上還是很靈活的。

  1. #!/usr/bin/perl -w  
  2. sub Test {  
  3.         $p1 = $_[0];  
  4.         $_[0]  .= " be changed.";  
  5.         return $p1;  
  6. }  
  7.  
  8. $v1 = "abc";  
  9. $v2 = "efg";  
  10. print "Test return: ${\&Test($v1,$v2)} \n";  
  11. print qq(now v1=$v1\n);  
  12.  
  13. #others' code  
  14. print "foo: [${ \&foo() }]\n";  
  15. print "bar: [@{ [&bar()] }]\n";  
  16. sub foo {  
  17.     return "single message";  
  18. }  
  19. sub bar {  
  20.     return ("hello""world");  

$ perl f71.pl
Test return: abc
now v1=abc be changed.
foo: [single message]
bar: [hello world]

目前我的理解是這種傳引數的方式的要點在於函式是用動態長度的列表來接收引數的。這樣,想一次傳多個列表就要想別的辦法。例如,(@a,@b)=@_;這種接收方式的結果是@a把@_全部接收了。($a,$b,@others)=@_;這樣可以接收多個變數和1個列表,但是列表要放最後面。傳雜湊列表類似的,也要放最後面。

吃完飯回來繼續寫。。。。。

開始學習引用(指標/別名)。

引用的語法:$ref=\$a;  這樣$ref和$a就指向同一個資料塊了嗎?噢,使用$ref和使用$a還是有差別的。$a和$$ref返回的結果是一樣的。為什麼ref前面有兩個$?哈哈,這下大約是捕捉到$的含義了。為了方便閱讀,下面另起一段專門說說這個事。

變數在記憶體中應該是由2部分組成,一部分是“名字”,另一部分是“值的位置”。如果把“值”理解為沒有“名字”的變數,那麼這個事情就能忽悠圓了。執行完$a="abc"; $ref=\$a;以後,記憶體中應該有三塊了:ref(a的位置)、a("abc"的位置)、("abc"),即,ref-->a-->"abc"。\$這個符號返回的是變數的位置,$要根據位置去找下一個變數,那麼$ref就不應該是("abc的位置"),而應該是(複製)ref所指向的變數或常量。因此,想得更多一些,$b=$a; 不應理解為“將a的值拷貝給b”,而應理解為“複製一份a所指向的變數,然後讓b指向這個複製品(儲存這個複製品的位置)”。

通過以上討論,不難發現要想徹底控制ref-->a-->"abc",還缺少獲取變數名稱的操作符。花了不少時間,得到的答案是要用到安裝PadWalker模組(下次再學),網址:http://search.cpan.org/~robin/PadWalker-1.9/PadWalker.pm

練習(f73.pl):

  1. #!/usr/bin/perl -w  
  2.  
  3. $a="abc";  
  4. print "\$a: address " . \$a . "value $a\n";  
  5. $b=$a;  
  6. print "\$b: address " . \$b . "value $b\n";  
  7. $ra=\$a;  
  8. print "\\\$ra: address " . \$ra . " value $ra\n";  
  9. $rb=$ra;  
  10. print "\\\$rb: address " . \$rb . " value $rb\n";  
  11. $$rb="cde";  
  12. print qq(after reset \$\$rb=cde a=$a b=$b \$\$ra=$$ra \$\$rb=$$rb);  
  13. print "\n";  

$ perl f73.pl
$a: address SCALAR(0x8c45600)value abc
$b: address SCALAR(0x8c45684)value abc
\$ra: address REF(0x8c456fc) value SCALAR(0x8c45600)
\$rb: address REF(0x8c45774) value SCALAR(0x8c45600)
after reset $$rb=cde a=cde b=abc $$ra=cde $$rb=cde

陣列引用和雜湊引用同樣的道理。ref-->a-->('a','b','c');

練習(f74.pl):

  1. #!/usr/bin/perl -w  
  2. @a=qw(a b c);  
  3. $ra=\@a;  
  4. %ha=(a=>"1",b=>"2",c=>"3");  
  5. $rha=\%ha;  
  6. print qq(\$\$ra[0]=$$ra[0] \@\$ra[1,2]=@$ra[1,2] \$\$rha{a}=$$rha{a});  
  7. print("\n"); 

$ perl f74.pl
$$ra[0]=a @$ra[1,2]=b c $$rha{a}=1
 

用{}匿名引用雜湊列表,用[]匿名引用順序列表(終於想到一個好名字“順序列表”)。下面是程式碼片斷:

  1. $rh1={a=>"11",b=>"22"};  
  2. print $$rh1{b} . "\n";  
  3. $r1=["a","b","c"];  
  4. print $$r1[2] . "\n"

列印(print)結果:

22
c
 

引用是用變數儲存的,函式用列表接收引數,這樣我們就能夠實現用函式接收多個列表了。而且,通過引用,我們還能模擬二維列表,甚至N維資料結構。

在給函式傳遞引用時,需要特別注意的是引用是可以修改原值的。一般教程中會提示說“危險”,我想這個危險應該是源自“無知”而不是“引用”本身,既然已經明白了引用,就沒什麼可畏懼的,帶著畏懼之心更容易出錯。在實踐中可以增加函式的註釋,註明其傳遞的是引用,還應註明是否對原值有修改。

這次就到這,下次學習正規表示式和CPAN。

相關文章