Dr. Mu has asked for the wisdom of the Perl Monks concerning the following question:

Yesterday I had the occasion to write,
undef ($from, $to) if $from > $to
It seemed like a reasonable thing to do. But apparently I had never tried it or had simply forgotten that, "The undef function is a unary operator, not a list operator, so you can only undefine one thing at a time." (Camel Book) So, I settled for the less elegant (in my mind),
$from = $to = undef if $from > $to
But I got to thinking, what would have been so bad about allowing undef to undefine a list of variables? I'm hard-pressed to think of any inconsistencies or ambiguities that might crop up if such a construct were allowed. After all, my can declare a list of variables. It seems logical that if you wanted to wipe that same list clean later, a parallel construction would be a clear and handy thing to have.

So, any ideas why this limitation exists in Perl?

20050201 Considered: holli: move to meditations, unconsidered by Corion: 13/19/0 - no decision

Replies are listed 'Best First'.
Re: undef a List of Variables
by borisz (Canon) on Jan 31, 2005 at 10:15 UTC
    You have several ways to undef a list of vars already. The most simple I know is
    ( $from, $to ) = ();
    Boris
Re: undef a List of Variables
by Anonymous Monk on Jan 31, 2005 at 11:07 UTC
    Take your pick:
    ($from, $to) = (); undef $_ for $from, $to; map undef $_, $from, $to; $from = $to = undef;
    A benefit of undef taking one argument is that you don't have to use parenthesis. You can use:
    undef $from, $to = 3 if $from > $to;
    which you couldn't if undef were to take a list. (Well, you could, but then $to wouldn't be 3 afterwards). Compare it to lc, which doesn't take a list either.
Re: undef a List of Variables
by ambrus (Abbot) on Jan 31, 2005 at 10:42 UTC

    It's easy to define a function that works like undef but allows multiple arguments. For example:

    sub undeff { @_[0..@_-1] = (); }; $foo = 5; $bar = 8; undeff($foo, $bar); # this undefs both of them print "foo=[$foo] bar=[$bar]\n"; # prints `foo=[] bar=[]' and two warn +ings
      sub undeff { @_[0..-1] = (); };

      -1 is the last index ... much easier to read. (And faster, too.)

      Being right, does not endow the right to be rude; politeness costs nothing.
      Being unknowing, is not the same as being stupid.
      Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence.
      Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.

        Yes, that works in most other languages. In ruby, arr[0..-1] returns all elements of the array (and is an lvalue too). In python, arr[0:-1] is all but the last element, arr[0:] or arr[:] is all elements. In octave, you don't have negative array indexes, but you have avec(:) for all of the vector, but also no special notation for all the elements starting the n'th (like arr[n:] in python). In mathematica, you have arr[[All]] for all elements of the array, but also no starting slice notation. (These are only a few languages of course.)

        Anyway, you can write 0..$#_ or even 0..@_ as the index, or avoid indexing completely and say sub undeff { undef $_ for @_ }.

        But it does not work.
        0..-1 is zero elements.
Re: undef a List of Variables
by holli (Abbot) on Jan 31, 2005 at 10:04 UTC
    how about,
    ($from,$to) = (undef) x 2;
    ?

    holli, regexed monk
Re: undef a List of Variables
by sh1tn (Priest) on Jan 31, 2005 at 11:23 UTC
    $a = 1; $b = 2; $b > $a and ($a, $b) = undef;