exists#
Test whether a hash or array element, or a named subroutine, is present — without creating it and without caring what it holds.
exists asks a structural question: is there an entry at this
location? It does not ask what the entry’s value is. An entry whose
value is undef still exists. An entry that has never been assigned
does not — looking it up with a plain read would return undef, but
exists distinguishes the two cases.
Synopsis#
exists $hash{KEY}
exists $array[INDEX]
exists &subroutine
exists $ref->{A}{B} # autovivifies $ref->{A}!
What you get back#
A boolean: 1 (a true scalar) if the element or subroutine is
present, the empty string "" (a false scalar) if not. The result
is always a plain scalar — there is no list-context variant.
my %h = (a => undef);
exists $h{a}; # 1 (key exists)
defined $h{a}; # "" (value is undef)
exists $h{b}; # "" (key does not exist)
exists is not defined#
The two answer different questions and they disagree exactly when an
existing entry holds undef:
State |
|
Plain read |
|
|---|---|---|---|
Never assigned |
false |
false |
|
Assigned |
true |
false |
|
Assigned any other value |
true |
true |
that value |
Use exists when you need to know whether a key has been placed in
the structure — e.g. an option hash where a bare key means “the
caller opted in, value doesn’t matter.” Use defined when
you need to know whether a value is usable.
Examples#
Hash-key test. Classic option-hash idiom — presence, not truth:
sub configure {
my %opt = @_;
my $verbose = exists $opt{verbose}; # caller passed verbose => anything
my $color = $opt{color} // "auto"; # caller-supplied or default
...
}
Distinguishing “missing” from “present but undef”:
my %cache = (user_42 => undef); # cached: "we looked, nothing there"
if (exists $cache{user_42}) {
# hit — even though the value is undef, we already did the lookup
} else {
# miss — have to query the database
}
Sparse-array test. Deleting an array element leaves a hole that
exists reports as false:
my @a = (10, 20, 30);
delete $a[1];
exists $a[0]; # 1
exists $a[1]; # "" (hole)
exists $a[2]; # 1
exists $a[99]; # "" (past the end)
Subroutine existence. True once the sub has been declared, even if the body is a forward declaration with no definition yet:
sub later; # forward declaration
exists &later; # 1
defined &later; # "" (no body yet)
sub later { 42 }
defined &later; # 1
Nested structure — the safe way. Check each level before descending, because the arrow-chain form has a side effect (see Edge cases):
if (exists $tree{users}
&& exists $tree{users}{$id}
&& exists $tree{users}{$id}{email}) {
send_mail($tree{users}{$id}{email});
}
Edge cases#
Autovivification of intermediate levels. This is the single most important pitfall.
exists $ref->{A}{B}{C}tests the innermost key, but evaluating the expression autovivifies every intermediate hash —$ref->{A}and$ref->{A}{B}spring into existence as empty hashes even when theexiststest returns false:my %h; exists $h{a}{b}{c}; # returns "" (false) exists $h{a}; # now returns 1 — $h{a} was created! exists $h{a}{b}; # likewise — now an empty hash
The innermost element is the only one that does not autovivify. The same happens through references:
exists $ref->{A}on an undef$refvivifies$refinto a hash reference. If you need to probe a deep structure without mutating it, walk it one level at a time withexistsat each step, or use a dedicated helper like [Data::Diver] semantics (a chainedeval/no autovivificationpragma scope).existson a key with valueundefis true. This is the defining difference fromdefined.deleteremoves both the key and the value; assigningundefkeeps the key.Array bounds.
exists $a[$i]is false when$iis past the end of the array or when the slot has beendeleted mid-array. Negative indices count from the end:exists $a[-1]tests the last element if the array is non-empty.Array
existsis discouraged upstream. The notion of deleting an array element is not conceptually clean —delete $a[1]leaves a hole rather than shifting. Most code that reaches forexists $a[$i]is better served by a bounds check ($i <= $#a) or by using a hash.exists &sub()is a syntax error. The argument must name a subroutine, not call one.exists &subasks “issubdeclared?”;exists &sub()would mean “does the return value of callingsubexist?”, which is meaningless.AUTOLOADdoes not count.exists &subis false for a sub that would spring into existence viaAUTOLOADon first call. A failingexiststherefore does not guarantee a call would fail.Tied variables. For tied hashes and arrays,
existscalls theEXISTSmethod on the tied object. The tie implementation decides what “existing” means — aDBMtie checks the on-disk record, a lazy tie might materialise the entry. Seeperltie.The argument must be an lvalue expression whose final operation is a key or index lookup, or a subroutine name.
exists func(),exists $scalar,exists @array,exists %hashare all errors. Only element access and&subare accepted.
Differences from upstream#
Fully compatible with upstream Perl 5.42.
See also#
defined— asks whether the value is usable, not whether the key is present; differs fromexistsonly when the stored value isundefdelete— removes an entry so thatexistson it becomes false; the counterpart toexistseach— iterates key/value pairs of a hash; only visits keys for whichexistsis truekeys— returns the list of existing keys;exists $h{$k}is equivalent to asking whether$kis amongkeys %h, but O(1) instead of O(n)ref— classifies what a reference points to; useful beforeexistson$ref->{...}if you are not sure$refis a hash referencescalar— force scalar context; note thatexistsis already scalar-only and does not need it