Misc

undef#

The undefined value, and the operator that produces it.

undef wears two hats. Bare undef is a value — the canonical undefined scalar, the thing defined returns false for. undef EXPR is a unary operator that undefines its argument in place: the variable, array, hash, subroutine, or typeglob named by EXPR is emptied out and, where possible, its storage is released.

Both forms evaluate to the undefined value.

Synopsis#

undef                  # the undefined value
undef EXPR             # undefine the lvalue EXPR, return undef

EXPR must be an lvalue: a scalar, an array (with @), a hash (with %), a subroutine (with &), or a typeglob (with *).

What you get back#

Always the undefined value. The operator form returns undef after wiping its argument; the value form just hands you undef.

my $x = undef;                      # $x is now undef
return undef if $oops;              # explicit "I mean no value"
my $was = undef $counter;           # $counter wiped, $was is undef

The value vs. the operator#

Bare undef is the undefined scalar. Assigning it to a variable leaves the variable’s storage in place and sets its value to undef:

my @big = (1) x 1_000_000;
$big[0] = undef;                    # slot 0 holds undef; @big still huge
@big    = ();                       # empties the array, keeps the AV
@big    = undef;                    # assigns the ONE-element list (undef)

Note the last line: @big = undef is a list assignment of a one-element list whose only element is undef, so @big ends up with length 1. It is almost never what you want. Use @big = () to empty, or undef @big to empty and release the backing storage.

The operator form does more than assign undef:

undef $scalar;          # scalar: sets value to undef, frees any PV buffer
undef @array;           # array: frees all elements AND the AV's storage
undef %hash;            # hash:  frees all entries AND the HV's buckets
undef ⊂             # sub:   frees the CV body; the name still exists
undef *glob;            # glob:  destroys $glob, @glob, %glob, &glob, etc.

The distinction matters for memory. @array = () leaves the allocated capacity intact so the next push is cheap; undef @array releases it. For a large, one-shot array that you want to truly let go of, use undef. For a working array you will refill, use = ().

Examples#

Returning “no value” from a subroutine. In scalar context this is a clean way to signal failure; in list context undef alone produces a one-element list containing undef, which is truthy:

sub find_user {
    my ($id) = @_;
    return undef unless $id;        # scalar-context caller: false
    ...
}

For subroutines meant to signal failure in both contexts, return an empty list instead — return with no argument does the right thing:

sub find_user {
    my ($id) = @_;
    return unless $id;              # () in list ctx, undef in scalar ctx
    ...
}

Skipping positional values in a list assignment. undef on the left-hand side of a list assignment is a placeholder that throws away the matching value:

my ($x, undef, $z) = foo();         # discard the middle value
my (undef, @rest)  = @_;            # drop the first arg, keep the rest

Classic select idiom for a sub-second sleep — three ignored filehandle sets plus a timeout:

select undef, undef, undef, 0.25;   # sleep 250 ms

Dual-context return:

return wantarray ? (undef, $errmsg) : undef if $they_blew_it;

Releasing a large working set:

my %cache = build_huge_cache();
use_cache(\%cache);
undef %cache;                       # free buckets and entries now

Undefining a subroutine. The name in the symbol table stays, but calling it will complain about an undefined subroutine:

sub greet { print "hi\n" }
undef &greet;
greet();                            # Undefined subroutine &main::greet

Undefining a typeglob nukes every slot at once:

our $xyz = 1;
our @xyz = (1, 2);
our %xyz = (a => 1);
sub xyz { 42 }

undef *xyz;                         # $xyz, @xyz, %xyz, &xyz all gone

Edge cases#

  • undef $hash{$key} is not delete. It sets the value at that key to undef; the key itself still exists and exists still returns true. Use delete $hash{$key} to remove the key. The same applies to array elements: undef $arr[3] leaves index 3 in place with value undef, it does not shorten the array.

  • On tied variables and DBM values, undef $tied{$key} invokes the tie’s STORE, not its DELETE. The perldoc warning (“probably not do what you expect on most predefined variables or DBM list values”) is specifically about this.

  • undef is a unary operator, not a list operator. It takes exactly one argument, so undef $a, $b parses as (undef $a), $b — only $a is undefined. To undefine several variables, call it several times, or use a loop:

    undef $_ for $a, $b, $c;
    
  • undef EXPR requires an lvalue. undef 42 or undef func() is a compile-time error (Can’t modify … in undef operator).

  • Left-hand undef in list assignment is syntax, not a value. (undef, $x) = @pair is parsed specially; you cannot write my $slot = undef; ($slot, $x) = @pair and expect the first value to be discarded — that assigns into $slot.

  • Constant undef in boolean context is false, in numeric context is 0, in string context is "". Under use warnings each of those conversions emits a Use of uninitialized value warning at the point of use, not at the point the variable became undef.

  • undef &sub does not remove the subroutine name from its package stash — only the code. To remove the name as well, undefine the whole glob slot: delete $Package::{sub_name} or undef *Package::sub_name if you also want the sibling slots gone.

Differences from upstream#

Fully compatible with upstream Perl 5.42.

See also#

  • defined — the predicate that asks “is this value not undef?”; the natural counterpart to the undef value

  • delete — remove a hash key or array element entirely; use this, not undef, when you want exists to become false

  • exists — check whether a hash key or array index is present, regardless of whether its value is defined

  • local — temporarily replace a package variable’s value (often with undef) for the duration of a scope

  • wantarray — pairs with undef in the idiomatic wantarray ? (undef, $err) : undef dual-context failure return