Chinaunix首页 | 论坛 | 博客
  • 博客访问: 45221
  • 博文数量: 43
  • 博客积分: 1161
  • 博客等级: 少尉
  • 技术积分: 425
  • 用 户 组: 普通用户
  • 注册时间: 2010-04-24 11:14
文章分类
文章存档

2011年(40)

2010年(3)

分类: Python/Ruby

2011-05-14 17:16:08

在Perl中,一个标量(scalar)对应一个单一值.一个数组(array)对应一个列表.一个哈希(hash)对应一系列标量集合,这些标量由另外的标量标示(key).
为了能实现更为复杂的数据结构,Perl引入了引用(reference).
The blackslash(\) character is the "take a reference to" operator.

标量的引用
  1. #!perl
  2. use strict; 
  3. sub add { 
  4.   my $par=shift @_; 
  5.   ++$$par; 
  6. } 
  7. my $val=50; 
  8. my $ref_to_val=\$val;
  9. print $ref_to_val . "\n";
  10. print $$ref_to_val . "\n";
  11. &add($ref_to_val);
  12. print $val . "\n";

标量的引用类似于指向一个标量的指针.
程序第7行定义了一个标量$val,第8行定义指向$val的引用$ref_to_val.
第9行直接用print访问了$ref_to_val,得到的结果是一个内存地址,并标明了这个内存地址中内容的类型为scalar.
第10行对$ref_to_val做了解引用(dereferrence),得到了标量$val的值.
利用传递标量引用为子程序参数,可以实现在子程序内部更改外部标量的值.
同时,这样传递参数省去了数值复制过程,减少了子程序调用开销.
具体的理解和作用与C/C++中的指针/引用概念非常类似.

数组的引用
A reference to the array is like a pointer,it points at the array,but it is not the array itself.
引用本身是一个标量,所以在标量适用的地方,引用都可以用.即,引用可以是数组或哈希的元素.或者存放到一个标量中去.
  1. #!perl
  2. use strict;
  3. my @array=qw(a b c d e f);
  4. my $ref_to_array=\@array;
第3行定义了一个数组@array.
在第4行,\@array是@array的引用,把它存放到标量$ref_to_array中.
引用可以复制,也可以用多个引用指向同一个对象.
  1. #!perl
  2. use feature qw(say);
  3. sub check {
  4.   my $who=shift;
  5.   my $items=shift;
  6.   my @req=qw(preserver sunscrren water_bottle jacket);
  7.   for my $item(@req) {
  8.     unless(grep $itemeq$_,@{$items}) {#not found in list?
  9.     #if(! grep $item eq $_,@{$items}) {
  10.         say "$who is missing $item.";
  11.     }
  12.   }
  13. }
  14. my $name="The Skipper";
  15. my @skipper=qw(blue_shirt hat jacket preserver sunscreen);
  16. my $ref_to_skipper=\@skipper;
  17. &check($name,\@skipper);
  18. say "${$ref_to_skipper}[1]";
这一段程序主要用来演示数组引用的解引用操作.
在check子程序中(第8行)将@skipper的引用做解引用操作,并作为一个数组进行访问.
第18行对@skipper的引用$ref_to_skipper做解引用操作,并只输出了数组中的下标为1的元素.
可以看到,除了尖括号{}和其中的存放引用的变量外,具体的使用方法和使用数组是差不多的.

去掉花括号
大多数时候,做解引用操作的数组引用都是一个简单的标量,例如@{$items}或${$items}[1].这里的数组引用$items就是一个简单的标量.这个时候,就可以省略掉花括号,简写成@$items和$$items[1].
但是,当数组引用不是一个简单标量时,花括号不能去掉,如@{$_[1]}----意思是数组@_中下标是1的元素是一个数组的引用,对这个引用做解引用操作.
如果去掉花括号写成@$_[1],则意思变为$_是一个数组的引用,对其做解引用操作,但其后的下标指示[1]会触发语法错误.

嵌套数据结构
  1. #!perl
  2. use feature qw(say);
  3. use strict;
  4. my @skipper=qw(blue_shirt hat jacket preserver sunscreen);
  5. my @skipper_with_name=('Skipper',\@skipper);
  6. my @professor=qw(sunscreen water_bottel slide_rule batteries radio);
  7. my @professor_with_name=('Professor',\@professor);
  8. my @gilligan=qw(red_shirt hat lucky_socks water_bottle);
  9. my @gilligan_with_name=('Gilligan',\@gilligan);
  10. my @all_with_names=(\@skipper_with_name,
  11.                    \@professor_with_name,
  12.                    \@gilligan_with_name);
  13. say "${$all_with_names[1]}[0]:@{${$all_with_names[1]}[1]}";
可以使用引用实现较为复杂的数据结构,如程序中所示.
可以看到,在第14行,访问嵌套的引用的写法非常的复杂,可读性非常低.
因此需要较为简单明了的嵌套引用的访问方法.

用箭头简化嵌套引用
对于上面的程序,为了取得professor的sunscreen,表达式的写法是
${${$all_with_names[1]}[1]}[0]
$all_with_names[1]:@all_with_names下标为1的元素,@professor_with_name的引用
${$all_with_names[1]}[1]:@professor_with_name下标为1的元素,@professor的引用
${${$all_with_names[1]}[1]}[0]:@professor下标为0的元素,sunscreen.
可以简写为
$all_with_names[1]->[1]->[0]
进一步简写为
$all_with_names[1][1][0]
省略箭头(->)的规则是:
如果箭头(->)被夹在两个下标之间(类似下标的东西),则这个箭头就可以省略.(if the arrow ends up between "subscripty kinds of things",such as square brackets,we can also drop the arrow)
The arrow has to be between non-subscripty things.
  1. #!perl
  2. use feature qw(say);
  3. usestrict;
  4. my@skipper=qw(blue_shirt hat jacket preserver sunscreen);
  5. my @skipper_with_name=('Skipper',\@skipper);
  6. my @professor=qw(sunscreen water_bottel slide_rule batteries radio);
  7. my @professor_with_name=('Professor',\@professor);
  8. my @gilligan=qw(red_shirt hat lucky_socks water_bottle);
  9. my @gilligan_with_name=('Gilligan',\@gilligan);
  10. my @all_with_names=(\@skipper_with_name,
  11.                    \@professor_with_name,
  12.                    \@gilligan_with_name);
  13. my $root=\@all_with_names;
  14. $root->[2]->[1]->[0];
  15. $root->[2][1][0];
  16. $root[2][1][0];
新增加一个@all_with_names的引用$root.
第16,17行的写法都是正确的访问.
第18行,省掉了紧跟在root后的箭头(->),意思变为,root是一个数组的名字(@root),取其中下标为2的元素,这是一个数组的引用...................
然而,root只是一个标量的名字,这就引发了语义和语法错误.

阅读(251) | 评论(0) | 转发(0) |
0

上一篇:怎么写POD

下一篇:引用计数

给主人留下些什么吧!~~