Synopsis 6
by Damian Conway, Allison Randal
|
Pages: 1, 2, 3, 4
Editor's note: this document is out of date and remains here for historic interest. See Synopsis 6 for the current design information.
Required Parameters
Required parameters are specified at the start of a subroutine's parameter list:
sub numcmp ($x, $y) { return $x <=> $y }
The corresponding arguments are evaluated in scalar context and may be
passed positionally or by name. To pass an argument by name,
specify it as a pair: parameter_name => argument_value.
$comparison = numcmp(2,7);
$comparison = numcmp(x=>2, y=>7);
$comparison = numcmp(y=>7, x=>2);
Passing the wrong number of required arguments is a fatal error.
The number of required parameters a subroutine has can be determined by
calling its .arity method:
$args_required = &foo.arity;
Optional Parameters
Optional positional parameters are specified after all the required
parameters and each is marked with a ? before the parameter:
sub my_substr ($str, ?$from, ?$len) {...}
The = sign introduces a default value:
sub my_substr ($str, ?$from = 0, ?$len = Inf) {...}
Default values can be calculated at run-time. They can even use the values of preceding parameters:
sub xml_tag ($tag, ?$endtag = matching_tag($tag) ) {...}
Arguments that correspond to optional parameters are evaluated in scalar context. They can be omitted, passed positionally, or passed by name:
my_substr("foobar"); # $from is 0, $len is infinite
my_substr("foobar",1); # $from is 1, $len is infinite
my_substr("foobar",1,3); # $from is 1, $len is 3
my_substr("foobar",len=>3); # $from is 0, $len is 3
Missing optional arguments default to their default value, or to undef
if they have no default.
Named Parameters
Named parameters follow any required or optional parameters in the
signature. They are marked by a + before the parameter.
sub formalize($text, +$case, +$justify) {...}
Arguments that correspond to named parameters are evaluated in scalar context. They can only be passed by name, so it doesn't matter what order you pass them in, so long as they follow any positional arguments:
$formal = formalize($title, case=>'upper');
$formal = formalize($title, justify=>'left');
$formal = formalize($title, justify=>'right', case=>'title');
Named parameters are always optional. Default values for named
parameters are defined in the same way as for optional parameters. Named
parameters default to undef if they have no default.
List Parameters
List parameters capture a variable length list of data. They're used
in subroutines like print, where the number of arguments needs to be
flexible. They're also called "variadic parameters," because they take a
variable number of arguments.
Variadic parameters follow any required or optional parameters. They are
marked by a * before the parameter:
sub duplicate($n, *@data, *%flag) {...}
Named variadic arguments are bound to the variadic hash (*%flag
in the above example). Such arguments are evaluated in scalar context.
Any remaining variadic arguments at the end of the argument list
are bound to the variadic array (*@data above) and are evaluated
in list context.
For example:
duplicate(3, reverse=>1, collate=>0, 2, 3, 5, 7, 11, 14);
# The @data parameter receives [2, 3, 5, 7, 11, 14]
# The %flag parameter receives { reverse=>1, collate=>0 }
Variadic scalar parameters capture what would otherwise be the first elements of the variadic array:
sub head(*$head, *@tail) { return $head }
sub neck(*$head, *$neck, *@tail) { return $neck }
sub tail(*$head, *@tail) { return @tail }
head(1, 2, 3, 4, 5); # $head parameter receives 1
# @tail parameter receives [2, 3, 4, 5]
neck(1, 2, 3, 4, 5); # $head parameter receives 1
# $neck parameter receives 2
# @tail parameter receives [3, 4, 5]
Variadic scalars still impose list context on their arguments.
Variadic parameters are treated lazily -- the list is only flattened into an array when individual elements are actually accessed:
@fromtwo = tail(1..Inf); # @fromtwo contains a lazy [2..Inf]
Flattening Argument Lists
The unary prefix operator * flattens its operand (which allows the
elements of an array to be used as an argument list). The * operator
also causes its operand -- and any subsequent arguments in the argument
list -- to be evaluated in list context.
sub foo($x, $y, $z) {...} # expects three scalars
@onetothree = 1..3; # array stores three scalars
foo(1,2,3); # okay: three args found
foo(@onetothree); # error: only one arg
foo(*@onetothree); # okay: @onetothree flattened to three args
The * operator flattens lazily -- the array is only flattened if
flattening is actually required within the subroutine. To flatten before
the list is even passed into the subroutine, use the unary prefix **
operator:
foo(**@onetothree); # array flattened before &foo called
Pipe Operators
The variadic array of a subroutine call can be passed in separately
from the normal argument list, by using either of the "pipe" operators:
<== or ==>.
Each operator expects to find a call to a variadic subroutine on its "sharp" end, and a list of values on its "blunt" end:
grep { $_ % 2 } <== @data;
@data ==> grep { $_ % 2 };
First, it flattens the list of values on the blunt side. Then, it binds
that flattened list to the variadic parameter(s) of the subroutine on
the sharp side. So both of the calls above are equivalent to:
grep { $_ % 2 } *@data;
Leftward pipes are a convenient way of explicitly indicating the typical right-to-left flow of data through a chain of operations:
@oddsquares = map { $_**2 } sort grep { $_ % 2 } @nums;
# more clearly written as...
@oddsquares = map { $_**2 } <== sort <== grep { $_ % 2 } <== @nums;
Rightward pipes are a convenient way of reversing the normal data flow in a chain of operations, to make it read left-to-right:
@oddsquares =
@nums ==> grep { $_ % 2 } ==> sort ==> map { $_**2 };
If the operand on the sharp end of a pipe is not a call to a variadic operation, then it must be a variable, in which case the list operand is assigned to the variable. This special case allows for "pure" processing chains:
@oddsquares <== map { $_**2 } <== sort <== grep { $_ % 2 } <== @nums;
@nums ==> grep { $_ % 2 } ==> sort ==> map { $_**2 } ==> @oddsquares;
Closure Parameters
Parameters declared with the & sigil take blocks, closures, or
subroutines as their arguments. Closure parameters can be required,
optional, or named.
sub limited_grep (Int $count, &block, *@list) {...}
# and later...
@first_three = limited_grep 3 {$_<10} @data;
Within the subroutine, the closure parameter can be used like any other lexically scoped subroutine:
sub limited_grep (Int $count, &block, *@list) {
...
if block($nextelem) {...}
...
}
The closure parameter can have its own signature (from which the parameter names may be omitted):
sub limited_Dog_grep ($count, &block(Dog), Dog *@list) {...}
and even a return type:
sub limited_Dog_grep ($count, &block(Dog) returns Bool, Dog *@list) {...}
When an argument is passed to a closure parameter that has this kind of
signature, the argument must be a Code object with a compatible
parameter list and return type.
Unpacking Array Parameters
Instead of specifying an array parameter as an array:
sub quicksort (@data, ?$reverse, ?$inplace) {
my $pivot := shift @data;
...
}
it may be broken up into components in the signature, by specifying the parameter as if it were an anonymous array of parameters:
sub quicksort ([$pivot, *@data], ?$reverse, ?$inplace) {
...
}
This subroutine still expects an array as its first argument, just like the first version.

