#!/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