怎么能 #?可以在不首先使用@的情况下在已解引用的数组上使用?

时间:2018-10-10 22:48:34

标签: perl reference

像这样取消对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};

(尽管看起来丑陋得多)。

4 个答案:

答案 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允许使用任意表达式来求值数组引用,但是没有理由这样做,因为您确实有一个带有数组引用的变量。

我很容易同意,这种语法中的许多需要花些时间才能使用。