in reply to exists() unexpected behavior

This is known, and very very hard to change. Perhaps in Perl 6.

-- Randal L. Schwartz, Perl hacker

Replies are listed 'Best First'.
Re: Re: exists() unexpected behavior
by Rhandom (Curate) on Apr 12, 2001 at 09:29 UTC
    Is this that hard to change? (A naive question coming from somebody who codes IN perl but doesn't code the perl) Autovivication is a great thing so that constructs such as $a->{b}->{c} = 'd' create the entire structure without much tedium. That being said, looking at a file existence check of (-e "/a/b/c/d") or a system ls on a directory doesn't go about creating directories (I know, I know ... apples to oranges). Is this planned behavior. It seems that it would make good sense in an assignment operator, but that is all. Does it have to occur whenever it tries to back up the reference line?
    OK, I've probably put my foot in my mouth because I haven't looked at the back end of Perl.

      See the other replies for why Perl does this. I have a subroutine I use when I want to get a value from a nested structure only if it exists. You can modify this to do the existence check only if you need that.

      use Carp; sub safe_get { my $handle = shift; my $ptr = $handle; for (my $i = 0; $i < @_; $i++) { my $key = $_[$i]; # Handle each type my $type = ref $ptr; if (not defined $type) { croak "Not a reference.\n"; } elsif ($type eq 'HASH') { return undef unless exists $ptr->{$key}; $ptr = $ptr->{$key}; } elsif ($type eq 'ARRAY') { croak "Non numeric array index '$key'." unless $key =~ m/^\+?\d+$/; croak "Bad array thing '$key'." unless $key >= 0; return undef unless $key < @$ptr; $ptr = $ptr->[$key]; } else { croak "Unable to handle type '$type'"; } # Is this the end? return $ptr if $i == @_ - 1; } } # Usage my %foo = {bar => [1, {baz => 'xyzzy'}] }; my $value1 = safe_get(\%foo, 'bar', 1, 'baz'); my $value2 = safe_get(\%foo, 'bar', 2, 'baz'); # $value1 is 'xyzzy', $value2 is undef

      -ben

      Well, technically, that's exactly what needs to be fixed, but it'd be hard to fix it. The dereferencing operator at the tail end knows if it's in an lvalue (being assigned to) or rvalue (being accessed) context, but apparently, the information is not available to the dereferencing operators in the middle of the chain, and that'd be messy to add. Apparently, it requires adding a new bytecode to Perl, and that has a lot of potential for breaking many more things than it fixes.

      For now, the known workaround is to step carefully down the tree, calling exists at each level before proceeding to the next. In practice, I've not been bitten by this, but maybe it's because I had been bitten once or twice while practicing with references. {grin}

      -- Randal L. Schwartz, Perl hacker