6.2 Anonymous Subroutines

In that last example, subroutines such as professor_greets( ) were never called explicitly, but indirectly through the coderef. Thus, you wasted some brain cells to come up with a name for the subroutine used only in one other place, to initialize the data structure.

But as you can have anonymous hashes and arrays, you can have anonymous subroutines!

Let's add another island inhabitant: Ginger. But rather than define her greeting behavior as a named subroutine, create an anonymous subroutine:

my $ginger = sub {
  my $person = shift;
  print "Ginger: (in a sultry voice) Well hello, $person!\n";
};
$ginger->("Skipper");

An anonymous subroutine looks like:

sub { ... body of subroutine ... }

The value in $ginger is a coderef, just as if you had defined the following block as a subroutine and then taken a reference to it. When you reach the last statement, you see:

Ginger: (in a sultry voice) Well hello, Skipper!

Although you kept the value in a scalar variable, you could have put that sub { ... } construct directly into the initialization of the greetings hash:

my %greets = (

  "Skipper" => sub {
    my $person = shift;
    print "Skipper: Hey there, $person!\n";
  },

  "Gilligan" => sub {
    my $person = shift;
    if ($person eq "Skipper") {
      print "Gilligan: Sir, yes, sir, $person!\n";
    } else {
      print "Gilligan: Hi, $person!\n";
    }
  },

  "Professor" => sub {
    my $person = shift;
    print "Professor: By my calculations, you must be $person!\n";
  },

  "Ginger" => sub {
    my $person = shift;
    print "Ginger: (in a sultry voice) Well hello, $person!\n";
  },

);

my @room; # initially empty
for my $person (qw(Gilligan Skipper Professor Ginger)) {
  print "\n";
  print "$person walks into the room.\n";
  for my $room_person (@room) {
    $greets{$person}->($room_person); # speaks
    $greets{$room_person}->($person); # gets reply
  }
  push @room, $person; # come in, get comfy
}

Notice how much it simplifies the code. The subroutine definitions are right within the only data structure that references them directly. The result is straightforward:

Gilligan walks into the room.

Skipper walks into the room.
Skipper: Hey there, Gilligan!
Gilligan: Sir, yes, sir, Skipper!

Professor walks into the room.
Professor: By my calculations, you must be Gilligan!
Gilligan: Hi, Professor!
Professor: By my calculations, you must be Skipper!
Skipper: Hey there, Professor!

Ginger walks into the room.
Ginger: (in a sultry voice) Well hello, Gilligan!
Gilligan: Hi, Ginger!
Ginger: (in a sultry voice) Well hello, Skipper!
Skipper: Hey there, Ginger!
Ginger: (in a sultry voice) Well hello, Professor!
Professor: By my calculations, you must be Ginger!

Adding a few more castaways is as simple as putting the entry for the greeting behavior into the hash and adding them into the list of people entering the room. You get this scaling of effort because you've preserved the behavior as data over which you can iterate and look up, thanks to your friendly subroutine references.