Portrait of Michael Limberger

Michael Limberger

Need me? Email mike@limberger.ca

Perl

Self-modifying loops

A countdown with no for, no while

2025-12-07

This note continues the self-modifying loop thread. Same territory as the earlier talk notes: useful when you want to see the machinery, not just the tidy answer.

You are welcome if you can read a few lines of Perl, or if you are willing to pause on a glyph and ask what it does. This is not a pattern for work code. It is the language handing you a chainsaw.

#!/usr/bin/env perl
use feature qw|say|;

$_ = <<'EOF';
10;
s~(\d+)(?{ say qq($1) })~$1-1~e;
sleep 1;
$1 ? eval : say q(Countdown complete!);
EOF

eval;

Run it. It counts from 10 to 1. No for. No while. A heredoc that eats itself.

Stuffing code into a string

A variable is a named box. $_ is Perl's default box. The $ on the front is the sigil: it says this box holds one value.

A heredoc is a quoted block that runs until a marker, here EOF. Single quotes around the marker mean no interpolation yet. The text is just text. It happens to be valid Perl. Then we run it.

A number sitting there

10;

In Perl a bare number is a valid statement. It evaluates to itself and does nothing. It is sitting in the string so a regex can find it.

The substitution that eats itself

s~(\d+)(?{ say qq($1) })~$1-1~e;

s~~~ is substitution. The ~ is just the delimiter, the same job / usually has.

(\d+)Capture digits into $1.
(?{ ... })Embedded code. Runs during the match.
say qq($1)Print the captured number.
$1-1Replacement: the number minus one.
eEvaluate that replacement as Perl.

After one pass, the string "10;..." becomes "9;...". The program is rewriting itself.

When to stop

$1 ? eval : say q(Countdown complete!);

A ternary is a one-line if. If $1 is truthy, eval runs the string again. When the number hits zero, Perl treats it as false, and the goodbye prints.

You would not ship this. It shows code as data, data as code, and a regex that runs Perl. The useful neighbour is knowing those pieces exist. Keep the chainsaw for golf.