范围运算符的Perl上下文是什么?

Rab*_*der 9 perl

我是一个Perl新手.我想结合范围运算符来理解Perl上下文.这是我的代码.

use strict;
use warnings;

my $asc = ( 10 .. 50 );
print "$asc\n";
Run Code Online (Sandbox Code Playgroud)

我有两个疑问.

  1. 如果表达式(10 ... 50)返回一个数组,那么,因为它是一个标量上下文,所以应该为"asc"变量赋予数组的长度,即41.

  2. 如果expression(10 ..50)返回一个列表,那么,因为它是一个标量上下文,所以应该为"asc"变量分配列表中的最后一项,即50.

但是,我得到以下的呼喊..

Use of uninitialized value in range (or flip) at main.pl line ..
Run Code Online (Sandbox Code Playgroud)

感谢并欢迎任何指南.

Mil*_*ler 9

您正在使用标量上下文中的Range运算符..,也称为触发器运算符.

您应该阅读整个文档,但以下摘录与您的情况相关:

在标量上下文中," .."返回一个布尔值.运算符是双稳态的,就像一个触发器,并模拟sed,awk和各种编辑器的行范围(逗号)运算符.

...

如果标量" .."的任一操作数是常量表达式,则如果该操作数==与当前输入行号($.变量)相等(),则该操作数被视为true .

"确切"错误消息解释了正在发生的事情:

Use of uninitialized value $. in range (or flip)
Run Code Online (Sandbox Code Playgroud)

基本上,Perl将此用法解释为翻转/翻转测试.

它正在测试当前行号$.是否等于您指定的整数值:

my $asc = ( $. == 10 .. $. == 50 );
Run Code Online (Sandbox Code Playgroud)

但是,因为您还没有从文件句柄中读取,所以该$.变量未初始化并抛出警告.

实现列表上下文

可以获取您描述的列表上下文行为,但您需要调整代码以使您的意图更明确:

my $count = () = (10..50);          # Forces a list context
my $last_element = (10..50)[-1];    # Also forces a list context

print "$count\n";
print "$last_element\n";
Run Code Online (Sandbox Code Playgroud)

输出:

41
50
Run Code Online (Sandbox Code Playgroud)


ike*_*ami 6

如果表达式(10 .. 50)返回一个数组,那么,因为它是一个标量上下文,...

如果表达式(10..50)返回一个列表,那么,因为它是一个标量上下文,...

你正在对一些非常不正确的错误观念进行操作.

  • 返回一个数组是不可能的[1].唯一可以返回的是零个或多个标量.在标量上下文中,该列表必须恰好是一个标量长.

  • 标量上下文会导致运算符更改它返回的内容; 它不会导致返回的值被强制转换为标量.

每个操作员决定在每个上下文中返回什么.有些像范围operator(..),甚至根据上下文改变行为.实际上,范围运算符在标量上下文中的行为与其在列表上下文中的行为明显不同.所以,当它在标量上下文中时,通常用不同的名称来调用它:触发器操作符.

这个问题并不是关于触发器操作符的,所以我不打算详细介绍.(它的文档在这里.)我只想说它可以用很少的代码按编号选择性地打印行.

例如,

while (<DATA>) {
   print if 2..3;
}

__DATA__
aaa
bbb
ccc
ddd
eee
Run Code Online (Sandbox Code Playgroud)

输出

bbb
ccc
Run Code Online (Sandbox Code Playgroud)

"魔术"的一部分涉及比较提供$.的数字,最后一行读取的行号.这意味着

my $ac = 10..50;
Run Code Online (Sandbox Code Playgroud)

是的缩写

my $ac = ($. == 10) .. ($. == 50);
Run Code Online (Sandbox Code Playgroud)

由于您从未从文件中读取,$.因此未定义.


  1. 执行此操作时return @array;,您可以$array[0], $array[1], ...根据上下文返回array()的元素或其长度.