Q: detect non-existent hash entries w/function?

  • Thread starter Daniel Friedman
  • Start date
D

Daniel Friedman

I'm trying to figure out how to to detect non-existent hash entries
via a function, something of this general nature:


function hashexists($$) {
# first arg might have to be non-scalar to get this to work,
# that would be OK, too
my var1 = $_[0]; # maybe a scalar, maybe not
my $err_hint = $_[1];

if (exists <something here related to var1>) {
# If I can get this function to work, maybe I'll redefine
# it to provide the value of the specified hash,
# or die otherwise; for now, let's just...
return(1);
} else {
die "<something [else?] related to var1> doesn't exist; (hint:
$err_hint)"
return(0);
}


I haven't been able to do this sort of thing
with "use strict", which I regard as a must;
Any thoughts on how to achieve this?

Thanks very much,
--daniel
 
T

Tad McClellan

Daniel Friedman said:
my var1 = $_[0]; # maybe a scalar, maybe not


No "maybe not" about it.

If it starts with a dollar sign, it *is* a scalar.

So what did you really mean there?

I haven't been able to do this sort of thing


I can't figure out what "sort of thing" you are after. Sorry.
 
M

Martien Verbruggen

I'm trying to figure out how to to detect non-existent hash entries
via a function, something of this general nature:

$ perldoc -f exists
function hashexists($$) {
# first arg might have to be non-scalar to get this to work,
# that would be OK, too

The first argument will be a scalar. That's what that prototype does
for you. The first and second argument will be forced to be
interpreted in scalar context.

So,

sub foo($$) { print "$_[0]:$_[1]\n" }

my @a = (1, 2);
my @b = (1, 2, 3, 4);

foo(@a, @b);

Will print

2:4
my var1 = $_[0]; # maybe a scalar, maybe not

No. A syntax error.

If you meant to write

my $var1 = $_[0];

then yes, it is a scalar. Always.
my $err_hint = $_[1];

if (exists <something here related to var1>) {

What does "something here related to var1" mean?
# If I can get this function to work, maybe I'll redefine
# it to provide the value of the specified hash,
# or die otherwise; for now, let's just...
return(1);
} else {
die "<something [else?] related to var1> doesn't exist; (hint:
$err_hint)"

Similar question about this bit.
return(0);

This return will never be reached. You just called die.

I have tried, but I don't really know how to interpret this.
I haven't been able to do this sort of thing
with "use strict", which I regard as a must;

Well... I don't think strict has anything to do with it.
Any thoughts on how to achieve this?

What is 'this'? Could you be a bit more specific? I am really not sure
what you're trying to do.

Martien
 
B

Brian McCauley

Daniel Friedman said:
my var1 = $_[0]; # maybe a scalar, maybe not


No "maybe not" about it.

If it starts with a dollar sign, it *is* a scalar.

Yes, this is so.

This is why I find the following annoying

my $glob;
my $r = \$glob;
print ref $r; # prints SCALAR
$glob = *FOO;
print ref $r; # prints GLOB

--
\\ ( )
. _\\__[oo
.__/ \\ /\@
. l___\\
# ll l\\
###LL LL\\
 
C

Charlton Wilbur

I'm trying to figure out how to to detect non-existent hash entries
via a function, something of this general nature:

If I understand what you're trying to do, why not just use

exists $hash{$key}

instead of creating a messy, complicated function to do the same thing?

Or, if you wanted to check multiple keys simply,

@nonexistent = grep { not exists $hash{$_} } @possible_keys;

Charlton
 
D

Daniel Friedman

There was apparently some ambiguity in my earlier post, so let me try
to clarify.

1) Purpose/motivation: I'm writing a script which will have lots of
places in which I want to carefully check for the existence of a hash
entry, and also avoid autovivification (I admit that the
non-autovification piece was not in my original post, I omitted it to
try to focus my question), before getting the value from the
hash--here's what I mean:

$errhint = __FILE__; # this is just an example
unless (exists $myhash{$foo}) {
die "$errhint: myhash{$foo} does not exist";
}
unless (exists $myhash{$foo}{$bar}) {
die "$errhint: myhash{$foo}{$bar} does not exist";
}
unless (exists $myhash{$foo}{$bar}{$baz}) {
die "$errhint: myhash{$foo}{$bar}{$baz} does not exist";
}
# apparently it exists, so let's get the value:
$thevalue = $myhash{$foo}{$bar}{$baz}

---> I want to make a function which does this. The function's
arguments
should be the "specification" of a hash whose existence is to be
checked, and some string for helping find the error ($errhint, above).
(The function would preferably be able to handle a non-fixed number
of hash levels.)

2) When I wrote in my earlier post "maybe a scalar, maybe not", I
meant that I wasn't fussy if the function receives the specification
as a single scalar argument (e.g. "myhash{$foo}{$bar}{$baz}") or in
some other form ("myhash", "$foo", "$bar", "$baz"). I think it can't
be a reference since I don't imagine it's possible to make a reference
to something which doesn't necessarily exist.

I hope that clarifies my question. Again, thanks very much,
--daniel
 
U

Uri Guttman

DF> There was apparently some ambiguity in my earlier post, so let me try
DF> to clarify.

DF> 1) Purpose/motivation: I'm writing a script which will have lots of
DF> places in which I want to carefully check for the existence of a hash
DF> entry, and also avoid autovivification (I admit that the
DF> non-autovification piece was not in my original post, I omitted it to
DF> try to focus my question), before getting the value from the
DF> hash--here's what I mean:

first level hash lookups never autovivify. only multilevel lookups do
that. basically autoviv happens when you dereference through undef. see
my paper on this at:

http://tlc.perlarchive.com/articles/perl/ug0002.shtml

uri
 
T

Tad McClellan

Daniel Friedman said:
There was apparently some ambiguity in my earlier post, so let me try
to clarify.

1) Purpose/motivation: I'm writing a script which will have lots of
places in which I want to carefully check for the existence of a hash
entry, and also avoid autovivification (I admit that the
non-autovification piece was not in my original post, I omitted it to
try to focus my question),



Errr, but that *is* your question:

detect non-existent hash entries w/o autoviv'ing

The answer to your OP questions was:

exists $myhash{$foo}{$bar}{$baz}

which doesn't avoid the autoviving for you.

---> I want to make a function which does this. The function's
arguments
should be the "specification" of a hash whose existence is to be
checked, and some string for helping find the error ($errhint, above).
(The function would preferably be able to handle a non-fixed number
of hash levels.)

2) When I wrote in my earlier post "maybe a scalar, maybe not", I
meant that I wasn't fussy if the function receives the specification
as a single scalar argument (e.g. "myhash{$foo}{$bar}{$baz}") or in
some other form ("myhash", "$foo", "$bar", "$baz").
I hope that clarifies my question.


It doesn't clarify your question, it states your question. :)

Here is a function to get you started, it wants a hash-ref as
the first arg, followed by a list of keys, eg:

do_something() if exists_no_viv(\%myhash, $foo, $bar, $baz)


---------------------------
sub exists_no_viv { # "walk" down a chain of hashrefs
my $h = shift; # a ref to hash, start at the "top"

while ( my $k = shift ) {
return 0 unless exists $h->{$k}; # fail w/o autoviv
if ( ref $h->{$k} eq 'HASH' ) # go one level "deeper"
{ $h = $h->{$k} }
}
return 1;
}
 
D

Daniel Friedman

Tad,

Late yesterday, the same idea sprouted in my mind, and lo, you've
given me the code! Bingo, this is just what I was looking for; thanks
very much.

--dan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,898
Latest member
BlairH7607

Latest Threads

Top