0

I use exists and defined in if statements all the time

if (exists($a->{b}) and defined($a->{b})

is there a subroutine that does both of these at the same time?

UPDATE:
Seems I didn't give very good example code. For a better question and matching answer check out checking-for-existence-of-hash-key-creates-key.

Community
  • 1
  • 1
Eric Fossum
  • 2,395
  • 4
  • 26
  • 50

3 Answers3

6

That's the same thing as

if (defined($a->{b}))

Regarding the reply in the comments, defined does not instantiate the keys.

>perl -E"if (exists($a->{b}) and defined($a->{b})) { }  say 0+keys(%$a);"
0

>perl -E"if (defined($a->{b})) { }  say 0+keys(%$a);"
0

->, on the other hand, autovivifies as normal.

>perl -E"if (defined($a->{b})) { }  say $a || 0;"
HASH(0x3fbd8c)

But that's the case for exists too.

>perl -E"if (exists($a->{b}) and defined($a->{b})) { }  say $a || 0;"
HASH(0x81bd7c)

If you're trying to avoid autovivification, you'd use

>perl -E"if ($a && defined($a->{b})) { }  say $a || 0;"
0

or

>perl -E"no autovivification; if (defined($a->{b})) { }  say $a || 0;"
0
ikegami
  • 367,544
  • 15
  • 269
  • 518
  • Nope, when using defined on a hash you inadvertently create the key. – Eric Fossum Oct 29 '12 at 20:57
  • "No, it doesn't" is the answer of a 5yo. Don't contradict someone without backing it up, or at least verifying your claim. My code will never create a key. It can create a hash ref in `$a`, but so can your original code. (It's `->` that creates the hash ref, and that's the first thing executed in both your code and my code.) – ikegami Oct 29 '12 at 20:59
  • 2
    @EricFossum You may be thinking of autovivification, which occurs if you use `defined` on a two-dimensional structure, such as `defined $foo->{bar}{baz}`, which creates the sublevel `$foo->{bar}` but not baz. – TLP Oct 29 '12 at 21:02
  • @TLP, I know, You seem to have misunderstood me. I was saying that autovifivication is not a "problem" introduced in my code. It existed in the original. (PS - my name is Eric too) – ikegami Oct 29 '12 at 21:06
  • @ikegami Ah yes, I see what you mean.. I was thinking of the keys, but you're right, the hash ref is also created. – TLP Oct 29 '12 at 21:07
  • Well seems like you would be right if you would have explained some more. I must have been doing something else when I used defined before. However, defined and exists ARE different and you seem to think they are the same. – Eric Fossum Oct 29 '12 at 21:08
  • @Eric Fossum, Of course `exists` and `defined` are different. What isn't different is `exists && defined` and `defined`. – ikegami Oct 29 '12 at 21:09
  • @ikegami - I agree 'exists && defined and defined', but I must be doing this autovivication somewhere. I don't know what it is though, I think I'll go look it up now. – Eric Fossum Oct 29 '12 at 21:19
  • @Eric Fossum, autovivification is the creation of hash or array when dereferencing an undefined scalar. e.g. `$h->{k}` is effectively short for `( $h //= {} )->{k}` because of autovivification. It has nothing to do with `defined` or `exists`. I showed two ways around it in my previously updated answer. – ikegami Oct 29 '12 at 21:22
2

defined(...) can only be true when exists(...) is true, so the answer to your question is that the subroutine is called defined.

mob
  • 117,087
  • 18
  • 149
  • 283
1
  • exists() checks if the key exists (even if undef value)
  • defined() checks if there is a value defined

if you only want to check if the key exists (even if undef) then just use exists()

here is a related questions that explains it quite nicely : What's the difference between exists and defined?

Community
  • 1
  • 1
xblitz
  • 663
  • 4
  • 14