Re: exists on hash autovivifies right?
by pc88mxer (Vicar) on Jun 28, 2008 at 23:07 UTC
|
Yes, it will autovivify intermediate structures (tested with 5.8.8 and 5.10) but not the final element being tested:
use Data::Dumper;
my $x;
if (exists $x->{a}->{c}) {
print "c exists\n";
} else {
print "c doesn't exists\n";
}
print Dumper($x);
__END__
c doesn't exist
$VAR1 = {
'a' => {}
};
Update: added confirmation about 5.10 | [reply] [d/l] |
|
No, not really. exists never autovivifies, but it doesn't prevent anything else (such as ->) from causing autovivification. In the given example ($x->{a}->{c}), the first -> autovivifies $x and the second -> autovivifies $x->{a}. This occurs independently of exists.
>perl -le"$x->{a}->{c}; print $x; print $x->{a}"
HASH(0x225f18)
HASH(0x226020)
| [reply] [d/l] [select] |
|
this is the best answer I read so far. thanks.
| [reply] |
|
If you need to test for existence without autovivification, you'll have to code up a test that goes something like this:
sub my_exists {
my $struct = shift;
while (@_) {
my $key = shift(@_);
return false unless exists $hash->{$key};
$hash = $hash->{$key};
}
1;
}
my $x = {};
if (my_exists($x, 'a', 'c')) {
print "c exists\n";
} else {
print "c doesn't exist\n";
}
print Dumper($x);
| [reply] [d/l] |
|
| [reply] |
|
|
| [reply] |
|
| [reply] |
|
well, cool that you answered. btu I dislike the behavior a lot. who does not?
| [reply] |
|
A reply falls below the community's threshold of quality. You may see it by logging in.
|
Re: exists on hash autovivifies right?
by GrandFather (Saint) on Jun 28, 2008 at 23:17 UTC
|
No. exists would always return true if it autovivified the element being tested. It will however autovivify any elements the element being tested depends on. Consider:
use strict;
use warnings;
my %hash;
if (exists $hash{top}{dependent}) {
print "\$hash{top}{dependent} exists\n";
} else {
print "\$hash{top}{dependent} does not exist\n";
}
if (exists $hash{top}) {
print "\$hash{top} exists\n";
} else {
print "\$hash{top} does not exist\n";
}
Prints:
$hash{top}{dependent} does not exist
$hash{top} exists
Perl is environmentally friendly - it saves trees
| [reply] [d/l] [select] |
|
I noticed that from the first example, and my memory of auto-vivification did fade a little. you said "exists would always return true if it autovivified the element being tested", well not entirely true, depends on sequence of events, but that's meaningless argue any way. thanks for taking your time.
| [reply] |
|
| [reply] |
|
Re: exists on hash autovivifies right?
by ysth (Canon) on Jun 29, 2008 at 05:42 UTC
|
You can protect against it with || (at the cost of some ugliness), like so:
# instead of: if (exists $x->{a}[0]{c}) {
if (exists ${ ${ $x->{a} || [] }[0] || {} }{c}) {
| [reply] [d/l] |
A reply falls below the community's threshold of quality. You may see it by logging in. |
Re: exists on hash autovivifies right?
by GrandFather (Saint) on Jun 28, 2008 at 23:59 UTC
|
I don't know what the application domain is nor how you got bit by this behaviour, but you may find Data::Diver helps.
Perl is environmentally friendly - it saves trees
| [reply] |
|
no, it didn't get me. I was aware of this from start on, so the code was right. just wanted to confirm my understanding, since I haven't perl 4 a while. played with given/when and say, nice little improvement.
| [reply] |
Re: exists on hash autovivifies right?
by ysth (Canon) on Jun 29, 2008 at 21:50 UTC
|
| [reply] |
|
That will turn an attempt to autovivify into an exception.
$ perl -MHash::Util=lock_keys -wle 'my %x; lock_keys %x; exists $x{a}{
+b}'
Attempt to access disallowed key 'a' in a restricted hash at -e line 1
+.
Very useful for debugging. | [reply] [d/l] |
|
that also turns lots of other things into an exception, good luck.
| [reply] |
|
that's not a solution, unless the lock on keys is what you happen to want. a solution must be precise.
| [reply] |
Re: exists on hash autovivifies right?
by Anonymous Monk on Jun 28, 2008 at 23:02 UTC
|
missed a small thing.. it vivifies to undef? | [reply] |
Re: exists on hash autovivifies right?
by menolly (Hermit) on Jun 30, 2008 at 21:18 UTC
|
I've taken advantage of short-circuiting operators to deal with this in the past, like so:
if (exists($x->{a}) && exists($x->{a}->{c}) { #do stuff }
Might get annoying if your hash is particularly deep, though.
| [reply] [d/l] |