linux上perl怎么传输参数,如何在perl子函数中传递参数?
慕村225694
Perl 可以通過函數元型在編譯期進行有限的參數類型檢驗。如果你聲明sub mypush (+@)那么 mypush() 對參數的處理就同內置的 push() 完全一樣了。函數聲明必須要在編譯相應函數調用之前告知編譯器(編譯器在編譯函數調用時會對相應函數用 prototype來查詢它的元型來進行參數檢驗,并決定怎樣編譯此函數調用)。元型只在不用 & 調用函數的時候起作用。就是說在語法上如果你想像內置函數一樣調用,它就表現的像內置函數一樣。如果想用過時的風格通過 & 調用,那么編譯器就無視函數聲明。另外元型在函數引用如 \&foo 和間接調用如 &{$subref} 和 $subref->() 時也不起作用。方法調用也不受元型影響,因為實際調用的函數無法在編譯期決定,它是由繼承關系決定的。因為這個特性最初的目的是使你可以像內置函數那樣調用自己的函數,所以下面就給出等價于內置函數調用方式的函數元型。聲明為 調用方式sub mylink ($$) mylink $old, $newsub myvec ($$$) myvec $var, $offset, 1sub myindex ($$;$) myindex &getstring, "substr"sub mysyswrite ($$$;$) mysyswrite $buf, 0, length($buf) - $off, $offsub myreverse (@) myreverse $a, $b, $csub myjoin ($@) myjoin ':', $a, $b, $csub mypop (+) mypop @arraysub mysplice (+$$@) mysplice @array, 0, 2, @pushmesub mykeys (+) mykeys %{$hashref}sub myopen (*;$) myopen HANDLE, $namesub mypipe (**) mypipe READHANDLE, WRITEHANDLEsub mygrep (&@) mygrep { /foo/ } $a, $b, $csub myrand (;$) myrand 42sub mytime () mytime任何 \ 跟著的函數元型中的字符代表著實際的參數必須由相應字符開頭(參數前可跟my our local 聲明),只有 $ 例外,它可以接收并不以 $ 開頭的 hash 和數組的元素,比如 my_function()->[0]。傳給 @_ 的參數將會是相應實際參數的引用,即對它加 \。你可以用 \[] 來表示多個可用的類型。比如:sub myref (\[$@%&*])上面的函數聲明允許像下面這樣調用 myref() 這個函數myref $varmyref @arraymyref %hashmyref &submyref *glob傳入函數 myref 的第一個參數將分別是一個 scalar、數組、hash、函數、glob 的引用。函數元型中前面不跟 \ 的字符有特殊意義。任何不跟 \ 的 @ % 將代表剩下的所有參數,并提供 list context。而 $ 將提供 scalar context。 & 表示需要一個匿名函數(即sub { } 這樣的結構,不能是變量),當用作第一個參數時可以省掉 sub 關鍵字(如果省掉 sub 則后面跟的逗號也必須要省掉).* 表明可以接收一個 bareword、常量、scalar 表達式、typeglob或 typeglob 的引用。傳入函數的參數要么是一個簡單的 scalar 要么是 typeglob 的引用(后兩種情況)。如果你總是想要一個 typeglob 的引用可以用 Symbol::qualify_to_ref() 將名字轉換成相應的 typeglob 的引用:use symbol 'qualify_to_ref';sub foo (*) {my $fh = qualify_to_ref(shift, caller);...}+ 類似于 $ 但是當遇到數組變量或 hash 變量時表示 \[@%],在其它情況下總是提供scalar context。它適用于可以接收數組變量或數組引用為參數的函數:sub mypush (+@) { # 5.14 中 push 第一個參數可以為數組的引用my $aref = shift;die "Not an arrayref" unless ref $aref eq 'ARRAY';push @$aref, @_;}當用 + 時函數必須要檢驗實際的參數是否是自己需要的類型,因為它不區分 @ %。分號 ; 用來分隔必須的參數和可選的參數。它必須在 @ % 之前,因為它們代表剩下的所有參數。在元型最后或在 ; 之前可以用 _ 來代替 $:它表示如果沒有提供這個參數會傳遞 $_作為對應的參數,它可以用來實現默認參數的語法。注意上面列表最后3個例子,mygrep() 表現的就像列表操作符,myrand() 表現的就像rand() 一樣為一元操作符,mytime() 就像 time() 一樣完全不需要參數。如果你這么用:mytime + 2;你將會得到 mytime() + 2,而不是 mytime(2),沒有函數元型根本無法實現這樣的效果。有意思的是你可以把 & 用在最開始的位置來創造新語法:sub try (&@) {my ($try, $catch) = @_;eval { &$try };if ($@) {local $_ = $@;&$catch;}}sub catch (&) { $_[0] }try {die "phooey";} catch {/phooey/ and print "unphooey\n";};上面的代碼會打印 "unphooey",即是 Try::Tiny 的實現方法。(當然用 &$catch 會將 @_ 暴露給 $catch 但這里并不是我們要考慮的)。讓我們重新實現下 Perl 的 grep 操作符:sub mygrep (&@) { # 無法實現 grep EXPR,LIST 這個語法my $code = shift;my @result;foreach $_ (@_) {push @result, $_ if &$code;}@result;}請不在要函數元型中使用字母或數字,它們被保留作它用,或許在將來用于實現完整的參數列表。不要為老的代碼添加上函數元型,因為有時會改變語意出來奇怪的結果。比如:sub func ($) {my $n = shift;print "you ave me $n\n";}某人在代碼中這么調用它:func(@foo);func(split /:/);只是聲明了函數 func 只接收一個 scalar 參數卻帶來了災難性的結果,原來參數所處的list context 被改為 scalar context,傳入的參數變成 @foo 的元素個數,和分割的元素個數。
總結
以上是生活随笔為你收集整理的linux上perl怎么传输参数,如何在perl子函数中传递参数?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 我是这么自学Java的
- 下一篇: 通过apizza生成python接口测试