Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

Dereferencing and context?

by Not_a_Number (Prior)
on Feb 08, 2004 at 18:08 UTC ( #327484=perlquestion: print w/replies, xml ) Need Help??
Not_a_Number has asked for the wisdom of the Perl Monks concerning the following question:

I would have expected the following two snippets to have the same output:

# Simple arrays: my @ary1 = ( 'a' .. 'e' ); my @ary2 = ( 0 .. 4 ); my $str = ''; $str .= $_ for @ary1, @ary2; print $str; # Array of arrays: my @AoA = ( [ 'a' .. 'e' ], [ 0 .. 4 ] ); my $str2 = ''; $str2 .= @$_ for @AoA; print $str2;

But the output from the first is:

abcde01234

while that from the second is:

55

Presumably, the concatenation operator is imposing scalar context in the second case (it's like if I'd done:

$str .= $_ for scalar @ary1, scalar @ary2;

in the first bit).

Wherein lies the difference?

TIA

dave

Replies are listed 'Best First'.
Re: Dereferencing and context?
by Corion (Pope) on Feb 08, 2004 at 18:18 UTC

    The difference lies in the fact that Perl automatically flattens all lists in a comma separated expression:

    print $_ for @arr1, @arr2

    is (for this example) the same as

    my @temp = @arr1; push @temp,@arr2; print $_ for @temp;

    where your second example does not have implicit list flattening as you are dealing with references. Your second example

    print @$_ for ( [ 'a' .. 'e' ], [ 0 .. 4 ] );

    is equivalent to

    print @$_ for \@arr1, \@arr2

    and to get the equivalent to your first example, you have to turn the references back into the list elements first, for example by using map, which can return multiple output elements for one element :

    print $_ for (map { @$_ } \@arr1, \@arr2);
Re: Dereferencing and context?
by Abigail-II (Bishop) on Feb 08, 2004 at 18:15 UTC
    Presumably, the concatenation operator is imposing scalar context in the second case
    Not just in the second case. It always imposes scalar context on both operands.
    Wherein lies the difference?
    The number of times you concatenate. The first time, you concatenate 10 times (as the arrays both have 5 elements). The second time, you concatenate twice - @AoA has two elements.

    Abigail

Re: Dereferencing and context?
by The Mad Hatter (Priest) on Feb 08, 2004 at 18:18 UTC
    I don't see why you would have expected the same output.

    In the second example, $_ is an array ref and when you dereference it is an array (for all purposes here). Since you're concatenating to a string, it has to be a scalar value, and the scalar value of an array is the number of elements in that array. In the first example, you explicitly concatenate the elements of both arrays.

    The difference is that in the first you are concatenating elements, and in the second you are concatenating the scalar values of two arrays.

Re: Dereferencing and context?
by Not_a_Number (Prior) on Feb 08, 2004 at 18:47 UTC

    Thanks very much for these replies. As I wanted a string, I will use:

    my $string = join '', map @$_, @AoA;

    dave

      or equivalently:
      my $string = join '', @$_ for @AoA;
      my $string = ''; $string .= join '', @$_ for @AoA;
      update: it has to be ".=", not just "=", with $string scoped/declared outside the for loop, in order to get all the elements. (thanks to Zaxo for pointing out the mistake)
Re: Dereferencing and context?
by davido (Cardinal) on Feb 09, 2004 at 03:12 UTC
    Since others have pointed out that the concatenation operator evaluates its operands in scalar context (which is what you should expect), just take it one step further and remember what happens when you evaluate an @array in scalar context? ....you get a number signifying the number of elements in the array. For example:

    my @array = qw/a b c d e/; print scalar @array, "\n"; __OUTPUT__ 5

    Now, this creates two annonymous arrays referred to by the two first elements of @aoa;

    my @aoa = ( [a, b, c], [d, e, f] );

    And when you dereference it like this, you evaluate one complete array:

    my @array = @{$aoa[0]}; print scalar @array, "\n"; __OUTPUT__ 3

    Well, your code snippet simply evaluates in scalar context two individual anonymous arrays, thus concatenating together the value representing the number of elements in each of those two anonymous arrays held in @aoa.

    The result of '5' . '5' is '55'.... nothing surprising if you walk through what's happening.


    Dave

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://327484]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others about the Monastery: (4)
As of 2018-12-15 17:03 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    How many stories does it take before you've heard them all?







    Results (70 votes). Check out past polls.

    Notices?