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

Dear fellow Monks,

I've stumbled upon this strange behavior: map will convert an undef scalar into an empty array reference when attempting to iterate on it. Here's an example:

#!/usr/bin/perl -w use strict; use Data::Dumper; my $aref = undef; print 'BEFORE: ', $aref ? "TRUE\n" : "FALSE\n"; print Dumper $aref; print "\n"; my @a = map {$_} @$aref; print 'AFTER: ', $aref ? "TRUE\n" : "FALSE\n"; print Dumper $aref; print "\n";
Do you know if this behavior is documented somewhere? I've read the perlref manpage and its doesn't mention it. Could it be considered a bug in Perl?

One other interestinging thing about this is that the -w flag will complain when using an undefined value as an array reference, but not in the example above. Try substituting the map line above for "my @a = @$aref;" to see my point. I ran this on Perl 5.6.

Thanks,

Gregorovius

Replies are listed 'Best First'.
Re: side effects of map
by dvergin (Monsignor) on May 20, 2001 at 11:21 UTC
    This subtle example of autovivification deserves a bit of discussion. It is not something that is self-evident in the docs.

    First: autovivification occurs when an lvalue (cling to this word in the paragraphs below) contains references that did not previously exist. So this:

    my $href; $href->{smith}{john}{eyecolor} = 'blue';
    works because the reference keys are autovivified to provide a slot for the value 'blue'. So far, so good...

    But interestingly, even though it does not appear to be an lvalue, the following also causes keys to magically appear:

    my $href; my $color = $href->{smith}{john}{eyecolor};
    In the process of looking for a value to return, Perl creates (autovivifies) the 'smith' and 'john', keys and then returns undef (eyecolor) to be assigned to $color. The Camel book (3rd Edition, p. 710) describes this while suggesting that this behavior may be "fixed in a future release".

    The same goes for:

    my $href; if (exists $href->{smith}{john}{eyecolor}) { # do something }

    lvalue? bug? You be the judge.

    So... to get closer to your code, if we said:

    my $aref = undef; my $a = $$aref[0];
    We would not thereby create a zero-th element but we would cause the undef $aref to autovivify as a reference to an anonymous array in the process of looking for the non-existent zero-th element.

    If you have made it this far, it's only one more step into the fog to suggest that (just as with the previous example):

    my $aref = undef; my @a = map {$_} @$aref;
    is going to look for a possible $$aref[0] ...and in the process autovivify the $aref as an actual reference to an anonymous array (containing no elements).

    Ain't Perl great?
    HTH

Re: side effects of map
by premchai21 (Curate) on May 20, 2001 at 08:48 UTC
    Yes. It's called autovivification. See perlref.
Re: side effects of map
by rchiav (Deacon) on May 20, 2001 at 07:47 UTC
    I don't know what value this is, but this behavior isn't limited to map. If you substitute your map line with
    foreach my $a (@$aref) { };
    The same thing will occur. The only thing that comes to mind as far as why this would happen is that two things are happening in both cases.

    1) You're derefrencing the scalar as an array.
    2) You're using a function that can modify the contents of that array.

    In your other example, @$aref isn't modifiable. I personally wouldn't consider this a bug in perl. If you're going to access a refrence as an array, why is there a problem if it is an array?

    Rich