perl 中的数组是这样取消引用的,
my @array = @{$array_reference};
当尝试将数组分配给不带"@"的取消引用时,例如,
my @array = {$array_reference};
Perl 抛出错误,"匿名哈希中的元素数量为奇数,位于 ./sand.pl 行 22。我们不能将它分配给数组变量 becauase Perl 对类型感到困惑。
那么我们该如何执行...
my $lastindex = $#{$array_reference};
如果 Perl 难以理解 '{$array_reference}' 是一种数组类型?如果这看起来像这样,对我来说更有意义,
my $lastindex = $#@{$array_reference};
(尽管看起来丑陋得多)。
tl;dr:匹配$#array
的语法是$#{$array_reference}
。
{}
有很多含义,这就是Perl。
有时{}
会创建一个匿名哈希。这就是{$array_reference}
正在做的事情,试图制作一个哈希,其中键是$array_reference
的字符串化,类似于"ARRAY(0x7fb21e803280)"
,没有价值。因为您尝试创建具有键但没有值的哈希,所以您会收到"奇数个元素"警告。
有时{...}
是一个块,如sub { ... }
或if(...) { ... }
,或do {...}
等等。
有时它是一个像{ local $/; ... }
这样的光秃秃的块.
有时它表示哈希的键,如$hash{key}
或$hash->{key}
.
前面有某些符号{}
使取消引用变得明确。虽然你可以写$#$array_reference
或@$array_reference
但有时你想取消引用一些不是简单标量的东西。例如,如果你有一个返回数组引用的函数,你可以用$#{ get_array_reference() }
在一行中获取它的大小。匹配$#array
的语法是$#{$array_reference}
。
$#{...}
取消引用数组并获取索引。@{...}
取消引用数组。%{...}
取消引用哈希。${...}
取消引用标量。*{...}
取消引用一个球体。
你可能会发现 Modern Perl 中的变量名和符号部分有助于更好地了解模式。
如果这看起来像...
这样的事情很多。Perl 自 1987 年以来一直存在。很多这样的设计决策都是几十年前做出的。用于确定{}
含义的代码特别复杂。数组和数组引用之间存在区别有点奇怪。
$array[$index]
@array[@indexes]
@array
$#array
相当于
${ @array }[$index]
@{ @array }[@indexes]
@{ @array }
$#{ @array }
看到模式了吗?无论在何处使用数组的NAME
,都可以改用返回对数组的引用的BLOCK
。这意味着您可以使用
${ $ref }[$index]
@{ $ref }[@indexes]
@{ $ref }
$#{ $ref }
这在 Perl Dereferencing Syntax 中得到了说明。
请注意,如果BLOCK
只包含一个简单的标量,则可以省略卷曲。
$$ref[$index]
@$ref[@indexes]
@$ref
$#$ref
还有一个"箭头"语法被认为更清晰。
$ref->[$index]
$ref->@[@indexes]
$ref->@*
$ref->$#*
Perl 对类型感到困惑
Perl 很难理解 '{$array_reference}' 是一个数组类型
好吧,它不是数组类型。Perl 不会"挣扎";你只是有错误的期望。
一般规则(如perldoc perlreftut
中所述)是:您始终可以使用大括号中的引用来代替变量名。
因此:
@array # a whole array
@{ $array_ref } # same thing with a reference
$array[$i] # an array element
${ $array_ref }[$i] # same thing with a reference
$#array # last index of an array
$#{ $array_ref } # same thing with a reference
另一方面,这是怎么回事
my @array = {$array_reference};
是您正在使用哈希引用构造函数的语法,{ LIST }
.出现警告是因为相关列表应该具有偶数个元素(对于键和值):
my $hash_ref = {
key1 => 'value1',
key2 => 'value2',
};
您写的内容被视为
my @array = ({
$array_reference => undef,
});
即包含单个元素的数组,它是对包含单个键的哈希的引用,这是一个字符串化引用(其值为undef
)。
取消引用和哈希引用构造函数之间的语法区别在于,取消引用以符号(如$
、@
或%
)开头,而哈希引用构造函数仅以裸{
开头。
从技术上讲,取消引用语法中的{
}
形成了一个实际的代码块:
print ${
print "onen"; # yeah, I just put a statement in the middle of an expression
print "twon";
["three"] # the last expression in this block is implicitly returned
# (and dereferenced by the surrounding $ [0] construct outside)
}[0], "n";
出于(希望)显而易见的原因,没有人真正在实际代码中这样做。
语法是
my $lastindex = $#$array_reference;
它分配给$lastindex
匿名数组最后一个元素的索引,该元素引用在变量$array_reference
中。
代码
my @ary = { $ra }; # works but you get a warning
不会抛出"错误",而是发出警告。换句话说,您确实会得到一个元素的@ary
,即对匿名哈希的引用。但是,哈希需要具有偶数个元素,因此您还会收到警告,指出事实并非如此。
您最后一次尝试使用@{$array_reference}
取消引用数组 -- 这将返回一个列表,而不是数组变量。 "列表"是内存中稍纵即逝的标量集合(想想在堆栈上复制标量去其他地方);这样的事情没有"索引"的概念。因此,$#@{$ra}
甚至没有按预期解析,并且是语法错误。
语法$#ary
只适用于变量@ary
,然后是$#$arrayref
语法。您通常可以编写$#{$arrayref}
因为卷曲允许计算结果为数组引用的任意表达式,但没有理由这样做,因为您确实有一个带有数组引用的变量。
我很乐意同意,这种语法的大部分需要一些习惯,这样说。