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 —
\Xproduces a scalar that points to another value.Context — when a scalar gets one value vs many.
scalar— force scalar context on a list or array.$_— the implicit scalar for many built-ins.