
-----------------------------------
wtd
Tue Sep 20, 2005 3:12 pm

[Perl5-tut] Perl Intro: Subroutines and Scope
-----------------------------------
Recap

In the What is a subroutine?

They're Perl's version of functions and procedures; a way to organize executable code that achieves a certain goal and give it a meaningful name.

An easy example

Let's look at a basic subroutine that very simply prints "Hello world" to the console.

sub say_hello {
   print "Hello world\n";
}

Nothing too fancy here.  The "sub" keyword introduces a new subroutine, then we have the name of the subroutine, then a block containing the code for the subroutine.

Calling the subroutine is equally easy.

say_hello;

What about arguments?

What if I want my subroutine to take an argument... the name of a person to greet?

sub say_hello {
   my $name = shift @_;
   print "Hello $name\n";
}

Calling it is pretty easy:

say_hello "Bob";

Okay, there was a lot of new stuff there.  Let's look at it one bit at a time.

The basic form of the subroutine is the same.  Nowhere do I explicitly state what arguments there are.  Instead, any arguments to the subroutine get slurped up into the @_ array.

shift @_

The "shift" subroutine removes the first item from an array and returns it.  Thus...

$name = shift @_;

Assigns the first item in the argument list to the $name variable.

my $name = shift @_;

The "my" keyword indicates that $name is local to the subroutine.  Any $name variable existing outside of the subroutine is unaffected by whatwe do to this $name variable.

"Hello $name\n"

Here we see an example of string interpolation.  The value of the $name variable is inserted directly into the string.  This only works with double-qouted strings, and not single-quoted strings.

The "print" should be easy enough to figure out.

Calling the subroutine can take two different forms.

say_hello "Bob";

Or:

say_hello("Bob");

Parentheses are not required, except to clarify which arguments belong to which subroutine in more complex expressions.

A little tip on arguments:  "shift", if not given an argument, assumes you meant @_, so we can rewrite that subroutine a bit more concisely.

sub say_hello {
   my $name = shift;
   print "Hello $name\n";
}

How did I make it assume, though?

Well, there's nothing forcing us to send a particular list of arguments to a subroutine.  For instance, I could still call my "say_hello" subroutine like:

say_hello;

When I ran it, I'd get a problem, but that's because inside the subroutine $name is undefined, and you can't insert undefined into a string.

That's not what I want.  I want the subroutine to assume a certain value for that argument.

sub say_hello {
   my $name = shift || "John";
   print "Hello $name\n";
}

This says, "shift from @_ or John... whichever works".

-----------------------------------
wtd
Tue Sep 20, 2005 5:47 pm


-----------------------------------
As with variables, it's also possible to have references to subroutines.

sub hello {
   print "Hello\n";
}

$sub_ref = \&hello;

& is the sigil for subroutines.

Dereferencing the subroutine is simple:

&{$sub_ref};

Creating an anonymous subroutine reference is simple as well.

$sub_ref = sub {
   print "Hello\n";
}

&{$sub_ref};
