像这样取消对perl中的数组的引用,
my @array = @{$array_reference};
当尝试将数组分配给不带'@'的取消引用时,例如
my @array = {$array_reference};
Perl引发错误,“ ./ sand.pl第22行的匿名哈希中的元素奇数”。我们不能将其分配给数组变量,因为Perl对类型感到困惑。
那我们该如何执行...
my $lastindex = $#{$array_reference};
如果Perl难以理解'{$ array_reference}'是数组类型吗?如果看起来像这样,对我来说更有意义
my $lastindex = $#@{$array_reference};
(尽管看起来丑陋得多)。
答案 0 :(得分:6)
tl; dr:与$#{$array_reference}
的语法匹配的$#array
。
{}
重载了很多含义,而这正是Perl的方式。
有时{}
创建一个匿名哈希。这就是{$array_reference}
的工作,试图做一个哈希,其中键是$array_reference
的字符串化,类似"ARRAY(0x7fb21e803280)"
,没有任何价值。因为您尝试使用键名和无值创建哈希,所以会收到“奇数个元素”警告。
有时{...}
是一个像sub { ... }
或if(...) { ... }
或do {...}
之类的块。
有时候,它像{ local $/; ... }
这样的裸露块。
有时它指示诸如$hash{key}
或$hash->{key}
之类的哈希键。
在某些信号前加{}
使取消引用成为显式的。尽管您可以编写$#$array_reference
或@$array_reference
,但有时您还是想取消对非简单标量的引用。例如,如果您有一个返回数组引用的函数,则可以用$#{ get_array_reference() }
将其大小写成一行。匹配$#{$array_reference}
的语法是$#array
。
$#{...}
取消引用数组并获取索引。 @{...}
取消引用数组。 %{...}
取消引用哈希。 ${...}
取消引用标量。 *{...}
取消引用全局。
您可能会发现the section on Variable Names and Sigils in Modern Perl有助于更好地查看模式。
如果这看起来对我来说更有意义...
有很多类似的事情。 Perl自1987年以来一直存在。许多设计决策是几十年前做出的。确定{}
含义的代码特别复杂。数组与数组引用之间根本没有区别。
答案 1 :(得分:5)
$array[$index]
@array[@indexes]
@array
$#array
等同于
${ \@array }[$index]
@{ \@array }[@indexes]
@{ \@array }
$#{ \@array }
看到图案了吗?无论在何处使用数组的NAME
,都可以使用BLOCK
来返回对数组的引用。这意味着您可以使用
${ $ref }[$index]
@{ $ref }[@indexes]
@{ $ref }
$#{ $ref }
Perl Dereferencing Syntax中对此进行了说明。
请注意,如果BLOCK
仅包含一个简单的标量,则可以省略掉curly。
$$ref[$index]
@$ref[@indexes]
@$ref
$#$ref
还有一种“箭头”语法,被认为更清晰。
$ref->[$index]
$ref->@[@indexes]
$ref->@*
$ref->$#*
答案 2 :(得分:3)
Perl对类型感到困惑
Perl难以理解'{$ array_reference}'是数组类型
嗯,这不是数组类型。 Perl不会“挣扎”。你只是有错误的期望。
general rule(如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
)。
取消引用和hashref构造函数之间的语法差异是,取消引用以符号(例如$
,@
或%
开头),而hashref构造函数仅以sigil开头裸露的{
。
从技术上讲,解除引用语法中的{
}
构成了实际的代码块:
print ${
print "one\n"; # yeah, I just put a statement in the middle of an expression
print "two\n";
["three"] # the last expression in this block is implicitly returned
# (and dereferenced by the surrounding $ [0] construct outside)
}[0], "\n";
出于(希望)明显的原因,实际上没有人在真实代码中这样做。
答案 3 :(得分:2)
语法是
my $lastindex = $#$array_reference;
,它为变量$lastindex
中引用的匿名数组的最后一个元素的索引分配给$array_reference
。
代码
my @ary = { $ra }; # works but you get a warning
不会抛出“错误”,而是发出警告。换句话说,您确实获得@ary
一个元素,即对匿名哈希的引用。但是,哈希需要包含偶数个元素,因此您还会收到警告,提示并非如此。
您最后一次尝试用@{$array_reference}
取消引用数组-返回一个 list ,而不是一个数组 variable 。 “列表”是内存中短暂的标量集合(请考虑将标量复制到堆栈上以移至其他位置);对于这样的事情,没有“索引”的概念。因此,$#@{$ra}
甚至没有按预期进行解析,并且是语法错误。
语法$#ary
仅适用于变量 @ary
,然后是$#$arrayref
语法。通常,您可以写$#{$arrayref}
,因为curls允许使用任意表达式来求值数组引用,但是没有理由这样做,因为您确实有一个带有数组引用的变量。
我很容易同意,这种语法中的许多需要花些时间才能使用。