NAME

Function::Parameters - subroutine definitions with parameter lists

SYNOPSIS

use Function::Parameters;

fun foo($bar, $baz) {
  return $bar + $baz;
}

fun mymap($fun, @args) :(&@) {
  my @res;
  for (@args) {
    push @res, $fun->($_);
  }
  @res
}

print "$_\n" for mymap { $_ * 2 } 1 .. 4;

method set_name($name) {
  $self->{name} = $name;
}
use Function::Parameters 'proc', 'meth';

my $f = proc ($x) { $x * 2 };
meth get_age() {
  return $self->{age};
}

DESCRIPTION

This module lets you use parameter lists in your subroutines. Thanks to "PL_keyword_plugin" in perlapi it works without source filters.

WARNING: This is my first attempt at writing XS code and I have almost no experience with perl's internals. So while this module might appear to work, it could also conceivably make your programs segfault. Consider this module alpha quality.

Basic stuff

To use this new functionality, you have to use fun instead of sub - sub continues to work as before. The syntax is almost the same as for sub, but after the subroutine name (or directly after fun if you're writing an anonymous sub) you can write a parameter list in parentheses. This list consists of comma-separated variables.

The effect of fun foo($bar, $baz) { is as if you'd written sub foo { my ($bar, $baz) = @_; , i.e. the parameter list is simply copied into my and initialized from @_.

In addition you can use method, which understands the same syntax as fun but automatically creates a $self variable for you. So by writing method foo($bar, $baz) { you get the same effect as sub foo { my $self = shift; my ($bar, $baz) = @_; .

Customizing the generated keywords

You can customize the names of the keywords injected in your package. To do that you pass a hash reference in the import list:

use Function::Parameters { proc => 'function', meth => 'method' }; # -or-
use Function::Parameters { proc => 'function' }; # -or-
use Function::Parameters { meth => 'method' };

The first line creates two keywords, proc and meth (for defining functions and methods, respectively). The last two lines only create one keyword. Generally the hash keys can be any identifiers you want while the values have to be either function, method, or a hash reference (see below). The difference between function and method is that methods automatically shift their first argument into $self.

The following shortcuts are available:

use Function::Parameters;
   # is equivalent to #
use Function::Parameters { fun => 'function', method => 'method' };
use Function::Parameters 'foo';
  # is equivalent to #
use Function::Parameters { 'foo' => 'function' };
use Function::Parameters 'foo', 'bar';
  # is equivalent to #
use Function::Parameters { 'foo' => 'function', 'bar' => 'method' };

You can customize things even more by passing a hashref instead of function or method. This hash can have the following keys:

name

Valid values: optional (default), required (all uses of this keyword must specify a function name), and prohibited (all uses of this keyword must not specify a function name). This means a name => 'prohibited' keyword can only be used for defining anonymous functions.

shift

Valid values: strings that look like a scalar variable. Any function created by this keyword will automatically shift its first argument into a local variable with the name specified here.

Plain function is equivalent to { name => 'optional' }, and plain method is equivalent to { name => 'optional', shift => '$self'}.

Other advanced stuff

Normally, Perl subroutines are not in scope in their own body, meaning the parser doesn't know the name foo or its prototype while processing sub foo ($) { foo $bar[1], $bar[0]; }, parsing it as $bar->foo([1], $bar[0]). Yes. You can add parens to change the interpretation of this code, but foo($bar[1], $bar[0]) will only trigger a foo() called too early to check prototype warning. This module attempts to fix all of this by adding a subroutine declaration before the definition, so the parser knows the name (and possibly prototype) while it processes the body. Thus fun foo($x) :($) { $x } really turns into sub foo ($); sub foo ($) { my ($x) = @_; $x }.

If you need subroutine attributes, you can put them after the parameter list with their usual syntax.

Syntactically, these new parameter lists live in the spot normally occupied by prototypes. However, you can include a prototype by specifying it as the first attribute (this is syntactically unambiguous because normal attributes have to start with a letter).

If you want to wrap Function::Parameters, you just have to call its import method. It always applies to the file that is currently being parsed and its effects are lexical (i.e. it works like warnings or strict);

package Some::Wrapper;
use Function::Parameters ();
sub import {
  Function::Parameters->import;
  # or Function::Parameters->import(@other_import_args);
}

AUTHOR

Lukas Mai, <l.mai at web.de>

COPYRIGHT & LICENSE

Copyright 2010, 2011, 2012 Lukas Mai.

This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License.

See http://dev.perl.org/licenses/ for more information.