Control Flow & Operators

Perl Fundamentals — Control Flow & Operators
Perl Fundamentals
Course 1 · Chapter 5 · Control Flow & Operators

🔀 Control Flow & Operators

Perl's control flow will look familiar coming from almost any C-family language — but two things are genuinely distinctive: postfix conditionals, which show up constantly in real Perl code, and a comparison-operator system that's split cleanly in two depending on whether you're comparing numbers or strings.

🔷 if / elsif / else

if ($age < 13) { say "child"; } elsif ($age < 20) { say "teenager"; } else { say "adult"; }

One firm Perl rule worth knowing up front: curly braces are always required, even for a single-statement body — unlike C or JavaScript, there's no bare if (x) doSomething(); form. This isn't a style choice; leaving the braces off is a syntax error.

🚫 unless — Perl's "if not"

unless ($is_valid) { say "Invalid input"; } # equivalent to: if (!$is_valid) { ... }

unless reads naturally for a genuinely negative condition. It's best kept simple, though — unless (...) { ... } else { ... } compiles fine but reads confusingly ("unless X, do this, else do that" inverts twice in your head); reach for a plain if/else the moment an else branch enters the picture.

➡️ Postfix Conditionals — a Distinctive Perl Style

say "Warning: low stock" if $stock < 5; return unless $is_valid; $total += $price if $in_stock;

Attaching if/unless to the end of a simple statement is genuinely idiomatic Perl — you'll see this constantly in real production code, not just as a trick. It reads almost like natural English ("return unless valid"), and for a single guarded statement it's usually clearer than a full multi-line block just to wrap one line.

⚖️ Comparison Operators — Numeric vs. String

This is a real, distinctive Perl design decision: numeric and string comparisons use entirely separate sets of operators.

ComparisonNumericString
Equal==eq
Not equal!=ne
Less than<lt
Greater than>gt
Less/equal<=le
Greater/equal>=ge
say "10" == "10.0" ? "equal" : "not equal"; # equal — compared NUMERICALLY, 10 == 10.0 say "10" eq "10.0" ? "equal" : "not equal"; # not equal — compared as STRINGS, "10" != "10.0"
⚠ Using == on Non-Numeric Strings Compares 0 == 0

Because == always forces both sides into numeric context (Chapter 2's string-number duality), comparing two genuinely non-numeric strings with == converts both to 0 first — "apple" == "banana" is true, since both sides become 0, and (with use warnings active) you'll see an isn't numeric warning pointing at the mistake. Use eq for comparing text, always — reaching for == out of habit from another language is one of the most common early Perl bugs.

🔁 Loops — while, until, for, foreach

my $i = 0; while ($i < 5) { say $i; $i++; } until ($i == 0) { # until = "while not" — loops while the condition is FALSE $i--; } for (my $j = 0; $j < 5; $j++) { # classic C-style for say $j; } foreach my $fruit (@fruits) { # from Chapter 3 say $fruit; }

Loop control works the same way inside any of these: last exits the loop entirely (like break elsewhere), next skips to the next iteration (like continue), and the rarely-needed redo restarts the current iteration from the top without re-checking the condition.

🔗 Logical Operators — Two Sets, Different Precedence

MeaningHigh precedence (C-style)Low precedence (English)
AND&&and
OR||or
NOT!not
open(my $fh, '<', $filename) or die "Can't open $filename: $!";

This is a genuinely common Perl idiom, and it's precisely why the low-precedence or exists rather than being redundant with ||: or's low precedence means the whole open(...) call binds tighter than the or, so this line reads as "(try to open the file) or (die with this message)" — using || here instead can bind more tightly than intended around the assignment inside open's arguments, a real gotcha in exactly this pattern. As a rule of thumb: use &&/|| inside expressions and conditions; reach for and/or for this control-flow-like "do this or bail out" idiom.

🔧 A Worked Example

my $username = "ada99"; my $age = 28; say "Username too short" unless length($username) >= 3; say "Adult" if $age >= 18; say "Name check passed" if $username eq "ada99"; # eq — a string comparison

Comparison Operators: Perl vs. Python/JavaScript

Python and JavaScript use one == (or ===) for everything, letting the runtime figure out whether it's comparing numbers or strings. Perl deliberately splits this into two explicit operator sets — more to type, but it means the comparison you write always says exactly what kind of comparison you meant, rather than relying on implicit type coercion to guess correctly. The trade-off Perl makes: explicitness over brevity, and a real trap (the warn-box above) for anyone who forgets which set to reach for.

if / unless

Braces always required; unless reads well alone, awkwardly with else.

Postfix conditionals

statement if condition; — genuinely idiomatic, common in real code.

== vs eq

Numeric and string comparisons use entirely separate operators.

&&/|| vs and/or

Same meaning, different precedence — or for the "do this or die" idiom.

💻 Coding Challenges

Challenge 1: Postfix Conditionals

Given a scalar $temperature, use postfix conditionals (no full if blocks) to print "Freezing" if it's at or below 0, and "Hot" if it's at or above 30.

→ Solution

Challenge 2: Numeric vs String Comparison

Given my $a = "07"; my $b = "7";, write one comparison using == and one using eq, print both results, and explain in one sentence why they disagree.

→ Solution

Challenge 3: The open-or-die Idiom

Write a line attempting to open a file that doesn't exist, using the open(...) or die "..."; idiom from this chapter, and explain in one sentence why or is used here instead of ||.

→ Solution

🎯 What's Next

Next chapter: Regular Expressions in Perlm//, s///, tr///, and capture groups, contrasted directly with the site's own regex1 course.