为什么在这个 Perl 示例中 print 之后的第一个左括号之前有一个 +? [英] Why is there a + before the first left parenthesis following print in this Perl example?

查看:51
本文介绍了为什么在这个 Perl 示例中 print 之后的第一个左括号之前有一个 +?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近我遇到了这样的声明

print +( map { $_ + 1 } @$_ ),@$array 为\n";# <- 迎角

我以前从未见过像这样与 print 一起使用的 + 运算符.运行语句,不难推断出它在做什么.但是我无法找到有关以这种方式使用的 + 运算符的文档.

我的@tab = ([1,2,3,4],[qw(a b c d)],);my $test = "(", +( map { qq( >>$_<< ) } @$_ ), ")\n" for @tab;打印 $test;我的@test = "(", +( map { qq( >>$_<< ) } @$_ ), ")\n" for @tab;打印@test;my %test = "(", +( map { qq( >>$_<< ) } @$_ ), ")\n" for @tab;打印 %test;

以上产生警告:Useless use of a constant ()) in void context 对于所有三个测试.使用未初始化的值用于scalar测试和哈希赋值中元素的奇数对于arrayhash 测试,能够将语句输出存储在 scalar 中会很好.我知道我可以使用如下所示的 for 循环将相同的字符串存储在 scalar 中.

print "(", +( map { qq( >>$_<< ) } @$_ ), ")\n" for @tab;我的 $out = '';对于(@tab){$out .= "(" . ( join '', map { qq( >>$_<< ) } @$_ ) . ")\n";}打印 $out;# 输出 ...(>>1<>>2<<>>3<<>>4<<)(>>a<<>>b<<>>c<<>>d<)---(>>1<>>2<<>>3<<>>4<)(>>a<<>>b<<>>c<<>>d<)

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

<块引用>

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

使用严格;使用警告;我的@a = ([1,2,3],[qw/a b c/]);我的 $one = '';$one .= "(" . ( join '', map { " >>$_<< " } @$_ ) . ")\n" for @a;打印 $1;# 输出 ...(>>1<>>2<<>>3<<)(>>a<<>>b<<>>c<<)

解决方案

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

<块引用>

一元+"没有任何影响,即使对字符串也是如此.它在语法上非常有用,可用于将函数名称与括号表达式分开,否则该表达式将被解释为函数参数的完整列表.

为了扩展打印语句中到底发生了什么,我在 perlmaven<上找到了解释/a> 相当不错.

<块引用>

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

这可能会让你满意,但如果你更感兴趣,你可以使用 B::Deparse 模块询问 perl 它是如何理解这段代码片段的:

print +(stat $filename)[7];

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

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

希望对您有所帮助!

编辑

详细解释为什么不能使用相同的命令打印该序列并将其分配给标量可能超出了本问题的范围,但我将尝试简要解释...如果我对某事有错误,我希望得到更正,我已经通过使用它编写代码而不是通过阅读有关其内部工作原理的 perl 文档来了解这是如何工作的:)用打印语句

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

perl 将其解释为

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

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

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

perl 在 ")\n" 上执行 for @tab 代码,因此您的 在无效上下文中无用使用常量 ()) 警告.为了做你想做的事,你需要明确what你想要for'd

我的 $test;( $test .= "(" . join ('', ( map { qq( >>$_<< ) } @$_)) . ")\n") 为@tab;打印 $test;

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

Recently I came across a statement like this

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

I had not seen the + operator used with print like this before. Running the statement, it is not hard to infer what it is doing. But I am having trouble finding documentation on the + operator used this way.

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;

Above produces the warnings: Useless use of a constant ()) in void context for all three tests. Use of uninitialized value for the scalar test and Odd number of elements in hash assignment for both the array and hash tests, It would be nice to be able to store the statements output in a scalar. I know I can store an Identical string in a scalar using a for loop like below.

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<< )

Why can't I store the statement in any variable or test its type. Id like in detail what is actually happening with the print builtin when using the + operator.

EDIT: I belive my original post was kind of confusing, I did want to learn more about the + operator used with print but what I was really after is how to store each iteration of the shorthand for statement into a scalar string - I found a way after some testing ...

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<< )

解决方案

I think you've asked two questions here, so I'll answer both of them as well as I can... Firstly, you're referring to the unary "+" operator, from perlop

Unary "+" has no effect whatsoever, even on strings. It is useful syntactically for separating a function name from a parenthesized expression that would otherwise be interpreted as the complete list of function arguments.

To expand on what exactly is going on in the print statement, I found the explanation on perlmaven to be pretty good.

The documentation explains that the + separates the print function from the parentheses ( and tells perl that these are not the parentheses wrapping the parameters of the print function.

That might satisfy you, but if you are further intersted you can use the B::Deparse module to ask perl how does it understand this code-snippet:

print +(stat $filename)[7];

We save that content in the plus.pl file and run perl -MO=Deparse plus.pl. The result is:

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

Hope this is helpful!

Edit

Explaining in detail why you can't use the same command to print that sequence and assign it to a scalar is maybe outside of the scope of this question, but I'll attempt to briefly explain... with the note that if I'm wrong about something, I'd love a correction, I've come to understand how this works through writing code using this, not from reading the perl docs on its inner workings :) With the print statement

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

perl is interpreting it as

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

That is, it's grouping all of the stuff you want to print, and performing it for each element in @tab. However, with your scalar assignment

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

perl is performing the for @tab code on ")\n", thus your Useless use of a constant ()) in void context warning. To do what you want, you need to make it explicit what you want for'd

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

Should get you what you're looking for. Note the parenthesis around the entire assignment, and the omission of the unary "+" before the map, which is no longer necessary.

这篇关于为什么在这个 Perl 示例中 print 之后的第一个左括号之前有一个 +?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆