不管是从理论还是实践的角度出发, Perl 都是偏爱平面线性的数据结构的.
假设你想制作一个二维数组, 显示一组人员的生理数据. 包括年龄、眼睛的颜色和重量等. 可以通过先给每一个独立的成员创建一个数组来实现.
my @john = (47, "brown", 186); my @mary = (23, "hazel", 128); my @bill = (35, "blue", 157);
然后你就可以构造一个附加的数组, 该数组由其他数组的名字组成.
my @vitals = ("john", "mary", "bill");
在小镇上过了一夜之后, John 的眼睛突然变成了"红色", 我们需要一个方法可以仅仅通过使用字符串 "john" 就可以改变数组 @john 的内容. 在 Perl 语言中实现的最常见的形式就是引用(reference).
什么是引用?
在上述例子中, $vitals[0] 的值是 "john". 也就是说它正好包含另外一个变量的名字. 我们说第一个变量应用了第二个变量, 并且这种引用叫符号引用, 因为 Perl 必须在符号表中找出 @john 来才能找到它.
另外一种引用是硬引用, 这种引用是大多数人使用的方法. 如果我们没有指定是那种引用, 那么我们说的就是硬引用.
一个叫 $bar 的变量引用了一个叫 $foo 的变量的内容, 而 $foo 的值是 "bot". 和符号引用不同的是, 硬引用引用的不是另外一个变量的名字, 而是数值本身.
引用可以指向任何数据结构. 因为引用是标量, 所以可以把他们保存在数组和散列中. 从而就有了很多复杂的数据结构, 数组的数组、散列的数组、数组的散列等等.
创建引用
(1) 反斜杠操作符
可以用反斜杠创建一个指向任何命名变量或者子例程的引用.
my $scalarref = \$foo; my $constref = \186_282.42; my $arrayref = \@ARGV; my $hashref = \%ENV; my $coderef = \&handler; my $globref = \*STDOUT;
(2) 匿名数据
上述例子中, 反斜杠操作符只是简单地赋值了已经存在于一个命名变量上的一个引用. 但是有一个例外, 186_282.42 不是一个命名变量的引用, 它只是一个数值. 它就是匿名引用.
匿名引用物只能通过引用来访问. 也可以创建匿名数组、散列和子例程.
[1] 匿名数组组合器
可以用中括号创建一个指向匿名数组的引用.
my $arrayref = [1, 2, [‘a‘, ‘b‘, ‘c‘]];
这个例子组合成了一个有三个元素的匿名数组, 该数组的最后一个元素是指向三个元素的一个匿名数组.
对数组的引用, 它的第三个元素自身就是一个数组引用.
[2] 匿名散列组合器
可以使用大括号创建一个指向匿名散列的引用.
my $hashref = { ‘Adam‘ => ‘Eve‘, ‘Clyde‘ => $bonnie, ‘Antony‘ => ‘Cleo‘ . ‘patra‘, };
如果需要一个函数生成一个新散列然后指向它的引用, 那么有三种不同的方法.
sub hashem { {@_} } # 发生错误返回 @_ sub hashem { +{@_} } # 对 sub hashem { return {@_} } # 对
[3] 匿名子例程组合器
可以通过不带子例程名字的 sub 创建一个匿名子例程.
my $coderef = sub { print "Boink!\n" }; # 现在 &$coderef 打印 "Boink!"
注意分号的位置, 在这里要求用分号是为了终止该表达式. 正常的 sub NAME{} 中是不需要分号的.
(3) 对象构造器
(7) 句柄引用
dd
(8) 符号引用
dd
(9) 引用的隐含创建
dd
使用硬引用
(1) 把变量当做变量名使用
dd
(2) 把BLOCK当做变量名用
dd
(3) 使用箭头操作符
dd
(4) 使用对象方法
dd
(5) 伪散列
dd
(6) 硬引用的其他技巧
dd
(7) 闭包
dd
(8) 用闭包做函数模块
dd
(9) 嵌套子例程
dd
符号引用
dd
大括号、中括号和引号
(1) 引用不能当做散列键用
dd
(2) 垃圾回收、循环引用和若引用
dd