是个scalar,因此它需要一个scalar值。当你尝试将@inner这样的array值赋给它,@inner就会在scalar上下文中被求值,这就与将scalar @inner是同样的效果。这相当于求出了array @inner的长度,也就是2。

    然而,scalar变量可以包含任何变量的引用,包括array和hash。在Perl中,复杂的数据结构就是这样被构造出来的。

    我们用反斜杠来创建一个引用。

    1. my $colour = "Indigo";
    2. my $scalarRef = \$colour;

    如果你能够使用某个变量名,你可以加一些花括号,把一个变量的引用放进去。

    1. print $colour; # "Indigo"
    2. print $scalarRef; # 输出可能是 "SCALAR(0x182c180)"
    3. print ${ $scalarRef }; # "Indigo"

    如果结果没有歧义的话,你甚至可以直接省略掉花括号:

    1. print $$scalarRef; # "Indigo"
    1. my @colours = ("Red", "Orange", "Yellow", "Green", "Blue");
    2. my $arrayRef = \@colours;
    3. print $colours[0]; # 直接访问array元素
    4. print ${ $arrayRef }[0]; # 通过引用访问array元素
    5. print $arrayRef->[0]; # 与上一句等价
    6. my %atomicWeights = ("Hydrogen" => 1.008, "Helium" => 4.003, "Manganese" => 54.94);
    7. my $hashRef = \%atomicWeights;
    8. print $atomicWeights{"Helium"}; # 直接访问hash元素
    9. print ${ $hashRef }{"Helium"}; # 通过引用访问hash元素
    10. print $hashRef->{"Helium"}; # 与上一句等价 - 这种写法相当常见

    声明数据结构

    这里有4个例子,不过现实中最后一个最有用。

    显然可以不用这么费劲,这段代码可以简化为:

    1. my %owner1 = (
    2. "name" => "Santa Claus",
    3. "DOB" => "1882-12-25",
    4. );
    5. my %owner2 = (
    6. "name" => "Mickey Mouse",
    7. "DOB" => "1928-11-18",
    8. );
    9. my %account = (
    10. "number" => "12345678",
    11. "opened" => "2000-01-01",
    12. "owners" => \@owners,
    13. );

    用不同的符号声明匿名的array和hash也是可行的。用方括号声明匿名array,而用花括号声明匿名hash,这两种方法返回的是声明的匿名数据结构的引用。看仔细了,下面的代码声明的%account和上面的完全等价:

    1. # 花括号表示匿名hash
    2. my $owner1Ref = {
    3. "name" => "Santa Claus",
    4. "DOB" => "1882-12-25",
    5. };
    6. my $owner2Ref = {
    7. "name" => "Mickey Mouse",
    8. "DOB" => "1928-11-18",
    9. };
    10. # 方括号表示匿名array
    11. my $ownersRef = [ $owner1Ref, $owner2Ref ];
    12. my %account = (
    13. "number" => "12345678",
    14. "opened" => "2000-01-01",
    15. "owners" => $ownersRef,
    16. );

    或者写得更加简短(这也是你真正应该用来声明复杂数据结构的方法):

    1. my %account = (
    2. "number" => "31415926",
    3. "opened" => "3000-01-01",
    4. "owners" => [
    5. {
    6. "name" => "Philip Fry",
    7. "DOB" => "1974-08-06",
    8. "name" => "Hubert Farnsworth",
    9. "DOB" => "2841-04-09",
    10. },
    11. ],
    12. );

    从数据结构中获取信息

    现在我们假设你还在折腾那个%account,而且其他东西都不在作用域内(如果还有其他东西的话)。你可以逆向操作解引用,以取得每一项需要打印的信息。同样,这里有4个例子,其中最后一个最有用:

    1. my $ownersRef = $account{"owners"};
    2. my @owners = @{ $ownersRef };
    3. my $owner1Ref = $owners[0];
    4. my %owner1 = %{ $owner1Ref };
    5. my $owner2Ref = $owners[1];
    6. my %owner2 = %{ $owner2Ref };
    7. print "Account #", $account{"number"}, "\n";
    8. print "Opened on ", $account{"opened"}, "\n";
    9. print "Joint owners:\n";
    10. print "\t", $owner1{"name"}, " (born ", $owner1{"DOB"}, ")\n";
    11. print "\t", $owner2{"name"}, " (born ", $owner2{"DOB"}, ")\n";

    或者使用引用和->运算符:

    1. my $ownersRef = $account{"owners"};
    2. my $owner1Ref = $ownersRef->[0];
    3. my $owner2Ref = $ownersRef->[1];
    4. print "Account #", $account{"number"}, "\n";
    5. print "Opened on ", $account{"opened"}, "\n";
    6. print "Joint owners:\n";
    7. print "\t", $owner1Ref->{"name"}, " (born ", $owner1Ref->{"DOB"}, ")\n";
    8. print "\t", $owner2Ref->{"name"}, " (born ", $owner2Ref->{"DOB"}, ")\n";

    如果我们完全跳过那些中间值,代码看起来就是这样:

    1. print "Account #", $account{"number"}, "\n";
    2. print "Opened on ", $account{"opened"}, "\n";
    3. print "Joint owners:\n";
    4. print "\t", $account{"owners"}->[0]->{"name"}, " (born ", $account{"owners"}->[0]->{"DOB"}, ")\n";
    5. print "\t", $account{"owners"}->[1]->{"name"}, " (born ", $account{"owners"}->[1]->{"DOB"}, ")\n";

    如何用array的引用作茧自缚

    这个数组有5个元素:

    1. my @array1 = (1, 2, 3, 4, 5);
    2. print @array1; # "12345"

    然而这个array只有1个元素(一个含有5个元素的匿名array的引用):

    这个scalar是一个含有5个元素的匿名array的引用: