Skip to content
VLSI Mentor

Perl Part I · Module 2 · Variables, Scalars, and Data Types

undef and Definedness

A scalar that has been declared but never given a value holds undef, which is Perl's way of saying there is nothing here yet. The chapter's real subject is the distinction between that and zero. In arithmetic they behave identically, both print as very little, and in a report they mean completely different things: one says the measurement was zero, the other says there was no measurement. Perl gives you exactly one tool to tell them apart, defined(), and the habit of reaching for it is what stops a missing field being published as a confident zero.

Foundation12 min readPerlPart IFundamentalsundefCorrectness

Part I · Module 2 · Chapter 2.7 · undef and Definedness

1. A Declared Variable With No Value

Declare a scalar without assigning to it and it holds undef:

Azvya Education Pvt. Ltd.VLSI Mentor
undef-basics.pl
use strict;
use warnings;

my $marks;
my $zero = 0;

print "no marks recorded\n" if !defined $marks;
print "scored zero\n"       if defined $zero && $zero == 0;
Azvya Education Pvt. Ltd.VLSI Mentor
Captured output
no marks recorded
scored zero

Two new pieces here:

  • defined is a built-in that answers one question: does this scalar hold a value at all? It is true for any value, including 0 and the empty string, and false only for undef.
  • && means both conditions must hold. Chapter 3.8 covers the logical operators; it appears here because the second check genuinely needs two parts.

$marks was never assigned, so defined $marks is false and !defined $marks is true. $zero was assigned — the value happens to be 0, and 0 is a value.

2. Absent and Zero Are Not the Same Thing

This is the distinction the whole chapter exists for, and the reason it needs stating is that Perl mostly hides it.

Azvya Education Pvt. Ltd.VLSI Mentor
looks-the-same.pl
use strict;
use warnings;

my $absent;
my $zero = 0;

print "absent + 5 = ", $absent + 5, "\n";
print "zero   + 5 = ", $zero + 5, "\n";
Azvya Education Pvt. Ltd.VLSI Mentor
Captured output — the results
absent + 5 = 5
zero   + 5 = 5
Azvya Education Pvt. Ltd.VLSI Mentor
Captured output — the warning, on STDERR
Use of uninitialized value $absent in addition (+) at looks-the-same.pl line 7.

The arithmetic gave the same answer both times, because undef used as a number is 0 — exactly the behaviour Chapter 2.6 established for a non-numeric value. The only difference between the two lines was a warning.

In the engineering sense, though, they are completely different claims:

  • $zero = 0 says the measurement was taken and it was zero. No errors. Clean run.
  • $absent says no measurement exists. The field was missing, the tool did not report it, the run never got that far.

Publishing the second as the first is the failure. "Zero errors" and "we have no idea how many errors" are not the same sentence, and only one of them should let a run pass.

3. The Three States

A scalar you are handed is in one of three conditions, and they are easy to conflate because two of them are false:

StatedefinedUsed as a numberTreated as true?
undef — no valuefalse0, with a warningno
0 — the number zerotrue0no
"" — the empty stringtrue0, with a warningno

All three behave as 0 in arithmetic and all three are false. defined is the only one of the three columns that separates the first row from the others — which is why a check for "is this value present?" must use defined and not a plain truth test.

Chapter 2.8 covers that last column properly. The row to notice now is the middle one: 0 is a perfectly good value, and any check that treats it as missing data is wrong.

4. The Test That Looks Right and Is Not

The most common mistake in this area is to test the value instead of its definedness:

Azvya Education Pvt. Ltd.VLSI Mentor
wrong-check.pl — this is the mistake
use strict;
use warnings;

my $error_count = 0;          # a real measurement: zero errors

if (!$error_count) {
    print "no error count was reported\n";
}
Azvya Education Pvt. Ltd.VLSI Mentor
Captured output
no error count was reported

That message is false. An error count was reported, and it was the best possible value. The test asked "is this value false?" when the question was "is this value present?", and 0 answers yes to the first.

The correct form asks the right question:

Azvya Education Pvt. Ltd.VLSI Mentor
right-check.pl
use strict;
use warnings;

my $error_count = 0;

if (!defined $error_count) {
    print "no error count was reported\n";
} else {
    print "errors reported: $error_count\n";
}
Azvya Education Pvt. Ltd.VLSI Mentor
Captured output
errors reported: 0

The rule worth memorising: to ask whether a value exists, use defined. To ask whether a value is zero, compare it to zero. Those are different questions and they need different code.

5. Reading the Warning

use warnings reports undef the moment you use it, and the wording changes with the operation — which is a diagnostic, not noise:

Azvya Education Pvt. Ltd.VLSI Mentor
Captured output — undef in arithmetic
Use of uninitialized value $absent in addition (+) at script.pl line 7.
Azvya Education Pvt. Ltd.VLSI Mentor
Captured output — the same undef inside a string
Use of uninitialized value $absent in concatenation (.) or string at script.pl line 8.

Chapter 1.11 set out the procedure: read the variable name, read the operation, then look upstream for where the value should have come from. "Uninitialized" is Perl's word for undef, and the message is telling you that a value you expected to be there was not.

The important follow-up is the one from Chapter 1.11 that bears repeating: this warning does not stop the program and does not change the exit status. The run completes, the report is written, and the only evidence is a line on STDERR.

6. Why This Matters in Engineering Work

A parsing script's single most common real-world failure is a field that is not there.

A tool wrote a shorter line than usual. A section is absent because that analysis did not run. A log was truncated when a job hit its time limit. In every case the script asks for a value and gets undef, converts it to 0, and carries on — and the resulting report says 0 where it should say unknown.

The consequence is worse than a wrong number, because of what 0 means in this domain. Zero errors is the pass condition. A missing error count that silently becomes 0 does not merely corrupt a statistic; it turns an unknown run into a passing one. That is a failure that gets signed off.

The habit is cheap and you can start it now: whenever a value comes from outside your script, ask whether it is defined before you use it, and decide deliberately what its absence means. Sometimes the answer genuinely is "treat it as zero". More often it is "report that it is missing", and the two should never be the same code path. Part II builds the machinery; this chapter builds the reflex.

7. Common Mistakes

Testing truth when you meant presence. if (!$count) is true for a real zero. Use if (!defined $count). This is the mistake in §4 and the one that matters most.

Assuming undef will announce itself. It converts to 0 or to the empty string and carries on. The warning is the only signal, and it goes to STDERR.

Assuming "" is the same as undef. The empty string is a value — defined is true for it. A field that was present but empty is a different situation from a field that was absent, and defined distinguishes them.

Letting a default hide the question. Substituting 0 for a missing value is sometimes right and should always be a decision you made, not a conversion Perl made for you.

Reading "uninitialized" as a Perl problem. It is a statement about your data. Nothing is wrong with Perl; a value you expected was not supplied.

8. What You Should Be Able to Say Now

  1. A declared scalar with no assignment holds undef.
  2. defined is true for every value including 0 and "", and false only for undef.
  3. undef used as a number is 0 and used as text is empty, both with a warning.
  4. 0 is a real value; a check that treats it as missing data is wrong.
  5. To ask whether a value exists use defined; to ask whether it is zero, compare it to zero.
  6. The warning names the operation, which narrows a long line — and it does not stop the program or change the exit status.
  7. In a flow report, a missing error count that becomes 0 turns an unknown run into a passing one.

9. Exercise

Exercise 1 — the three states. Declare three scalars: one unassigned, one holding 0, one holding "". Print defined for each by printing a word of your choosing under a postfix if. Confirm which one is undefined and record all three results.

Exercise 2 — predict, then run. Without running it, say what this prints and how many warnings it produces: my $a; my $b = 0; print $a + $b, "\n"; print "[$a][$b]\n"; Then run it and compare, reading the two warning wordings carefully.

Exercise 3 — fix the wrong check. Take wrong-check.pl from §4 and correct it so that it distinguishes all three cases: no count reported, a count of zero, and a positive count. Verify it with each of the three inputs by editing the assignment.

Exercise 4 — decide the policy. A timing report should contain a slack value for every endpoint. For one endpoint the field is missing entirely. Argue in three or four sentences for what your script should report for that endpoint, and explain why treating it as 0 would be the most dangerous available choice.

10. Summary

  • undef means no value yet — the state of any declared scalar you have not assigned to.
  • defined is the only test for presence. It is true for 0 and for "", and false only for undef.
  • undef converts silently to 0 or to empty, with a warning that changes nothing about the run.
  • 0 is a real measurement, so a truth test is the wrong way to ask whether a value arrived.
  • Presence and value are different questions needing different code.
  • In this domain the conflation is expensive: a missing error count that becomes 0 reads as a pass.

Chapter 2.8 takes the last column of §3's table — what Perl counts as true and false — and finds a trap in it that catches people reading numbers out of files.

Where this fits

Part of the Perl curriculum.