引用
Perl的标量变量保存单个值;数组保存一个有序的标量变量;散列保存一个无序的标量集合作为值
个人觉得,正是因为有引用,将标量、数组和散列很好的结合在一起,才在处理复杂的数据结构中游刃有余,引用可以分别数组引用和散列引用,还有个是子例程引用 1. 数组引用
数组引用可以将数组和标量联系在一起
$result = \@array;
从标量再变回数组则叫做解引用
@array_2 = @{$result};
如果想访问@array数组的第一个元素,下述三种方式是等价的,个人喜欢第三种(其实是书中对引用如何可以进行省略的缩写,但是个人觉得还是按照正常写法更加能让别人看懂,不然代码可能会让大部分人都会搞晕了)
$a = $array[0];
$a = ${$result}[0];
$a = $result -> [0];
散列引用
其实对散列引用,也可以粗略理解为将散列转化为标量,那么散列和标量以及数组的又联系到了一起,用法跟数组引用一样,也是用反斜杠进行引用,然后用大括号进行解引用,最后在访问散列中的某个键对应的值
$result = \%hash; %hash_2 = %{$result}; $a = ${$result}{"one"}; $a = ${$result} -> {"one"};
其实将散列引用解引用后,就是一个正常的散列了,可以随意的使用(同样的,这里的大括号也是可以省略的,但是我一般都不省略,以防万一以后理解错了。。)
@key = keys %{$result};
将散列引用存入数组中,这样有效地将散列和数组结合在一起使用,然后在后续有需要的时候解引用后即可返回为散列
@array = (\%hash, \%tmp); %hash_2 = %{$array[0]};
子例程引用
理解了上述2个引用,那么子例程也是相同的用法
sub sum { my @array = @_; my $sum = 0; map{ $sum += $_; }@array; return($sum); } my $function = \∑
引用后肯定也要解引用,子例程的解引用则是用小括号,比如用上述子例程对@array数组求和,同样也是用箭头使代码美观
$array_sum = &$function(@array); $array_sum = $function -> (@array);
匿名
引用是Perl处理复杂数据结构的有力工具的话,那么个人认为匿名则是将其功能进一步升华了。
先简单的介绍下怎么算是匿名数组,如果正常的引用过程是如下:
@tmp = ("a", "bb", "ccc"); $result = \@tmp;
那么按照匿名数组的写法则是如下,可以有效的减少动用脑细胞去思考该如何命名上面的那个@tmp数组
$result = ["a", "bb", "ccc"];
会了匿名数组的写法,那么下述的数组中含有数组就很好理解了
@array = (["a", "bb", "ccc"], "dddd"); @array = (["a", "bb", "ccc"], ["d", "ee", "fff"]);
那么应该就很好理解什么是二维数组了,所谓二维数组,就是上述的代码,数组有匿名数组;对数组里的第一个元素解引用,然后再读取解引用后的数组的第一个元素赋值于新的标量,可用箭头增加代码的可读性
$result = $array[0] -> [0];
了解了匿名数组,那么匿名散列也是相同的意思,不同于匿名数组是用中括号,匿名散列则是用大括号表示
@array = ( { a => "aa", b => "bb", }, { c => "cc", d => "dd", }, )
那么二维散列可以理解为散列里面有匿名散列
%hash = { x =>{ a => "aa", b => "bb", }, c => "cc", } $result = $hash{x} -> {a}
匿名子例程也是跟匿名数组和匿名散列的理解一样,为了减少临时的命名,比如对上述的求和子例程,就可以写成下面这种简单的形式:
$function = sub { my @array = @_; my $sum = 0; map{ $sum += $_; }@array; return($sum); } $array_sum = $function -> (@array);
如果将匿名子例程放入一个子例程中,比如将匿名子例程放入一个find子例程中:
find( sub { my $a = "aaa"; print $a."\n"; }, $path, )
其实个人觉得匿名数组和匿名散列最大的作用在于Perl会自动创建空的匿名数组/散列的引用,比如下面的代码就非常实用
push @{$hash{$i}}, "aaa";
上面这个代码的理解是:在运行这个代码之前,$hash{$i}
并不存在,但是在运行代码时,我们设置了一个数组引用@{$hash{$i}}
,那么Perl就会自动创建一个匿名数组,只是在push
之前,这个匿名数组是空的。
然后可以引申出在标量前面加个@就能转化为数组
@{$tmp} = (1,2,3);
并也可以对二维数组进行直接赋值,尽管这个二维数组之前还并不存在,这样导致了我们认为创建了一个新的有2个元素的数组,并在这个数组的第二个元素上写入了一个匿名数组,然后将"a"赋值于这个匿名数组的第3个元素。
$tmp[1] -> [2] = "a";
出了数组可以像上述这样操作,散列也是可以的,以二维散列的形式对其赋值
$hash{$a} -> {$b} = "c";
然后我们就可以用foreach循环提取出所有的键以及对应的值
foreach my $key1 (keys %hash){
foreach my $key2 (keys %{$hash{$key1}}){
$result = $hash{$key1} -> {$key2}
}
}
至于子例程的引用和匿名子例程的使用,能够帮我们很好的理解面向对象的使用,有些Perl的模块的使用,就是在调用其子例程的引用
本文出自于http://www.bioinfo-scrounger.com转载请注明出处