NAME

Function::Parameters - subroutine definitions with parameter lists

SYNOPSIS

use Function::Parameters;

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

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

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

# method with implicit $self
method set_name($name) {
  $self->{name} = $name;
}

# method with explicit invocant
method new($class: %init) {
  return bless { %init }, $class;
}

# function with default arguments
fun search($haystack, $needle = qr/^(?!)/, $offset = 0) {
  ...
}

# method with default arguments
method skip($amount = 1) {
  $self->{position} += $amount;
}
use Function::Parameters qw(:strict);

fun greet($x) {
  print "Hello, $x\n";
}

greet "foo", "bar";
# Dies at runtime with "Too many arguments for fun greet"

greet;
# Dies at runtime with "Not enough arguments for fun greet"
# use different keywords
use Function::Parameters {
  proc => 'function',
  meth => 'method',
};

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 it works without source filters.

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 into your scope. To do that you pass a reference to a hash mapping keywords to types in the import list:

use Function::Parameters {
  KEYWORD1 => TYPE1,
  KEYWORD2 => TYPE2,
  ...
};

Or more concretely:

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

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 (keywords) can be any identifiers you want while the values (types) have to be either a hash reference (see below) or 'function', 'method', 'classmethod', 'function_strict', 'method_strict', or 'classmethod_strict'. The main difference between 'function' and 'method' is that 'method's automatically shift their first argument into $self ('classmethod's are similar but shift into $class).

The following shortcuts are available:

use Function::Parameters;
   # is equivalent to #
use Function::Parameters { fun => 'function', method => 'method' };
use Function::Parameters ':strict';
   # is equivalent to #
use Function::Parameters { fun => 'function_strict', method => 'method_strict' };

The following shortcuts are deprecated and may be removed from a future version of this module:

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

That is, if you want to create custom keywords with Function::Parameters, use a hashref, not a list of strings.

You can tune the properties of the generated keywords even more by passing a hashref instead of a string. 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 whose name is specified here.

invocant

Valid values: booleans. This lets users of this keyword specify an explicit invocant, that is, the first parameter may be followed by a : (colon) instead of a comma and will by initialized by shifting the first element off @_.

You can combine shift and invocant, in which case the variable named in shift serves as a default shift target for functions that don't specify an explicit invocant.

attributes, attrs

Valid values: strings that are valid source code for attributes. Any value specified here will be inserted as a subroutine attribute in the generated code. Thus:

use Function::Parameters { sub_l => { attributes => ':lvalue' } };
sub_l foo() {
  ...
}

turns into

sub foo :lvalue {
  ...
}

It is recommended that you use attributes in new code but attrs is also accepted for now.

default_arguments

Valid values: booleans. This property is on by default, so you have to pass default_arguments => 0 to turn it off. If it is disabled, using = in a parameter list causes a syntax error. Otherwise it lets you specify default arguments directly in the parameter list:

fun foo($x, $y = 42, $z = []) {
  ...
}

turns into

sub foo {
  my ($x, $y, $z) = @_;
  $y = 42 if @_ < 2;
  $z = [] if @_ < 3;
  ...
}

You can even refer to previous parameters in the same parameter list:

print fun ($x, $y = $x + 1) { "$x and $y" }->(9);  # "9 and 10"

This also works with the implicit first parameter of methods:

method scale($factor = $self->default_factor) {
  $self->{amount} *= $factor;
}
check_argument_count

Valid values: booleans. This property is off by default. If it is enabled, the generated code will include checks to make sure the number of passed arguments is correct (and otherwise throw an exception via Carp::croak):

fun foo($x, $y = 42, $z = []) {
  ...
}

turns into

sub foo {
  Carp::croak "Not enough arguments for fun foo" if @_ < 1;
  Carp::croak "Too many arguments for fun foo" if @_ > 3;
  my ($x, $y, $z) = @_;
  $y = 42 if @_ < 2;
  $z = [] if @_ < 3;
  ...
}

Plain 'function' is equivalent to:

{
  name => 'optional',
  default_arguments => 1,
  check_argument_count => 0,
}

(These are all default values so 'function' is also equivalent to {}.)

'function_strict' is like 'function' but with check_argument_count => 1.

'method' is equivalent to:

{
  name => 'optional',
  default_arguments => 1,
  check_argument_count => 0,
  attributes => ':method',
  shift => '$self',
  invocant => 1,
}

'method_strict' is like 'method' but with check_argument_count => 1.

'classmethod' is equivalent to:

{
  name => 'optional',
  default_arguments => 1,
  check_argument_count => 0,
  attributes => ':method',
  shift => '$class',
  invocant => 1,
}

'classmethod_strict' is like 'classmethod' but with check_argument_count => 1.

Syntax and generated code

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 the body of 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 function body, 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 while a prototype starts with ().

As an example, the following declaration uses every available feature (subroutine name, parameter list, default arguments, prototype, default attributes, attributes, argument count checks, and implicit $self overriden by an explicit invocant declaration):

method foo($this: $x, $y, $z = sqrt 5)
  :($$$;$)
  :lvalue
  :Banana(2 + 2)
{
  ...
}

And here's what it turns into:

sub foo ($$$;$) :method :lvalue :Banana(2 + 2) {
  sub foo ($$$;$);
  Carp::croak "Not enough arguments for method foo" if @_ < 3;
  Carp::croak "Too many arguments for method foo" if @_ > 4;
  my $this = shift;
  my ($x, $y, $z) = @_;
  $z = sqrt 5 if @_ < 3;
  ...
}

Another example:

my $coderef = fun ($p, $q)
  :(;$$)
  :lvalue
  :Gazebo((>:O)) {
  ...
};

And the generated code:

my $coderef = sub (;$$) :lvalue :Gazebo((>:O)) {
  # vvv   only if check_argument_count is enabled    vvv
  Carp::croak "Not enough arguments for fun (anon)" if @_ < 2;
  Carp::croak "Too many arguments for fun (anon)" if @_ > 2;
  # ^^^                                              ^^^
  my ($p, $q) = @_;
  ...
};

Wrapping Function::Parameters

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(@custom_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.