J> undef %o, %e;
first off it isn't even needed before the first loop.
Sometimes I like to have an explicit initialization, as documention
that I have considered the issue and believe that the assignment is
needed at that point. It's also nice if I have to move the block of
code someone else. But I'm idiosyncratic in that respect -- I suspect
few people do that.
secondly it doesn't do what you think it does.
If nothing else, for one reason not mentioned yet. The undef docs say
undef EXPR
undef
... Note that this is a unary operator, not a list operator.
That is, it takes either zero or one argument. It certainly doesn't
take two or more. So the quoted line is equivalent to
(undef(%o)), %e;
It undefs only %o and doesn't touch %e. %e is evaluated in a void
context, and if it returns a value, it's thrown away.
The output under Perl 5.14 of
#! /usr/bin/perl -w
use strict;
use warnings;
my %x;
my %y = ('sparkly' => "You might think this is deleted by undef");
undef %x, %y;
print "$y{'sparkly'}. If so, you'd be wrong.\n";
exit 0;
is
$ perl local/test/095.pl
Useless use of private hash in void context at local/test/095.pl line 6.
You might think this is deleted by undef. If so, you'd be wrong.
Note well: if the original poster had used
use strict;
use warnings;
as ought to be done, the bug would have been found.
Similarly for "my" taking only one argument (though it can be a list
of variables), and that "use strict; use warnings;" is great.
$ perl -e 'use warnings; my $x = 3, $y = 4;'
Name "main::y" used only once: possible typo at -e line 1.
That is, the warning about $main::y indicates that $y was NOT my-ed.
$ perl -e 'use strict; use warnings; my $x = 3, $y = 4;'
Global symbol "$y" requires explicit package name at -e line 1.
Execution of -e aborted due to compilation errors.
is better, having a fatal error due to the undeclared $y.
The usual way for multiple initializations in my is with separate
statements
$ perl -e 'use strict; use warnings; my $x = 3; my $y = 4; print "$x $y\n"'
3 4
or with lists
$ perl -e 'use strict; use warnings; my ($x, $y) = (3, 4); print "$x $y\n"'
3 4
the proper way to clear hashes is to assign an empty list to them:
%o = () ;
undef is not meant to be used on aggregates (arrays and hashes). it
not only clears the data, it reclaims all storage inside it.
Um, if (by Grice's heuristics) you're trying to imply that %o=() does
NOT reclaim all storage, you just made undef sound better. In Perl
5.14, the scalar value of the hash is the same for deleting every
existing element, assigning (), or undeffing:
#! /usr/bin/perl -w
my %x;
@x{0..1000} = ();
print '%x is ', scalar(%x), "\n";
delete @x{0..1000};
print '%x is ', scalar(%x), "\n";
@x{0..1000} = ();
%x = ();
print '%x is ', scalar(%x), "\n";
@x{0..1000} = ();
undef %x;
print '%x is ', scalar(%x), "\n";
exit 0;
results in
$ perl local/test/097.pl
%x is 630/1024
%x is 0
%x is 0
%x is 0
There may well be a way to look at internals to know how much storage
space is used for each behind the scenes, but I don't know what such a
method might be.
(As a tangent: I think there was a way in Perl 4 to assign to a
subscript of an array, shrink the array to be smaller than the
subscript, regrow past that subscript, and see the assigned value
again. Does anyone remember the details? Please tell me that it no
longer works.)
and it leads to a worse problem which is using defined on aggregates
to see if they have any elements.
That is to say, using "undef %x" might lead you to think that
"defined %x" is also usable, but "defined" on a hash table is a trap
and a snare, because
and that is very wrong as defined on a hash which has been undef'ed
will be false but if is ever had elements but was empty now, defined
on it will be true. and that is almost never what you expect.
Indeed. To illustrate that,
#! /usr/bin/perl -w
use strict;
use warnings;
my %x;
sub checkx($) {
print "After $_[0]\n";
print " defined? ", (defined %x ? "yes\n" : "no\n");
print " boolean? ", (%x ? "true\n" : "false\n");
print "\n";
}
checkx("start");
%x = ();
checkx("empty list");
# Quotes aren't needed around 'fred' or 'sparkly',
# but I'd rather not go into the bareword rules.
$x{'fred'} = 'barney';
$x{23} = 45;
delete $x{23};
delete $x{'fred'};
checkx("deleting last element");
%x = ();
checkx("again empty list");
undef %x;
checkx("undeffing");
exit 0;
results in
$ perl local/test/094.pl
defined(%hash) is deprecated at local/test/094.pl line 8.
(Maybe you should just omit the defined()?)
After start
defined? no
boolean? false
After empty list
defined? no
boolean? false
After deleting last element
defined? yes
boolean? false
After again empty list
defined? yes
boolean? false
After undeffing
defined? no
boolean? false
That is, "use warnings;" again comes through. And the program shows
that a simple use of %x in boolean context like
if (! %x)
tells you accurately in each case that %x has no elements, but
if (! defined %x)
is not a reliable indication of that.