Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why would I use Perl anonymous subroutines instead of a named one?

I'm just curious why one would choose to use an anonymous subroutine, versus a named one, in Perl. Thanks.

like image 316
user102881 Avatar asked May 07 '09 13:05

user102881


People also ask

Why is subroutine important in Perl?

A Perl function or subroutine is a group of statements that together perform a specific task. In every programming language user want to reuse the code. So the user puts the section of code in function or subroutine so that there will be no need to write code again and again.

How do you call and identify a subroutine in Perl?

Define and Call a Subroutinesubroutine_name( list of arguments ); In versions of Perl before 5.0, the syntax for calling subroutines was slightly different as shown below. This still works in the newest versions of Perl, but it is not recommended since it bypasses the subroutine prototypes.

What is used to identify the subroutine in Perl?

The first thing you need to do is create a subroutine. sub keyword is used to define a subroutine in Perl program.


1 Answers

  • You can store anonymous subs in arrays, hashes and scalars.
  • You can build them at runtime
  • You can pass them as arguments to other functions.
  • You get to keep variables in the surrounding scope.

The last point is probably the most important, because it's often the most unexpected facet of named vs. anonymous subroutines in Perl. Example:

sub outer
{
  my $a = 123;

  sub inner
  {
    print $a, "\n";
  }

  # At this point, $a is 123, so this call should always print 123, right?
  inner();

  $a = 456;
}

outer(); # prints 123
outer(); # prints 456! Surprise!

But change "inner" from a named subroutine to a reference to an anonymous subroutine and it works is a much less surprising manner:

sub outer
{
  my $a = 123;

  my $inner = sub
  {
    print $a, "\n";
  };

  # At this point, $a is 123, and since the anonymous subrotine 
  # whose reference is stored in $inner closes over $a in the 
  # "expected" way...
  $inner->();

  $a = 456;
}

# ...we see the "expected" results
outer(); # prints 123
outer(); # prints 123

(Of course, everyone's expectations are different, thus the "scare quotes" around "expected.")

Here's an example use in real code (though it should be noted that the File::Find interface is generally considered to be a poor one—due to its use of global variables, not its use of anonymous subroutines):

sub find_files
{
  my @files;

  my $wanted = sub
  { 
    if($something)
    {
      push @files, $File::Find::name;
    }
  };

  # The find() function called here is imported from File::Find
  find({ wanted => $wanted }, $directory);

  return @files;
}

Passing a named subroutine as the value of the wanted parameter would require polluting the namespace with a routine that may only be used once, and defining a named subroutine within the find_files() subroutine would exhibit the "unexpected" behavior demonstrated earlier.

like image 63
innaM Avatar answered Sep 23 '22 19:09

innaM