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 withfor
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<< )
perldoc -f print:
In this case, you do not want
map
to consume the"\n"
, you must put parentheses around themap { $_ + 1 } @$_
. But, the moment you do that you run into the situation described above unless you put a+
before the left parenthesis so that+(map { $_ + 1 } @$_)
becomes a single argument to print instead of(map { $_ + 1 } @$_)
being interpreted as the complete argument list.If you had
the comma following the right parenthesis above would be interpreted as the comma operator.
print
would just print the numbers, and not the newline:The
print
is evaluated. As a side effect, it prints the numbers. The return value of theprint
is discarded, and the value of the expression becomes"\n"
. Since this value is not assigned to anything, you get the warning. Basically, the code ends up looking like:except for the side effect of invoking
print
.If you want to store the output of the loop in a variable, you can do:
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
To expand on what exactly is going on in the print statement, I found the explanation on perlmaven to be pretty good.
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 yourUseless use of a constant ()) in void context
warning. To do what you want, you need to make it explicit what you wantfor
'dmy $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.