http://www.perlmonks.org?node_id=1071774

jktstance has asked for the wisdom of the Perl Monks concerning the following question:

Hi all, I'm learning Perl (my only other programming experience is Tcl) and I'm having some trouble. I'm confused over lists, so I looked up some help and found this thread at Stack Overflow. I looked up the perldoc of reverse (reverse) and I on the page, there is some code, which I've slightly modified:
#!/usr/bin/perl use strict; use warnings; print join(", ", reverse "world", "One"), "\n"; # One, world print scalar reverse ("dlrow ,", "owT"),"\n"; # Two, world $_ = "dlrow ,eerhT"; print reverse; # No output, list context $_ = "dlrow ,ruoF"; print scalar reverse; # Four, world
I get the following output:
One, world Two, world Four, world
My first question is why isn't the third line printed? Reverse supposedly returns a list and the perldoc of print says that a list is one of it's arguments. Why doesn't this work? My second question is that if I explicitly state the $_ after reverse in the third print statement, then it prints out the string, but it is NOT reversed:
#!/usr/bin/perl use strict; use warnings; print join(", ", reverse "world", "One"), "\n"; # One, world print scalar reverse ("dlrow ,", "owT"),"\n"; # Two, world $_ = "dlrow ,eerhT"; print reverse $_; # No output, list context $_ = "dlrow ,ruoF"; print scalar reverse $_; # Four, world
I get the following output:
One, world Two, world dlrow, eerhTFour, world
What is going on here? Why does listing $_ explicitly as an argument to reverse cause print to work, but reverse() is not performed?

Replies are listed 'Best First'.
Re: New user, confusion over print and lists
by tobyink (Canon) on Jan 23, 2014 at 17:07 UTC

    From the documentation for reverse:

    Used without arguments in scalar context, reverse() reverses $_.

    That is, $_ is only "special" to reverse when:

    • reverse is called with no arguments; and
    • reverse is called in scalar context.

    In the case of print reverse;, it is not in scalar context, so $_ is not special. You're calling reverse with the empty list as an argument. It reverses that list and return the result (which is still the empty list).

    use Moops; class Cow :rw { has name => (default => 'Ermintrude') }; say Cow->new->name
Re: New user, confusion over print and lists
by choroba (Cardinal) on Jan 23, 2014 at 16:01 UTC
    When you specify $_ as an argument for reverse in list context, it is taken as the single member of the list to reverse. Equivalently, no arguments represent an empty list.
    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
      OK, I understand why the string is being printed back as is (1-length list). I'm still confused on why the behavior is different when I explicitly state $_ and when I do not.

      When reverse has no arguments, doesn't it just take $_? Is writing reverse; the same as reverse $_;? I'm imagining this to be the behavior, because print; and print $_; seem identical when I test them.

      EDIT: From the doc, I seems that reverse will ONLY work on $_ if it is in scalar context, which print is not. So I give it no arguments in list context, does reverse ignore $_, which the doc seems to imply it does. If so, is it just returning an empty list which is then passed to print?

Re: New user, confusion over print and lists
by LanX (Saint) on Jan 23, 2014 at 16:43 UTC
    This comment is wrong
    $_ = "dlrow ,eerhT"; print reverse $_; # No output, list context

    you get the one-element list ($_) reversed, which is the same list. Harder to spot since you forgot the newline this time.

    reverse does exactly like documented and explained by choroba

    • In list context, returns a list value consisting of the elements of LIST in the opposite order.

    • In scalar context, concatenates the elements of LIST and returns a string value with all characters in the opposite order.

    I think you are misunderstanding how context works, it's the LHS which decides how the RHS of reverse is interpreted and print always induces list context.

    Cheers Rolf

    ( addicted to the Perl Programming Language)