perl-reference

一个星期学完perl基础知识点,感觉效率有点高啊。不过还是有一些没完全搞懂的地方,其实之前也断断续续的学习了一段时间perl的。学习了perl发现,它并没有人们所说的那么难,可能是一些定义比较难懂,或者说更接近基础,更接近c语言吧。

我觉得这个reference是perl的精髓,虽然大家都说正则才是它的特色。

由于这一节基本都是对数据的操作,所以先复习一下各种数据类型的声明方式:

1
2
3
4
5
# array
@array = (value1,value2,....);

# hash
%hash =(key1 => value1, key2 => value2,.......);

reference的作用

由于list和hash只能存放标量变量,所以不能写嵌套的list和hash,但是却可以通过reference来将list和hash放入list或者hash中,因为reference是一个标量变量。它的作用就是为了构建复杂的数据结构

之前在这里的理解不对,这里所说的list和hash只能存放变量指的是这个list或者hash中的数据类型就只能是变量,不能将一个list或者hash直接放这个里面作为一个嵌套的list或者hash,这里的嵌套指的是层次上的嵌套

比如:

1
2
3
4
5
6
@list = (1,
---------2,
---------@sublist('a',
------------------'b'
------------------)
---------)

那么如果把list或者hash放入这个里面的结果是什么呢?就是list或者hash会展开,例如数据合并,这种方法在python中用的很多,反而觉得理所应当了。

1
@list = (1,2,3,(4,5,6))
1
2
3
4
@nums = (-4,-3,-2,-1);
@list = (1,2,3,4,@nums);
print @list;
# -4,-3,-2,-1,1,2,3,4

reference

In Perl, we use variables to access data stored in a memory location(all data and functions are stored in memory). Variables are assigned with data values which are used in various operations. Perl Reference is a way to access the same data but with a different variable. A reference in Perl is a scalar data type which holds the location of another variable. Another variable can be scalar, hashes, arrays, function name etc. Nested data structure can be created easily as a user can create a list which contains the references to another list that can further contain the references to arrays, scalar or hashes etc.

1
2
3
4
5
# 四种类型的normal reference
$varRef = \$var
$listRef = \@list
$hashRef = \%hash
$subroutineRef = \&subroutine

reference比较难懂,它实际是存放的一个内存地址,指向的是变量。可以说是变量的一个alias.那么refere2ence的数据的操作与变量对数据的操作效果一样。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/usr/bin/perl

$var = 'hello wolrd';
$varRef = \$var;
$$varRef = 'ref change';

print $var,"\n";
print $varRef,"\n";
print $$varRef,"\n";

print "---------------\n";
$var = 'origon change';

print $var,"\n";
print $varRef,"\n";
print $$varRef,"\n";
1
2
3
4
5
6
7
ref change
SCALAR(0x55d88b2f40f8)
ref change
---------------
origon change
SCALAR(0x55d88b2f40f8)
origon change

dereference

前面reference只是生成了一个保存有数据内存地址的变量,然而要真正操作数据(这里的操作是指对数据的修改等,引用不属于),还需要dereference。dereference后就与变量一样了

1
2
3
4
5
# 四种类型的dereference
$$varRef
@$listRef
%$hashRef
&$subroutineRef

取值方式

数组list

1
2
3
4
5
6
@list = (1..5);
#变量取值
$list[0];
#reference取值
$listRef = \@list;
$listRef -> [0];

哈希hash

1
2
3
4
5
6
%hash = ('a' => '1','b' => '2');
#变量取值
$hash{'a'};
#reference取值
$hashRef = \%hash;
$hashRef -> {'a'};

anonymous reference

前面的reference都是通过指向已经存在的变量。其实还可以直接指向数据,这就是anonymous reference

list anonymous reference使用[]

1
2
# list anonymous reference,数组不使用()而是使用[]
$listRef = [1..5];

hash anonymous reference使用{}

1
2
# hash anonymous reference,数组不使用()而是使用{}
$hashRef = {'a' => 1,'b' => 2};

symbolic reference

这种不常用,而且只能用于标量,同时use stricts时,无法通过编译。

1
2
3
4
5
6
7
# 不reference,直接dereference
my $foo = "bar";
$$foo = "whatever";

print $foo,"\n"; # bar
print $$foo , "\n"; # whatever
print $bar, "\n"; # whatever

可以发现,它使用了标量的值作为一个reference了。我是没发现这样做有啥用处

autovivification

前面的symbolic reference是直接dereference一个存在值的标量变量。那么autovivification则是直接“dereference”一个不存在值的变量。它可以用于scalar,list,hash。而且是perl独有的特性,可以说相当强大。

对dereference理解:autovivification的dereference不是加\

Autovivification only works on undefined values. If you have a scalar without a value and use it like it’s an array reference, Perl makes it an array reference

autovivification的方式:

  • Perl autovivifies when you use an undefined value like it’s a reference
  • An undefined value in exists autovivifies
  • Perl can autovivify when you store a value or fetch a value
1
2
3
4
5
6
# 并不存在hash,却使用了不存在hash的匿名reference赋值
my $foo->{address}->{building} = 1000;

print $foo, "\n"; # HASH(0x3bad24)
print $foo->{address}, , "\n"; # HASH(0x3bae04)
print $foo->{address}->{building},"\n"; # 1000

这两个例子就可以看出autovivification的优势,不需要先声明一个数据结构,可以直接使用。在数据结构比较复杂的时候写出来却非常简单,不知道用什么言语来形容对它的喜爱。

1
2
3
4
5
6
7
8
9
@list = ();
$list[3] = 'define';
print @list,"\n";

$array[3] = 'define and assign value';
print @array,"\n";

$listRef -> [3] = 'autovivification';
print @$listRef,"\n";

在数组中,初始数组的长度为autovivication时指定索引的长度。

以上是简单的介绍,至于说详细怎么使用,那就比较灵活了。别人已经写的超级好了,我就不写了,链接

总结:

数据结构的使用:

普通声明:

1
2
3
4
5
# array
@array = (value1,value2,....);

# hash
%hash =(key1 => value1, key2 => value2,.......);

匿名声明:使用了reference

1
2
3
4
5
# array
$array = [value1,value2,.....];

# hash
$hash = {key1 => value1, key2 => value2,...};

autovivification:使用了referenece和dereference

1
2
3
4
5
6
7
8
# array
$array -> [0] = value1;
# 由于autovivification是用于未使用的变量,所以其它的值需要dereference后添加,毕竟它的作用主要是自动生成复杂数据结构
@$array -> [1] =value2;

# hash
$hash -> {key1} = value1;
%$hash -> {key2} = value2;

终于把reference学完了,之前学了还有许多不懂的地方,这次看了很多资料,总算理解了。可能是我c语言忘的差不多了(大一学的选修课),所以在内存中数据如何存储的地方有很多疑惑。