为什么在Perl示例中打印后的第一个左括号之前有一个+?

Bry*_*anK 4 perl

最近我遇到了这样的声明

print +( map { $_ + 1 } @$_ ), "\n" for @$array; # <- AoA
Run Code Online (Sandbox Code Playgroud)

我之前没有看过+像这样的打印机使用过的操作符.运行该语句,不难推断出它在做什么.但我很难找到+使用这种方式的操作员的文档.

my @tab = (
[1,2,3,4],
[qw(a b c d)],
);

my $test = "(", +( map { qq( >>$_<< ) } @$_ ), ")\n" for @tab;
print $test;
my @test = "(", +( map { qq( >>$_<< ) } @$_ ), ")\n" for @tab;
print @test;
my %test = "(", +( map { qq( >>$_<< ) } @$_ ), ")\n" for @tab;
print %test;
Run Code Online (Sandbox Code Playgroud)

以上产生警告:Useless use of a constant ()) in void context对于所有三个测试.Use of uninitialized value对于scalar测试和Odd number of elements in hash assignment两个arrayhash测试,能够将语句输出存储在一个中是很好的scalar.我知道我可以scalar使用如下所示的for循环存储一个相同的字符串.

print "(", +( map { qq( >>$_<< ) } @$_ ), ")\n" for @tab;

my $out = '';
for (@tab) {
    $out .= "(" . ( join '', map { qq( >>$_<< ) } @$_ ) . ")\n";
}   
print $out;

# output ...
( >>1<<  >>2<<  >>3<<  >>4<< )
( >>a<<  >>b<<  >>c<<  >>d<< )
---
( >>1<<  >>2<<  >>3<<  >>4<< )
( >>a<<  >>b<<  >>c<<  >>d<< )
Run Code Online (Sandbox Code Playgroud)

为什么我不能将语句存储在任何变量中或测试它type.我详细了解print使用+运算符时内置函数实际发生了什么.

编辑:我相信我的原始帖子有点令人困惑,我确实想了解更多关于+运算符使用print但我真正想知道的是如何将速记for语句的每个迭代存储到标量字符串中 - 我找到了一些方法测试......

use strict;
use warnings;
my @a = ([1,2,3],[qw/a b c/]);
my $one = '';
$one .= "(" . ( join '', map { " >>$_<< " } @$_ ) . ")\n" for @a;
print $one;

# output ...
( >>1<<  >>2<<  >>3<< )
( >>a<<  >>b<<  >>c<< )
Run Code Online (Sandbox Code Playgroud)

Zip*_*ers 5

我想你在这里问了两个问题,所以我会尽可能地回答这两个问题......首先,你指的是来自perlop的一元"+"运算符

一元"+"无论如何都没有任何效果,即使是在字符串上也是如此.在语法上有用的是将一个函数名与一个带括号的表达式分开,否则它将被解释为函数参数的完整列表.

为了扩展print语句的确切内容,我发现perlmaven的解释非常好.

文档解释了+将打印函数与括号分开(并告诉perl这些不是包装打印函数参数的括号.

这可能会让你满意,但是如果你还有其他问题,可以使用B :: Deparse模块询问perl它是如何理解这段代码片段的:

print +(stat $filename)[7];

我们将该内容保存在plus.pl文件中并运行perl -MO = Deparse plus.pl. 结果是:

print((stat $filename)[7]);

希望这有用!

编辑

详细解释为什么你不能使用相同的命令来打印那个序列并将它分配给标量可能超出了这个问题的范围,但我会试着简单解释一下...如果我'我错了什么,我喜欢纠正,我已经通过使用这个编写代码来理解这是如何工作的,而不是通过阅读其内部工作的perl文档:)使用print语句

print "(", +( map { qq( >>$_<< ) } @$_ ), ")\n" for @tab;

perl将其解释为

(print "(", +( map { qq( >>$_<< ) } @$_ ), ")\n") for @tab;

也就是说,它将您要打印的所有内容分组,并为@tab中的每个元素执行它.但是,使用标量赋值

my $test = "(", +( map { qq( >>$_<< ) } @$_ ), ")\n" for @tab;

perl正在for @tab")\n" 执行代码,因此你的Useless use of a constant ()) in void context警告.要做你想做的事,你需要明确你想要的东西for

my $test; ( $test .= "(" . join ('', ( map { qq( >>$_<< ) } @$_)) . ")\n") for @tab; print $test;

应该得到你想要的东西.注意整个赋值周围的括号,以及在映射之前省略一元"+",这是不再需要的.