Scalars#

A scalar is the unit value of Perl. It holds one of: a number (integer or float), a string, a reference, or undef. The sigil is $, in every position where the value is a single scalar — including when the value is one element of an array or hash:

$x                # the scalar named x
$arr[0]           # the first element of @arr — also a scalar
$h{key}           # one value from %h — also a scalar

A scalar is not statically typed. The same variable can hold a number now and a string a moment later. Perl converts between the two whenever an operator demands one shape or the other; see numbers and strings.

Truth, definedness, and undef#

Two related but distinct questions about a scalar:

defined $x        # is there any value at all?
$x ? T : F        # is the value true?

A scalar is false in boolean context if it is one of:

undef             # the undefined value
0                 # numeric zero
0.0               # also numeric zero
""                # empty string
"0"               # the literal string "0"

Everything else is true. Note "00", "0.0", "0 but true", and "0E0" are all true — they are non-empty strings that don’t match the literal "0". The last two are common idioms for «this function returned successfully but there was nothing to count»:

sub touch_files {
    my $count = 0;
    $count++ for grep { -e $_ && utime undef, undef, $_ } @_;
    return $count || '0E0';     # true even on zero work, so callers
                                # can write `if (touch_files(...))`
}

defined is the only way to tell undef from the false-but-defined values. A common bug:

if ($cache{$key}) { ... }            # WRONG — false for empty/0/undef
if (exists $cache{$key}) { ... }      # right — pure presence test
if (defined $cache{$key}) { ... }     # right — value-not-undef test

Use defined when the only thing you care about is «is there a value here at all»; exists for «is this key/index in the container» (the two differ for sparse arrays and deleted keys).

Dynamic typing#

A scalar can change shape during execution:

my $x = 42;          # internally an integer
$x = "hello";        # now a string
$x = 3.14;           # now a float
$x = \@items;        # now a reference

Most code never needs to think about which internal shape a scalar currently has. The exceptions are JSON-serialisation libraries that care whether 1 was assigned as a number or a string, and the Scalar::Util introspection helpers (looks_like_number, dualvar).

«Looks like a number»#

When Perl converts a string to a number it stops at the first character that isn’t part of a valid numeric prefix:

"42"        + 1   # 43
"42abc"     + 1   # 43      — leading digits parsed
"abc42"     + 1   # 1       — no leading digits, treated as 0
" 42"       + 1   # 43      — leading whitespace allowed
"4_2"       + 1   # 5       — underscores in literals only, NOT in strings
"0x1F"      + 1   # 1       — hex string is NOT auto-recognised; hex() does

The mismatch between numeric literals (which honour _ and 0x) and numeric strings (which do not) is one of the most reported «why» questions in Perl. Use hex / oct when the input is a string in non-decimal form:

my $bytes = hex "1F";        # 31
my $perms = oct "0755";       # 493
my $perms = oct "0o755";      # 493 — explicit octal prefix
my $bytes = oct "0x1F";       # 31  — oct() accepts any prefix

Under use warnings, an arithmetic operation on a non-numeric string emits Argument «…» isn’t numeric in addition (+). The operation still returns 0 — the warning, not a fatal error, is the signal.

Dual values#

Some scalars carry both a string and a number form simultaneously, chosen by context. The classic example is $!:

$!                # in string context: "Permission denied"
$! + 0            # in numeric context: 13

You can build your own with Scalar::Util::dualvar:

use Scalar::Util qw(dualvar);
my $err = dualvar 13, 'Permission denied';

print "err is $err";           # "err is Permission denied"
print "err is " . ($err + 0);  # "err is 13"

Dual scalars are a niche tool. The common case where one matters is the $! errno; the general escape hatch is the dualvar helper.

«0 but true»#

The literal string "0 but true" is the canonical Perl idiom for «a function whose normal return is a count, but the count is zero and the call succeeded». It is true (non-empty, non-"0") but numerically equals 0:

my $hits = "0 but true";

if ($hits)        { print "succeeded\n"; }    # prints
print $hits + 0;                               # 0
print "got $hits results\n";                   # got 0 but true results

The compiler also recognises "0 but true" specifically and skips the isn’t numeric warning that any other «0 followed by garbage» string would emit.

See also#

  • Numbers and strings — how integer, float, and string forms convert into one another and where the corners are.

  • References\X produces a scalar that points to another value.

  • Context — when a scalar gets one value vs many.

  • defined, undef — test for and produce the undefined value.

  • scalar — force scalar context on a list or array.

  • $_ — the implicit scalar for many built-ins.