Consider this Perl code
考虑一下这个Perl代码
my @a=[[1]];
print $a[0][0];
**output**
ARRAY(0x229e8)
Why does it print an ARRAY
instead of 1
? I would have expected @a
to create an array of size 1 with a reference to a second array containing only one element, 1
.
为什么打印ARRAY而不是1?我希望@a创建一个大小为1的数组,引用第二个只包含一个元素的数组1。
4 个解决方案
#1
14
This stuff is tricky. You have assigned @a
as a list containing a reference to an array that contains a reference to an array, which is one more extra level of indirection than you were expecting.
这个东西很棘手。您已将@a指定为包含对包含对数组的引用的数组的引用的列表,这是一个比您预期更多的间接层。
To get the results you expect, you should have said
为了得到你期望的结果,你应该说
@a = ( [ 1 ] );
#2
11
The value that you want is at $a[0][0][0]
. You're assigning an array reference as the first element of the @a
array.
您想要的值是$ a [0] [0] [0]。您将数组引用指定为@a数组的第一个元素。
This is a similar thing:
这是类似的事情:
my @a = 'scalar';
And that will create an array of 1 slot with the string 'scalar'
as the sole element. So when you assign a scalar to an array, Perl tries to do what it sounds like you want and create a list of size 1, with the scalar value as the first element.
这将创建一个1槽的数组,其中字符串'scalar'作为唯一元素。因此,当您为数组指定标量时,Perl会尝试执行您想要的操作并创建大小为1的列表,标量值为第一个元素。
Also,
my @a = undef;
does the same thing, but the first slot is undef
. What you want is
做同样的事情,但第一个插槽是undef。你想要的是什么
my @a = [1];
#3
4
Here is what I am guessing you wanted to write:
这是我猜你想写的:
my $x = [[1]]; # reference to anon array containing
# reference to anon array with one element
print $x->[0][0];
See also Perl Data Structures Cookbook.
另请参见Perl Data Structures Cookbook。
#4
3
mobrule, Axeman and Sinan have all answered your question: you created a data structure 3 layers deep, instead of 2.
mobrule,Axeman和Sinan都回答了你的问题:你创建了一个3层深度的数据结构,而不是2层。
I am surprised that no one suggested using the core Data::Dumper library to help understand data structure questions.
我很惊讶没有人建议使用核心Data :: Dumper库来帮助理解数据结构问题。
use Data::Dumper;
my @a = [[1]];
print Dumper \@a;
This prints:
$VAR1 = [ [ [ 1 ] ] ];
$ VAR1 = [[[1]]];
Your error was using the array reference constructor []
instead of just using parenthesis (or nothing). @a = ([1]);
您的错误是使用数组引用构造函数[]而不是仅使用括号(或没有)。 @a =([1]);
So, why does Perl have the weird []
and {}
syntax for declaring hash and array references?
那么,为什么Perl会使用奇怪的[]和{}语法来声明散列和数组引用?
It comes down to the fact that Perl flattens lists. This means that if you say: @a = (@b, @c);
that @a
is assigned the contents of @b
concatenated with the contents of @c
. This is is the same as Python's extend
list method. If you want @a
to have two elements, you need to force them not to expand. You do this by taking a reference to each array: @a = (\@b, \@c);
. This is like Python's append
list method.
它归结为Perl压缩列表的事实。这意味着如果你说:@a =(@ b,@ c); @a被赋予与@c内容连接的@b的内容。这与Python的扩展列表方法相同。如果你想让@a有两个元素,你需要强制它们不要扩展。您可以通过引用每个数组来执行此操作:@a =(\ @ b,\ @c);.这就像Python的追加列表方法。
When you want to create anonymous nested structures you need to have a way to mark them as hashes or arrays. That's where the syntax I mentioned above comes in.
当您想要创建匿名嵌套结构时,您需要有一种方法将它们标记为哈希或数组。这就是我上面提到的语法的用武之地。
But what good is list flattening? Why is it worth having this unusual syntax for making array and hash references, that is distinct from the syntax used for normal initialization?
但是列表扁平化有什么用呢?为什么值得使用这种不寻常的语法来进行数组和散列引用,这与用于正常初始化的语法有什么不同?
List flattening means that you can easily assemble a list of subroutine parameters in a variable and then pass them in without doing anything tricky: foo(@some_args, 5, @more_args);
. See Apply on wikipedia for info on how this concept works in other languages. You can do all sorts of other nice things with map
and other functions.
列表展平意味着您可以轻松地在变量中组合子例程参数列表,然后在不做任何棘手操作的情况下传递它们:foo(@some_args,5,@ more_args);.有关此概念如何在其他语言中工作的信息,请参阅*上的应用。你可以用地图和其他功能做各种其他好事。
#1
14
This stuff is tricky. You have assigned @a
as a list containing a reference to an array that contains a reference to an array, which is one more extra level of indirection than you were expecting.
这个东西很棘手。您已将@a指定为包含对包含对数组的引用的数组的引用的列表,这是一个比您预期更多的间接层。
To get the results you expect, you should have said
为了得到你期望的结果,你应该说
@a = ( [ 1 ] );
#2
11
The value that you want is at $a[0][0][0]
. You're assigning an array reference as the first element of the @a
array.
您想要的值是$ a [0] [0] [0]。您将数组引用指定为@a数组的第一个元素。
This is a similar thing:
这是类似的事情:
my @a = 'scalar';
And that will create an array of 1 slot with the string 'scalar'
as the sole element. So when you assign a scalar to an array, Perl tries to do what it sounds like you want and create a list of size 1, with the scalar value as the first element.
这将创建一个1槽的数组,其中字符串'scalar'作为唯一元素。因此,当您为数组指定标量时,Perl会尝试执行您想要的操作并创建大小为1的列表,标量值为第一个元素。
Also,
my @a = undef;
does the same thing, but the first slot is undef
. What you want is
做同样的事情,但第一个插槽是undef。你想要的是什么
my @a = [1];
#3
4
Here is what I am guessing you wanted to write:
这是我猜你想写的:
my $x = [[1]]; # reference to anon array containing
# reference to anon array with one element
print $x->[0][0];
See also Perl Data Structures Cookbook.
另请参见Perl Data Structures Cookbook。
#4
3
mobrule, Axeman and Sinan have all answered your question: you created a data structure 3 layers deep, instead of 2.
mobrule,Axeman和Sinan都回答了你的问题:你创建了一个3层深度的数据结构,而不是2层。
I am surprised that no one suggested using the core Data::Dumper library to help understand data structure questions.
我很惊讶没有人建议使用核心Data :: Dumper库来帮助理解数据结构问题。
use Data::Dumper;
my @a = [[1]];
print Dumper \@a;
This prints:
$VAR1 = [ [ [ 1 ] ] ];
$ VAR1 = [[[1]]];
Your error was using the array reference constructor []
instead of just using parenthesis (or nothing). @a = ([1]);
您的错误是使用数组引用构造函数[]而不是仅使用括号(或没有)。 @a =([1]);
So, why does Perl have the weird []
and {}
syntax for declaring hash and array references?
那么,为什么Perl会使用奇怪的[]和{}语法来声明散列和数组引用?
It comes down to the fact that Perl flattens lists. This means that if you say: @a = (@b, @c);
that @a
is assigned the contents of @b
concatenated with the contents of @c
. This is is the same as Python's extend
list method. If you want @a
to have two elements, you need to force them not to expand. You do this by taking a reference to each array: @a = (\@b, \@c);
. This is like Python's append
list method.
它归结为Perl压缩列表的事实。这意味着如果你说:@a =(@ b,@ c); @a被赋予与@c内容连接的@b的内容。这与Python的扩展列表方法相同。如果你想让@a有两个元素,你需要强制它们不要扩展。您可以通过引用每个数组来执行此操作:@a =(\ @ b,\ @c);.这就像Python的追加列表方法。
When you want to create anonymous nested structures you need to have a way to mark them as hashes or arrays. That's where the syntax I mentioned above comes in.
当您想要创建匿名嵌套结构时,您需要有一种方法将它们标记为哈希或数组。这就是我上面提到的语法的用武之地。
But what good is list flattening? Why is it worth having this unusual syntax for making array and hash references, that is distinct from the syntax used for normal initialization?
但是列表扁平化有什么用呢?为什么值得使用这种不寻常的语法来进行数组和散列引用,这与用于正常初始化的语法有什么不同?
List flattening means that you can easily assemble a list of subroutine parameters in a variable and then pass them in without doing anything tricky: foo(@some_args, 5, @more_args);
. See Apply on wikipedia for info on how this concept works in other languages. You can do all sorts of other nice things with map
and other functions.
列表展平意味着您可以轻松地在变量中组合子例程参数列表,然后在不做任何棘手操作的情况下传递它们:foo(@some_args,5,@ more_args);.有关此概念如何在其他语言中工作的信息,请参阅*上的应用。你可以用地图和其他功能做各种其他好事。