正如我之前在其他地方写的……
一元 \ 创建一个对其后面的任何内容的引用。在列表上使用时,它会创建一个引用列表。
不要将此行为与字符串中的反斜杠行为混淆,尽管这两种形式都传达了一种含糊否定的概念,即保护下一个事物不被解释。这种相似之处并非完全偶然。
您可以使用反斜杠创建对任何命名变量或子例程的引用。您也可以在匿名标量值上使用它,例如 7 或 "camel",尽管您通常不需要这样做。该运算符的工作方式类似于 C 或 C⁺⁺ 中的 &(地址)运算符—— 至少乍一看。
这里有一些例子:
$scalarref = \$foo;
$constref = \186_282.42;
$arrayref = \@ARGV;
$hashref = \%ENV;
$coderef = \&handler;
$globref = \*STDOUT;
反斜杠运算符不仅可以生成单个引用。如果应用于列表,它将生成完整的引用列表。
如前所述,反斜杠运算符通常用于单个引用以生成单个引用,但并非必须如此。当用于引用列表时,它会生成相应引用列表。以下示例的第二行与第一行执行相同的操作,因为反斜杠会自动分布在整个列表中。
@reflist = (\$s, \@a, \%h, \&f); # List of four references
@reflist = \($s, @a %h, &f); # Same thing
如果一个带括号的列表只包含一个数组或哈希,那么它的所有值都会被插值并返回对每个值的引用:
@reflist = \(@x); # Interpolate array, then get refs
@reflist = map { \$_ } @x; # Same thing
当有内括号时也会发生这种情况:
@reflist = \(@x, (@y)); # But only single aggregates expand
@reflist = (\@x, map { \$_ } @y); # Same thing
如果您尝试使用哈希,结果将包含对值的引用(如您所料),但对键的 副本 的引用(您可能不 期待)。
因为数组和哈希切片实际上只是列表,所以您可以对其中任何一个切片进行反斜杠以获得引用列表。接下来的四行中的每一行都做同样的事情:
@envrefs = \@ENV{"HOME", "TERM"}; # Backslashing a slice
@envrefs = \@ENV{ qw<HOME TERM> }; # Backslashing a slice
@envrefs = \( $ENV{HOME}, $ENV{TERM} ); # Backslashing a list
@envrefs = ( \$ENV{HOME}, \$ENV{TERM} ); # A list of two references
由于函数可以返回列表,因此您可以对它们应用反斜杠。如果你有多个函数要调用,首先将每个函数的返回值插入一个更大的列表,然后反斜杠整个事情:
@reflist = \fx();
@reflist = map { \$_ } fx(); # Same thing
@reflist = \( fx(), fy(), fz() );
@reflist = ( \fx(), \fy(), \fz() ); # Same thing
@reflist = map { \$_ } fx(), fy(), fz(); # Same thing
反斜杠运算符始终为其操作数提供列表上下文,因此这些函数都在列表上下文中调用。如果反斜杠本身在标量上下文中,您最终将引用函数返回的列表的最后一个值:
@reflist = \localtime(); # Ref to each of nine time elements
$lastref = \localtime(); # Ref to whether it’s daylight savings time
在这方面,反斜杠的行为类似于命名的 Perl 列表
运算符,例如 print、reverse 和 sort,它们总是
无论他们的左边可能发生什么,在他们的右边提供一个列表上下文。与命名列表运算符一样,使用显式 scalar 将以下内容强制转换为标量上下文:
$dateref = \scalar localtime(); # \"Sat Nov 13 10:41:30 2010"
现在你知道了……故事的其余部分。
(向已故的保罗·哈维道歉)