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

In a quest for knowledge, I decided to run back through the Llama and do every exercise, this time using strict and -w. While the use of strict and -w isn't the problem, I encountered a "funny thing" when I was trying to tweak my script for Chapter 3, Exercise 1 (P. 57)

Here's my code as I first wrote it:

use strict; my @list = qw (first second third fourth fifth sixth + seventh eigth ninth tenth); print (reverse (@list));

...and this presents the answer:

TENTHNINTHEIGTHSEVENTH...

Okay, this meets the "intent" of the lesson, but I wanted it tweaked so that there would be a space in between each element of the displayed list. While it didn't feel "right" to me, I simply changed the code to:

use strict; my @list = qw (first second third fourth fifth sixth + seventh eigth ninth tenth); print (reverse (@list) . " ");

This got me a totally unexpected:

HTNETHTNINHTGIEHTNEVES...

Wow! Not my expectation at all! So, this leads to:

  1. Why did this not only change it from reversing the list, but reversing the word itself?
  2. How would I have accomplished my original goal most eloquently, to add a simple space between words?

Thanks, everyone. And if this was posted to the wrong area, please let me know. A swift slap to the head usually gets my attention.

-- Just another Perl slacker
Steampunk.

Replies are listed 'Best First'.
(kudra: printing reverse list answer) Re: A simple
by kudra (Vicar) on Oct 04, 2000 at 16:31 UTC
    1. I'm not sure about this, but perhaps you're putting it in scalar context. From PP: "In scalar context, the function concatenates all the elements of LIST together and then returns the reverse of that, character by character."

    2. One way to do this would be with join:

    print join " ",(reverse @list);
    Or you could modify the (local) output field separator:
    # In real use you'd probably want this in a block local $, = ' '; print (reverse @list);
Re: A simple
by kilinrax (Deacon) on Oct 04, 2000 at 16:35 UTC
    1. Concatenating the list with " " causes it to evaluate in a scalar context. In a scalar context, reverse returns the reverse of the concatenation of all elements of the list. The space will be concatenated to the end of that.

    2. The following code should do what you want to do:
      #!/usr/bin/perl - w use strict; my @list = qw (first second third fourth fifth sixth + seventh eigth ninth tenth); print join ' ', reverse (@list);
      And here's another way:
      #!/usr/bin/perl - w use strict; my @list = qw (first second third fourth fifth sixth + seventh eigth ninth tenth); my @reverse = reverse (@list); print "@reverse";
Re: A simple
by swiftone (Curate) on Oct 04, 2000 at 18:14 UTC
    1.Why did this not only change it from reversing the list, but reversing the word itself?

    Others have answered both your questions well, but I'm going to be a bit more verbose on this one (I recently did a bunch of messing around with reverse, so it's fresh in my mind)

    reverse works on a list, and returns either a list or a scalar, depending on context. Your original (Camel) code: print (reverse (@list)); It's in a list context (checking perldoc -f print we see that print operates on a list, so that's what context you're in). (Note also that the outer ()'s are syntactic sugar, they have NOTHING to do with putting this into list context, print reverse @list works the same. See a thread where merlyn gives the quick explanation here.)

    Now your modified version: print (reverse (@list) . " ") concatenates the results of reverse with a string, meaning that the reverse is used in a scalar context.

    With me so far? Okay, now there are times when you WANT this kind of behavior. For example, when learning how to commify a number, you can't just say print reverse "10000000"; Because you'll get just "10000000" as output. (I.e. the reverse order of a list of one element). To see what it really looks like reversed, try print scalar reverse "10000000"; Of course, if you assign the result to a scalar variable rather than simply printing the result, it will be taken in a scalar context without the scalar.

    reverse is an easily underestimated function. Many regexes and the like are much easier to do on the reverse of a string rather than the string itself.

Re: A simple
by clemburg (Curate) on Oct 04, 2000 at 16:37 UTC

    1. From the Perl docs:
      # perldoc -f reverse =item reverse LIST 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.
    2. Just try this: print "@list";

    Christian Lemburg
    Brainbench MVP for Perl
    http://www.brainbench.com/

        This code:

        #!/usr/bin/perl -w use strict; my @list = qw (first second third fourth fifth sixth seventh eigth ninth tenth); print "@list";

        Does the following on my machine:

        Mi 04.10.2000 15:41:50,56 D:\tmp >perl try.pl first second third fourth fifth sixth seventh eigth ninth tenth Mi 04.10.2000 15:43:47,85 D:\tmp >
        Christian Lemburg
        Brainbench MVP for Perl
        http://www.brainbench.com
Thanks!
by Steampunk (Scribe) on Oct 04, 2000 at 20:25 UTC
    First off, thanks everyone for the good explanations. I'll read up more on the join function. And also in what situations I'm forcing a list into a scalar context.

    Second, the title was meant to say, 'A simple, "why?"' but the HTML overlooked the quotes when rendered. Oops -- is there an HTMLmonks.org? Haha...

    Lastly, two more questions!

    1. Why then, don't I see a space on the print out with my second version? My guess is that it is there - albeit at the end and therefor not seen?
    2. Why did my second version reverse the element, i.e. THIRD => DRIHT, and also reverse the list? Almost as if I used two reverse statements; first one in a scalar context, then a second on the list itself.

    Again, thanks everyone for the help.

    -- Just another Perl slacker
    Steampunk.

      In answer to number 1, the space is still there. You can easily confirm your theory by adding a line like:
      print "-\n";
      after you print the list. The space should be quite obvious then.

      As for your second question, remember: "concatenates all the elements of LIST together and then returns the reverse of that, character by character." So first your list becomes "firstsecondthird" (a short version of it), then that is reversed to "driht...".