Functions in Perl
Learn how to define and call subroutines in Perl, including parameters, return values, scope, recursion, closures, and modern signatures with Docker-ready examples
In Perl, functions are called subroutines, defined with the sub keyword. As a multi-paradigm language that borrows heavily from Lisp, Perl treats subroutines as first-class values: you can store them in variables, pass them as arguments, and return them from other subroutines. This makes higher-order programming and closures natural and idiomatic.
Perl’s approach to parameters is famously flexible. Rather than a fixed parameter list, every subroutine receives its arguments flattened into a single special array, @_. You unpack that array however you like—a design that fits Perl’s “There’s more than one way to do it” philosophy. Modern Perl (5.20+) also offers subroutine signatures, a more conventional syntax that became a stable feature in Perl 5.36.
In this tutorial you’ll learn how to define and call subroutines, pass arguments and return values, control variable scope with my/our/local, write recursive subroutines, and use code references and closures for functional-style programming. We’ll finish with the modern signature syntax available in the perl:5.40-slim image.
Defining and Calling Subroutines
The classic way to handle arguments is to unpack @_ at the top of the subroutine. Subroutines can return a single scalar or an entire list, and the defined-or-assignment operator (//=) makes default values easy.
Create a file named functions.pl:
| |
The use strict and use warnings pragmas are standard practice in modern Perl—they catch typos and dubious constructs early. Note how minmax returns a two-element list that the caller unpacks into $min and $max.
Variable Scope
Perl distinguishes between lexical variables (my), package globals (our), and dynamically-scoped temporaries (local). A my variable is visible only within its enclosing block, which is the foundation of well-behaved subroutines.
Create a file named scope.pl:
| |
Because $calls is declared at file scope but outside the subroutine, track can read and modify it on each call—a simple form of persistent state.
Recursion
Subroutines can call themselves. Recursion is a clean way to express problems like factorials and Fibonacci numbers. Perl’s statement modifiers (return 1 if $n <= 1;) keep base cases compact.
Create a file named recursion.pl:
| |
The map block runs fibonacci once for each value in the range 0 .. 9, collecting the results into the @fibs array, which interpolates space-separated inside the double-quoted string.
Higher-Order Functions and Closures
Subroutines are first-class values. An anonymous subroutine (sub { ... }) can be stored in a scalar as a code reference and invoked with the arrow operator (->). A subroutine that returns another subroutine creates a closure, capturing the variables it referenced.
Create a file named higher_order.pl:
| |
Each call to make_counter produces a fresh closure with its own private $count. The built-in map and grep are higher-order functions baked into the language—map transforms every element, while grep filters by a condition.
Modern Subroutine Signatures
Since Perl 5.36, subroutine signatures are a stable, non-experimental feature. They let you declare named parameters directly in the subroutine definition, with optional defaults and a slurpy array for the rest. Enabling use v5.36 also turns on strict, warnings, and say automatically.
Create a file named signatures.pl:
| |
Signatures make subroutine interfaces self-documenting and remove most of the boilerplate of unpacking @_ by hand. They are the recommended style for new Perl code targeting 5.36 or later.
Running with Docker
| |
Expected Output
functions.pl:
Hello from a subroutine!
3 + 4 = 7
Hello, Alice!
Hello, stranger!
min = 1, max = 9
scope.pl:
I am lexical
I am global
Inside block: hidden
Call number 1
Call number 2
Call number 3
recursion.pl:
5! = 120
fib(10) = 55
Sequence: 0 1 1 2 3 5 8 13 21 34
higher_order.pl:
square(6) = 36
apply_twice(square, 2) = 16
Counter: 1
Counter: 2
Counter: 3
Doubled: 2 4 6 8 10 12
Evens: 2 4 6
signatures.pl:
add(10, 5) = 15
Hello, Perl!
Hello, World!
total(1, 2, 3, 4) = 10
Key Concepts
subdefines a subroutine — Perl’s name for a function. Call it with parentheses:name(args).- Arguments flatten into
@_— every subroutine receives its arguments in the special array@_, which you typically unpack withmy ($x, $y) = @_;. - Default values — use the defined-or-assign operator (
//=) with@_, or a$param = defaultclause in a signature. - Return values can be lists — a subroutine can return a single scalar or an entire list, and the caller can unpack it:
my ($min, $max) = minmax(...). myis lexical,ouris package-global — lexical variables are confined to their enclosing block, which keeps subroutines self-contained.- Subroutines are first-class — store an anonymous
sub { ... }in a scalar to create a code reference, invoke it with->, and pass it around like any other value. - Closures capture their environment — a subroutine returned from another subroutine remembers the lexical variables it used, enabling private state.
- Signatures (5.36+) are stable —
sub add ($x, $y) { ... }is the modern, self-documenting alternative to manually unpacking@_.
Comments
Loading comments...
Leave a Comment