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

Well I was coding for too long at one time again and I made a silly mistake that had me scratching my head.
I had:
my @array = ('red','green','blue'); print @array . "\n";
But it was printing '3' instead of what I thought it should which is 'redgreenblue'
Since it was inside a loop I thought it might be a scoping issue. I poked around a bit and finally I took a break. Then it occured to me, "Comma not period!".
So I changed to the code to read:
my @array = ('red','green','blue'); print @array , "\n";

And everything is fine, well almost.
Its bugging my why it was returning the number of elements instead of nothing or an error. It is my assumption that the '.' forces the variable to be printed in a scalar context instead of as a list. I also assume that the ',' is simply adding a element to the list since ',' is a list seperator character. I found something in the Camel book in the Efficiency section, but it only explained that the ',' is faster in some cases when doing a concatenation. I never really gave this much thought until I used the wrong concatenation character.

What book can I refer to for a detailed explaination?
Are my assumptions correct?

Replies are listed 'Best First'.
Re: Period vs. Comma concatenation and reference material for it
by belg4mit (Prior) on Jan 23, 2002 at 07:15 UTC
    In your example the array is in scalar context (due to concatenation). An array in scalar context returns the number of elements in the array.

    The efficiency bit is referring to:

    print 'hello', 'bob', 'smith', "\n"; #vs. print 'hello' . 'bob' . 'smith' . "\n";
    The second one requires perl to do more work as it must do a concatenation on all the elements and then print does it's thing on the result. The former works because print works in list context by simply doing it's thing to each and every element of the list you provide. See $OFS in perlvar and print for some other differences.

    --
    perl -pe "s/\b;([st])/'\1/mg"

Re: Period vs. Comma concatenation and reference material for it
by count0 (Friar) on Jan 23, 2002 at 20:22 UTC
    I think it's important to note here that a comma *does not* concatenate.
    print() accepts a list, which is what you were giving it.
    It is my assumption that the '.' forces the variable to be printed in a scalar context instead of as a list.
    Bingo =)
    The dot operator concatinates two strings
    A string is a scalar. You tried to concat a string ("\n") with a list, which is not possible. So Perl took the liberty of putting @array in its scalar context.

Re: Period vs. Comma concatenation and reference material for it
by dereks (Scribe) on Jan 23, 2002 at 08:29 UTC
    This doesn't answer your question on efficiency, but if you really like using the period, you could always force list context.
    print (@array) . "\n"; # this is broken
    This isn't correct at all as pointed out here.

    Update: Retracted bad suggestion. Thanks, chipmunk.

    - Derek Soviak

      This doesn't answer your question on efficiency, but if you really like using the period, you could always force list context. print (@array) . "\n";

      That won't quite do what you intend. First, parentheses around an expression do not force list context. Consider print ( (@array) . "\n");, which prints the size of the array, just as without any parentheses.

      Parentheses do affect precedence, however, which leads to the second problem. The parentheses in your snippet cause perl to treat the print as a function call, with the concatenation applied to the result. This has the same effect as: (print(@array)) . "\n"; The contents of @array will be printed, print's return value will be concatenated with newline, and the resulting string will be discarded. With warnings enabled, your code would produce:

      print (...) interpreted as function at - line 1. Useless use of concatenation in void context at - line 1.

      Useful ways to print an array include:

      print @array, "\n"; # joined with '' print "@array\n"; # joined with $", ' ' by default print join("\t", @array), "\n"; # joined with whatever you specify