我是Perl的新手,无法找到满意的答案
my @foo = ("foo","bar")
print "@foo[0]"
foo
print "$foo[1]"
bar
不仅@foo[0]
可以正常工作,而且$foo[1]
也可以输出字符串。
为什么?即使启用了use strict
。
答案 0 :(得分:7)
@foo[0]
和$foo[1]
都是合法的Perl构造。
$foo[$n]
,或更常见的是$foo[EXPR]
是一个标量元素,代表数组$n
的第@foo
个元素(索引从0开始)(或任何EXPR
得出的结果)。
@foo[LIST]
是一个数组切片,@foo
中的元素集由LIST
中的索引指示。当LIST
具有一个元素,例如@foo[0]
时,则@foo[LIST]
是具有一个元素的列表。
尽管@foo[1]
是一个有效的表达方式,但经验表明,通常更不恰当地使用构造,而更适合说$foo[1]
。因此,在启用警告并使用该构造时会发出警告-而不是错误。
$foo[LIST]
在Perl中也是有效的表达式。只是Perl会在标量上下文中评估LIST
并返回与该评估相对应的@foo
元素,而不是元素列表。
@foo = ("foo","bar","baz");
$foo[0] returns the scalar "foo"
@foo[1] returns the list ("bar") (and issues warning)
@foo[0,2] returns the list ("foo","baz")
$foo[0,2] returns "baz" ($foo[0,2] evaluates to $foo[2], and issues warning)
$foo[@foo] returns undef (evaluates to $foo[scalar @foo] => $foo[3])
转移:我想出的使用@foo[SCALAR]
的唯一原因是作为左值,可以区分标量/列表上下文。考虑
sub bar { wantarray ? (42,19) : 101 }
$foo[0] = bar();
会将值101
分配给@foo
的第一个元素,但是@foo[0] = bar()
会分配值42
。但是,除非您打高尔夫球,否则即使您说($foo[0]) = bar()
也无法做到这一点。
答案 1 :(得分:7)
Perl信号告诉您如何处理数据,并且仅与变量类型松散相关。不用考虑是什么,而是考虑它正在做什么。这是Perl中名词的动词:
$
使用单个项目@
使用多个项目%
使用对标量变量$foo
是单个项目,并使用$
符号。由于没有单个项目的倍数或成对,因此其他信号不再起作用。
数组变量@foo
可能包含许多项目,@
一起引用了所有这些项目。 $foo[INDEX]
引用数组中的单个项目,并使用$
标记。您可以使用数组切片引用多个项目,例如@foo[INDEX,INDEX2,...]
,并为此使用@
。您的问题集中在一个元素@foo[INDEX]
的切片的简并情况下。可以,但是在列表上下文中。有时,行为会有所不同。
哈希变量%foo
是键值对的集合。要获取单个值,请再次使用$
,例如$foo{KEY}
。您还可以使用@
通过散列切片获得多个值,因为它是多个值,例如@hash{KEY1,KEY2,...}
。
而且,这是最近的发展:Perl 5.20 introduces “Key/Value Slices”。您可以获取数组或哈希的哈希切片。 %array[INDEX1,INDEX2]
或%hash{KEY1,KEY2}
。这些返回键值对列表。在数组的情况下,键是索引。
对于具有单个元素访问权限或切片类型的数组和哈希,您可以通过索引字符来了解变量类型:数组使用[]
,而哈希使用{}
。而且,还有另一个有趣的问题:这些分隔符根据单个或(可能)多个项目提供标量或列表上下文。
答案 2 :(得分:2)
@foo[0]
和$foo[1]
都是合法的Perl构造。
$foo[EXPR]
(其中EXPR
是在标量上下文中求值的任意表达式)返回由表达式结果指定的单个元素。
@foo[LIST]
(其中LIST
是在列表上下文中求值的任意表达式)返回表达式结果指定的每个元素。
(与其他文章相反,Perl中没有$foo[LIST]
这样的东西。使用$foo[...]
时,表达式总是在标量上下文中求值。)
尽管@foo[1]
是一个有效的表达方式,但经验表明,通常更不恰当地使用构造,而更适合说$foo[1]
。因此,当启用警告并使用该构造时,会发出警告(而不是例外)。
这意味着什么:
my @foo = ( "foo", "bar", "baz" );
$foo[0] 0 eval'ed in scalar cx. Returns scalar "foo". ok
@foo[1] 1 eval'ed in list cx. Returns scalar "bar". Weird. Warns.
@foo[0,2] 0,2 eval'ed in list cx. Returns scalars "foo" and "baz". ok
$foo[0,2] 0,2 eval'ed in scalar cx. Returns scalar "baz". Wrong. Warns.
$foo[@foo] @foo eval'ed in scalar cx. Returns undef. Probably wrong.
我想使用@foo[SCALAR]
的唯一原因是作为区分标量/列表上下文的某个地方的左值。考虑
sub bar { wantarray ? (42,19) : 101 }
$foo[0] = bar();
会将值101
分配给@foo
的第一个元素,但是@foo[0] = bar();
会分配值42
。改为使用($foo[0]) = bar()
更为常见。
mob版权所有的部分帖子,与本网站相同。
这篇文章解决了暴民post中的许多问题,包括1)滥用LIST
意味着在列表上下文中使用任意表达式以外的东西; 2)假装parens创建列表,3)假装返回标量和返回列表之间存在差异,并且4)假装没有非致命错误之类的东西。