#!/usr/bin/perl
use Modern::Perl;
while (<>)
{ chomp;
say reverse;
}
The above code doesn't work but when I change 2nd last line to say scalar reverse;
then it works fine. Why do I need to force it to be a scalar explicitly? Can't Perl DWIM?
If I understand the documentation right, reverse
normally operates on lists. In a list context used without arguments, it returns an empty list and by default doesn't assign it anywhere. In your example, say outputs the unchanged $_
;
Forcing reverse
into scalar context changes its behaviour and makes it reverse character strings, and use $_
by default. Because say
can be used to print lists as well as scalars, it doesn't force its arguments into scalar context.
Perl probably does DWIM, just for given values of "I".
A breakdown of what reverse does when:
#!/usr/bin/env perl
use strict;
use v5.12;
my $inscalar = "foo bar";
# `reverse` is in list context, $in is coerced to a single-element list
my @outlist = reverse $inscalar;
# `reverse` is in scalar context, so it reverses strings
my $outscalar = reverse $inscalar;
say join(" | ", @outlist); # prints "foo bar"
say $outscalar; # prints "rab oof"
# the "normal" behaviour of `reverse`
my @inlist = qw(foo bar);
@outlist = reverse @inlist;
say join(" | ", @outlist); # prints "bar | foo"
Why do I need to force it to be a scalar explicitly?
As documented, reverse
reverses the order of the elements of the argument list when used in list context. For example, reverse 'a', 'b', 'c'
returns 'c', 'b', 'a'
.
Can't Perl DWIM?
Yes, it could do what you want (scalar behaviour when no argument expression is present).
It could be confusing, though. I can't think of any other operator that changes behaviour based on a lack of an argument expression (as opposed to just lack of arguments).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With