Perl Golf, I find, exposes me to some of the most unusual things in Perl as one tries to find a way to save a single character. Sometimes you discover a dozen different ways that don't work, a few that sort-of work, and one that really works, but sometimes for reasons unknown. In a recent effort, I found something a little surprising in the way that Perl processes an array definition which was causing some alignment problems within my program, and it made me think about something I hadn't thought about before.

What is the difference between "undef" and "nothing" in the context of an array definition?

Here is an array that has two elements, the first entry disappearing because it is an empty array:
my @array = ( (), 1, 2 );
Here is an array that has three elements, the first entry staying because it is a value of 'undef':
my @array = ( undef, 1, 2 );
Here is an array that has two elements, the first entry disappearing because it references "nothing":
my @array = ( (1,2,3)[3], 1, 2 );
The way map operates, collapsing out 'undef' values, and the way a regular array treats data, is slightly different and may be cause for confusion.

So, here's two simple questions for reflection:
  1. What is the value of '()' and how does this compare to the "value" of undef?
  2. What is the shortest way to insert an undef value into an array as a place holder? (Think: Perl Golf)
This kind of reminds me of the subtle difference between the deprecated "defined %hash" versus "scalar keys %hash" that was discussed recently.

Replies are listed 'Best First'.
Re: Collapsing Arrays with Empty Values
by japhy (Canon) on Jul 04, 2001 at 19:36 UTC
    An empty list, in list context, is just that -- a list with 0 elements. In scalar context, though, something must be assigned, and undef is that assigned value. Indexing beyond the end of a list, in list context, returns an empty list, and undef in scalar context.

    It is a possible oddity, though, that indexing an element of a list which is undef and assigning it to a list returns an empty list, and not the undef that was there -- this is probably because it was within the same blanket solution to the problem above. However, in 5.6.0, this buggish behavior was removed.
    # in 5.005_02 $x = (1,2,3)[10]; # $x is undef @x = (1,2,3)[10]; # @x is (), not (undef) @x = (undef)[0]; # @x is (), not (undef) # in 5.6.0 $x = (1,2,3)[10]; # $x is undef @x = (1,2,3)[10]; # @x is (), not (undef) @x = (undef)[0]; # @x is (undef), not ()
    My golf approach would be:
    # returns the collapsed list: 15 chars # 123456789_12345 sub collapse {grep{defined}@_} # returns the collapsed list, via array ref: 20 chars # 123456789_123456789_ sub collapse {grep{defined}@{+pop}} # modifies array ref elements in place: 26 chars # 123456789_123456789_123456 sub collapse {@$_=grep{defined}@{$_=pop}}


    japhy -- Perl and Regex Hacker
Re: Collapsing Arrays with Empty Values
by busunsl (Vicar) on Jul 04, 2001 at 14:01 UTC
    To your first question:
    If you assign () to a scalar variable, the value of that variable will be undef.
    Why it seems to be different in array assingment, I don't know.

    To your second question:
    The shortest undef is $\, which is undef by default.

Re: Collapsing Arrays with Empty Values
by John M. Dlugosz (Monsignor) on Jul 04, 2001 at 23:26 UTC
    Hmm, so the implication is that (1,2,3)[3] is similar to @x[3], not $x[3]. Why? Indexing beyond the end of the array returns a different "error" value depending on its context. Normally, indexing an array specifies scalar or list return values based on the signet used in front of the array name. It's a logical thing to do, but can cause wierd results because the dereference does different things depending on its actual argument.

    —John