perl基础-2
函数参数
perl 函数参数为$$,$$$,$@
Perl 可以通过函数元型在编译期进行有限的参数类型检验。
如果你声明 sub mypush (+@)那么 mypush() 对参数的处理就同内置的 push() 完全一样了。
函数声明必须要在编译相应函数调用之前告知编译器(编译器在编译函数调用时会对相应函数用 prototype来查询它的元型来进行参数检验,并决定怎样编译此函数调用)。
元型只在不用 & 调用函数的时候起作用。就是说在语法上如果你想像内置函数一样调用,它就表现的像内置函数一样。如果想用过时的风格通过 & 调用,那么编译器就无视函数声明。
另外元型在函数引用如 &foo 和间接调用如 &{$subref} 和 $subref->() 时也不起作用。方法调用也不受元型影响,因为实际调用的函数无法在编译期决定,它是由继承关系决定的。因为这个特性最初的目的是使你可以像内置函数那样调用自己的函数,所以下面就给出等价于内置函数调用方式的函数元型。
声明 | 调用方式 |
---|---|
sub mylink ($$) | mylink $old, $new |
sub myvec ($$$) | myvec $var, $offset, 1 |
sub myindex ($$;$) | myindex &getstring, "substr" |
sub mysyswrite ($$$;$) | mysyswrite $buf, 0, length($buf) - $off, $off |
sub myreverse (@) | myreverse $a, $b, $c |
sub myjoin ($@) | myjoin ':', $a, $b, $c |
sub mypop (+) | mypop @array |
sub mysplice (+$$@) | mysplice @array, 0, 2, @pushme |
sub mykeys (+) | mykeys %{$hashref} |
sub myopen (*;$) | myopen HANDLE, $name |
sub mypipe (**) | mypipe READHANDLE, WRITEHANDLE |
sub mygrep (&@) | mygrep { /foo/ } $a, $b, $c |
sub myrand (;$) | myrand 42 |
sub mytime () | mytime |
任何 \ 跟着的函数元型中的字符代表着实际的参数必须由相应字符开头(参数前可跟my our local 声明).
只有 $ 例外,它可以接收并不以 $ 开头的 hash 和数组的元素,比如 my_function()->[0]。
传给 @_ 的参数将会是相应实际参数的引用,即对它加 \。你可以用 [] 来表示多个可用的类型。比如: sub myref ([$@%&*])
上面的函数声明允许像下面这样调用 myref() 这个函数
myref $var
myref @array
myref %hash
myref &sub
myref *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 /
perl基础-2的更多相关文章
- Perl基础速成
本文是针对没有Perl基础,但想用perl一行式命令取代grep/awk/sed的人,用于速学Perl基础知识. Perl一行式系列文章:Perl一行式程序 perl的-e选项 perl命令的-e选项 ...
- Perl 基础语法
Perl 基础语法 Perl借用了C.sed.awk.shell脚本以及很多其他编程语言的特性,语法与这些语言有些类似,也有自己的特点. Perl 程序有声明与语句组成,程序自上而下执行,包含了循环, ...
- 2.Perl基础系列之入门
官网提供的入门链接:http://perldoc.perl.org/perlintro.html 语法概述 Perl的安装步骤省略,直接去官网下载并按照提示安装即可. 如果Perl安装没问题,那么运行 ...
- perl基础-1
基础 向函数中传递两个数组,使用指针 sub getSql{(my a,my b)=@_;my @array=@$a;} my @a;my @b; getSql(\@a,\@b); length($s ...
- perl基础:传递hash类型参数
1 如果是只有一个参数要传,且是hash,最直接想到的办法就是像传其他类型参数一样直接传, 如: subFuntion(%hash1); 2 如果有多于一个参数要传,这里假设只有一个参数的类型是h ...
- perl基础
perl比较好的博客:http://www.cnblogs.com/cosiray/archive/2012/03/18/2404371.html 以分析一个简单的pm文件为例 # # オプションの取 ...
- 1.Perl基础系列之WHAT、WHY、HOW
What? Perl,一种功能丰富的计算机程序语言,运行在超过100种计算机平台上,适用广泛,从大型机到便携设备,从快速原型创建到大规模可扩展开发. Why? Perl追求简洁快速地解决问题,可很方便 ...
- Perl基础(1)chop与chomp的区别
chop是去掉字符串的最后一个字符 chomp是去掉"$/"指定的结尾符号 测试程序一: [perl] #!/bin/perl $tmp = "sincere" ...
- perl基础01
参考:Perl教程 1.Perl简介 Perl是Practical Extraction and Report Language的缩写,它是由Larry Wall设计的. Perl具有高级语言的强大能 ...
- Perl基础语法
一.脚本文件perl 代码可以写在一个文本文件中,以 .pl..PL 作为后缀.文件名可以包含数字,符号和字母,但不能包含空格,可以使用下划线(_)来替代空格.一个简单的Perl 文件名:rurun_ ...
随机推荐
- JDK 监控和故障处理工具总结 (转)
出处: JDK 监控和故障处理工具总结 JDK 监控和故障处理工具总结 JDK 命令行工具 jps:查看所有 Java 进程 jstat: 监视虚拟机各种运行状态信息 jinfo: 实时地查看和调整 ...
- 基础数据类型之集合和深浅copy,还有一些数据类型补充
集合 集合是无序的,不重复的数据集合,它里面的元素是可哈希的(不可变类型),但是集合本身是不可哈希(所以集合做不了字典的键)的.以下是集合最重要的两点: 去重,把一个列表变成集合,就自动去重了. 关系 ...
- mac 下安装mysql8.0
有两种安装方式,一种是安装包安装,官网下载安装包,mysql8.0下载.mysql5.7安装: 这里记录brew安装: 1.brew uninstall mysql 卸载原有的: 2.brew ins ...
- IDEA导入Eclipse 非Maven的Web项目
- 安装kubuctl
安装和设置kubectl 使用Kubernetes命令行工具kubectl在Kubernetes上部署和管理应用程序.使用kubectl,可以检查集群资源; 创建,删除和更新组件. 以下是安装kube ...
- Tomcat 7 自动加载类及检测文件变动原理
在一般的 web 应用开发里通常会使用开发工具(如 Eclipse.IntelJ )集成 tomcat ,这样可以将 web 工程项目直接发布到 tomcat 中,然后一键启动.经常遇到的一种情况是直 ...
- 04 Websocket和Websocketed
一.web socket事件和方法 有了HTTP协议为什么还需要Websocket这种协议呢?因为HTTP协议发起的通信只能通过客户端发起,然后服务端才可以将消息回应到客户端.因此HTTP协议做不到服 ...
- javaweb中的标签的核心标签库的常用标签
//标签的使用使得页面的代码更加简洁,jsp脚本的尽可能少的使用,所以熟练掌握标签对于开发是很有必要的 <%--set设置数据,默认在page域 --%> <c:set var=&q ...
- 11条sql技巧
1. 负向条件查询不能使用索引 select * from order where status!=0 and stauts!=1 not in/not exists都不是好习惯 可以优化为in查询: ...
- 《Python基础教程》一点笔记
这本书还是月初的时候翻了翻,看了前十章左右就发现这本书写的比较烂,翻译地就更烂了,讲的内容其实没有抓住重点. 下面是看的时候记得几小段代码: #首字母相同的男生女生 girls = ['alice', ...