以遇见为主题做网站,安徽省六安市建设局网站,如何做好电商网站,wordpress 连接丢失慕村225694Perl 可以通过函数元型在编译期进行有限的参数类型检验。如果你声明sub mypush ()那么 mypush() 对参数的处理就同内置的 push() 完全一样了。函数声明必须要在编译相应函数调用之前告知编译器(编译器在编译函数调用时会对相应函数用 prototype来查询它的元型来进行参…慕村225694Perl 可以通过函数元型在编译期进行有限的参数类型检验。如果你声明sub mypush ()那么 mypush() 对参数的处理就同内置的 push() 完全一样了。函数声明必须要在编译相应函数调用之前告知编译器(编译器在编译函数调用时会对相应函数用 prototype来查询它的元型来进行参数检验并决定怎样编译此函数调用)。元型只在不用 调用函数的时候起作用。就是说在语法上如果你想像内置函数一样调用它就表现的像内置函数一样。如果想用过时的风格通过 调用那么编译器就无视函数声明。另外元型在函数引用如 \foo 和间接调用如 {$subref} 和 $subref-() 时也不起作用。方法调用也不受元型影响因为实际调用的函数无法在编译期决定它是由继承关系决定的。因为这个特性最初的目的是使你可以像内置函数那样调用自己的函数所以下面就给出等价于内置函数调用方式的函数元型。声明为 调用方式sub mylink ($$) mylink $old, $newsub myvec ($$$) myvec $var, $offset, 1sub myindex ($$;$) myindex getstring, substrsub 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 的元素个数和分割的元素个数。