Perl from the ground up

Subroutines: naming a piece of work

Defining your own named pieces of work, where the arguments arrive, why a subroutine can be called before it is defined, and how one answers with several values.

Part 7 of 12

Intermediate18 min readBack to Courses

Naming a piece of work

A subroutine is declared with sub name { ... } and called by writing its name. Perl reads the whole file before running it, so a call can sit above the line that defines the subroutine: the calls go at the top and the definitions underneath, which is how most Perl programs are arranged.

The word sub is short for subroutine, and a subroutine is what other languages call a function. Arguments are passed without any declaration at all — you simply write them at the call: area(3, 4). Parentheses at the call are the habit worth forming.

Where the arguments arrive

Inside the subroutine, the arguments are the list @_, and the usual first line copies them into named variables: my ($width, $height) = @_;. Reading them off one at a time with shift does the same job — my $width = shift; — and is tidier when the list is long.

Nothing checks how many arguments you passed. Too few leaves one of the names undef, and too many puts the extras in @_ where they are quietly ignored. The check is a line you write if you want it: return unless defined $height;.

Answers

return hands a value back and leaves at once; a subroutine that ends without one answers with the value of its last expression. Returning a list is how one subroutine answers two questions at the same time: return (int($top / $bottom), $top % $bottom); comes back as a list that unpacks into names.

A subroutine does not have to be silent to answer, but returning data and letting the caller print it is the habit worth forming — the same subroutine can then be used by a different report without being rewritten.

The arguments are one flat list

Everything the caller passes arrives in @_, in order, with no names attached. my ($width, $height) = @_; is an ordinary list assignment, which is why the first line of a subroutine looks like the code you already know. shift with no argument takes from @_ inside a subroutine, so my $width = shift; is the same idea one value at a time. The order is the only thing connecting the caller's values to the names inside, so the call and the first line have to agree.

Passing an array or a hash does not keep it together: the list is flattened into @_, so two arrays become one long run of values. When a subroutine really needs a list and a hash, pass references, which the chapter on references introduces. For fixed arguments, the flat list is simple and enough.

Guards make the rest of the body simple

A guard clause checks the arguments at the top and leaves early if they are wrong: return unless @values;. Everything below the guard can then assume the check passed, so the body reads without a layer of nesting. die is the louder version, and it is the right choice when continuing would be a bug rather than an empty answer.

Defaults belong beside the guard: my $name = shift // 'world';. The // keeps a real empty string and replaces only undef. A subroutine can also call itself — recursion — as long as every call moves towards a base case that returns without calling again.

Calling before defining

Because the file is read before it runs, a call may appear above the definition: area(3, 4) at the top of the file finds sub area at the bottom. That is why most Perl programs put the calls first and the definitions underneath, like a table of contents followed by the chapters.

A forward declaration is not needed for an ordinary call, and a prototype is not a type signature — it changes how the arguments are parsed and does not check them.

Three subroutines and the ways they answer

use strict;
use warnings;

sub greet {
  my ($name) = @_;
  return "Hello, $name!";
}
print greet('Ada'), "\n";

# shift reads the arguments off the list one at a time.
sub area {
  my $width = shift;
  my $height = shift;
  return $width * $height;
}
print area(3, 4), "\n";

# Two answers come back as one list.
sub divmod {
  my ($top, $bottom) = @_;
  return (int($top / $bottom), $top % $bottom);
}
my ($whole, $rest) = divmod(17, 5);
print "17 = 5 x $whole plus $rest\n";

# No return at all: the last expression answers.
sub double { $_[0] * 2 }
print double(21), "\n";

A greeting, an area and two answers at once

Run it and check each answer. Then write a subroutine called box that takes a width and a height and returns the perimeter, and call it with two numbers of your own.

Output
Click "Run" to execute your code

The values in the argument list are the caller's own values, so writing to one inside a subroutine changes the variable outside it. Copying them into my names on the first line — the habit this chapter teaches — is what keeps that surprise out of your program.

Three subroutine mistakes are common. Writing $_[0] = ... changes the caller's value, because @_ holds aliases rather than copies. A call with too few arguments leaves a name undef, and nothing stops the body from using it. And a return in a list context returns a list, so my $one = min_max(...) takes the last value, not the first; assign to a list when you expect several.

Try these next

  • Write a max subroutine with a guard for an empty list, and call it with no arguments.
  • Write a repeat subroutine that uses x and a default count, then call it with and without the count.
  • Write a recursive countdown that stops at 1 and returns its numbers as a list.

A guard and two answers

Run it and read both answers. Then call `min_max` with a single value and with no values, remove the guard for a moment, and put it back when you see what changes.

Output
Click "Run" to execute your code

Check what you learned

One question at a time. A wrong answer explains itself — take another go.

Part 1 of 5

Where do the arguments of a subroutine arrive?