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

Hi,
I'm currently refreshing my Perl experience by reading some books. During testing some scripts, I've noticed a strange behaviour during the following script:
#!/usr/bin/perl binmode(STDOUT, ":utf8"); use 5.010; use strict; use warnings; use diagnostics; use utf8; my @fred; my $fred; $fred = "HALLO"; $fred[0] = "eins"; $fred[1] = "zwei"; $fred[2] = "drei"; $fred[3] = "vier"; $fred[4] = "fünf"; $fred[5] = "sechs"; $fred[6] = "sieben"; $fred[7] = "acht"; $fred[8] = "neun"; $fred[9] = "zehn"; print @fred; print "\n"; print @fred."\n";
The output result is the following:
einszweidreivierfünfsechssiebenachtneunzehn 10
Why is the array counted if I use a new line?
Is this normal and why?

Thanks!

Kind regards,

Pingu

Replies are listed 'Best First'.
Re: Strange behaviour with Arrays and print?
by Corion (Patriarch) on Jul 12, 2014 at 13:00 UTC

    Perl sees your last line as

    print( (@fred."\n") );

    ... that is, it first evaluates @fred . "\n" and then prints that result.

    . evaluates its operands in scalar context. An array in scalar context evaluates to the number of its elements. Your expression then becomes

    print( (scalar(@fred),"\n") );

    ... which is

    print 10,"\n";

    If you want to print an array, maybe put it in string context first:

    print "@fred\n";
      or use say instead of print, then you don't have to append a "\n".

      CountZero

      A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

      My blog: Imperial Deltronics
      Hi,

      but why is this:

      print @fred;

      not the same? This prints the elements and not the scalar / count number.

      Kind regards,

      pingu

        Because print takes a list as an argument so @fred is not coerced into scalar context. In your original print @fred."\n" the concatenation coerces scalar context, hence the "10" but if you'd used a comma instead of a full stop then that would have been a list and the elements of @fred would have been printed.

        $ perl -Mstrict -Mwarnings -e ' > my @fred = qw{ one two three }; > print @fred . qq{\n}; > print @fred, qq{\n}; > print qq{@fred\n};' 3 onetwothree one two three

        I hope this makes things clearer.

        Cheers,

        JohnGG

        Because you are then passing the array  @fred to the function print as an argument list; the array is evaluated in list context and yields its individual elements.

        Update: E.g.:

        c:\@Work\Perl>perl -wMstrict -e "sub foo { print $_[1]; print qq{\n}; ;; my @copy_of_arguments = @_; print $copy_of_arguments[1]; print qq{\n}; } ;; my @ra = qw(one two three); foo(@ra); ;; foo('four', 'five', 'six'); " two two five five
        See  @_ in perlvar.

Re: Strange behaviour with Arrays and print?
by Anonymous Monk on Jul 12, 2014 at 15:54 UTC

    For completeness:

    my @a = qw/foo bar quz/; print "----- 1 -----\n"; print @a; # "foobarquz" print "\n----- 2 -----\n"; print scalar @a; # "3" print "\n----- 3 -----\n"; print @a , "\n"; # "foobarquz" print "----- 4 -----\n"; print @a . "\n"; # "3" print "----- 5 -----\n"; print "@a"; # "foo bar quz" print "\n----- 6 -----\n"; $" = "&"; print "@a\n"; # "foo&bar&quz" print "----- 7 -----\n"; $, = "%"; print @a , "\n"; # "foo%bar%quz%" print "----- -----\n";
    1. @a is in list context and provides the arguments to print, which simply outputs them one after the other.
    2. @a is forced to scalar context, and an array in scalar context returns the number of its elements.
    3. The same as 1. except there's an additional argument, "\n", compare this to the next case.
    4. The dot operator (.) concatenates two strings, and here @a is forced into scalar context the same way the scalar function does in 2.
    5. String interpolation of an array is like doing join($", @a) (see perldata).
    6. Same as 5. except we've fiddled with $" (the list separator) for demonstration purposes.
    7. Here's an interesting one not yet mentioned: $, (the output field separator) is what print outputs between its arguments. The extra % at the end is because that's output between the last element of @a and the \n.
Re: Strange behaviour with Arrays and print?
by Anonymous Monk on Jul 12, 2014 at 13:48 UTC
    Actually, I'd say it's pretty strange indeed
    perl -E 'my @a=qw(10 20 30); say "@a!"; say @a . "!"'
    Output:
    10 20 30! 3!
    I always thought that things like "$foo\n" were compile-time shortcuts for $foo . "\n". Apparently not, at least not for arrays...

      But in the spirit of your example code, the compiler might proceed something like:
      Source   "@a\n"
      Becomes  "@a" . "\n"
      Becomes  join($", @a) . "\n"
      Becomes  "10 20 30" . "\n"
      Becomes  "10 20 30\n"
      with  join($", @a) (or its runtime equivalent) still providing list context to the array.

        You're right, of course. Also, it appears that Perl has different overloads for for string concatenation and stringification. Interesting... I never knew that.