5.2 Parameters

     

One of the most significant additions to subroutines in Perl 6 is named formal parameters. The parameter list, often called the signature of the subroutine, is part of the subroutine declaration:

 sub standardize ($text, $method) {     my $clean;     given $method {         when 'length' { $clean = wrap($text, 72); }         when 'lower'  { $clean = lowercase($text); }          . . .      }     return $clean; } 

The subroutine standardize has two scalar parameters, $text and $method , so it is called with two arguments, each a scalar value. The parameters are lexical variables within the body of the sub. They never need to be explicitly declared as my , even under use strict because they're declared by the subroutine declaration.

In a sub with no parameter list, all arguments are passed in the @_ array:

 sub sum {     my $sum;     for @_ -> $number {         $sum += $number;     }     return $sum; } 

Subroutines with defined parameter lists don't get an @_ array. [2] If you want a subroutine that takes no arguments (and complains when arguments are passed), define it with an empty parameter list ( ) .

[2] In fact, a simple subroutine without a signature actually has an implicit signature of *@_ . See Section 5.2.3 later in this chapter.

Subroutine calls normally provide a nonflattening list context, which means that any array or hash passed into a subroutine is treated as a single argument. An array parameter in the signature expects to be passed an actual array or arrayref argument, and a hash parameter expects a hash or hashref argument:

 sub whole (@names, %flags) {      . . .  } whole(@array, %hash); 

5.2.1 Optional Parameters

Every subroutine call checks its signature to make sure the arguments it gets match the declared parameter list. A mismatch in the number or kind of arguments is an error. But since requiring every declared parameter to be passed in on every call isn't nearly flexible enough for the average programmer, Perl 6 also allows optional parameters. Each optional parameter is marked with a ? before the parameter name :

 sub someopt ($required1, $required2, ?$optional1, ?$optional2) {      . . .  } 

So, someopt will accept anywhere from two to four arguments. You can have any number of required and optional parameters, but all the required parameters must come before the first optional parameter. This is largely a common sense restriction. If you want to leave some elements off a list of arguments, it has to be the ones at the end, because positional arguments are bound to the parameters in strict linear order. All these calls to someopt are fine:

 someopt('req1', 'req2', 'opt1', 'opt2'); someopt('req1', 'req2', 'opt1'); someopt('req1', 'req2'); 

5.2.2 Named Parameters

Any argument can be passed either by position with an ordered list of arguments, or by name with an unordered list of pairs. (See Section 5.3.1 later in this chapter for more details.) Sometimes you'll want to specify that certain parameters will be passed only by name, never by position. Named parameters are marked with a + before the parameter name:

 sub namedparams ($first, +$second, +$third) {      . . .  } namedparams(1, second => 2, third => 3); 

Named parameters are always optional. They must come after all positional parameters ”that is, after the unmarked required parameters and the optional parameters marked with a ? . Again, this is largely a matter of common sense. Though named parameters are completely ignored when binding a list of positional arguments, the parser and the person maintaining your code will both be profoundly grateful they don't have to sort through a mixed bag of positional and named parameters to find the positional parameter list.

5.2.3 Variadic Parameters

Another element of flexibility Perl developers will expect is the ability to pull a list of arguments into an array or hash parameter. These are known as variadic parameters because they can take a variable number of arguments. In Perl 6, an array parameter with a * before the parameter name will slurp up all the positional arguments that haven't already been bound to another positional parameter. [3] So, the following call to transport binds $ arthur to @names[0] , and $ford to @names[1] :

[3] You may notice that this is the same symbol as the flattening/ slurping operator from Section 4.2.12 in Chapter 4.

 sub transport ($planet, *@names) {      . . .  } transport('Magrathea', $arthur, $ford); 

If the variadic array parameter is the only positional parameter in the signature, it will take all the positional arguments:

 sub simple (*@_) { . . . } # is the same as sub simple { . . . } 

A hash parameter with a * before the name will slurp up all the named arguments that haven't already been bound to another parameter. So, the following call to transport binds the value of the pair argument with the key ' planet ' to the parameter $planet , but all the other pairs become part of the %flags hash (more on this in Section 5.3.1 later in this chapter):

 sub transport ($planet, *%flags) { . . . } transport('name'    => 'Arthur',           'luggage' => 'lost',           'planet'  => 'Magrathea',           'towel'   => 'required'); 

When they're combined with other kinds of parameters, variadic parameters must come after all positional parameters in the signature. They can either precede or follow the named parameters.

5.2.4 Typed Parameters

Signature checking is sensitive not only to the number of arguments and the variable type (defined by the $ , @ , % , or & symbol), but also to the value type. (See Section 4.1.8 in Chapter 4 for more details on value and variable types.) The parameter type is defined before the parameter name and before any symbols for optional, named, or variadic parameters:

 sub typedparams (Int $first, Str ?$second) { . . . } 

The parameter type declares the type of argument that can be bound to it. The parameter and argument types have to be compatible, but not identical.

Type checking happens at compile time whenever possible, because it's faster and allows for optimizations. Otherwise, type checking happens at run time. So, if all the arguments passed to the subroutine are explicitly typed, the types will be checked at compile time. If the arguments aren't explicitly typed, the run-time checks will make sure the scalars contain an integer value and a string value.

5.2.5 Properties on Parameters

By default, parameters are aliases to the original arguments ( pass-by-reference ), but they're marked as constant so they cannot be modified within the body of the subroutine. The is rw property marks a parameter as modifiable, so changes to the parameter within the body of the sub modify the original variable passed in:

 sub modifyparams ($first is rw, $second is rw) { . . . } 

The is copy property marks a parameter as pass- by-value , so the parameter is a lexically scoped copy of the original value passed in:

 sub passbyvalue ($first is copy, $second is copy) { . . . } 

5.2.6 Default Values for Parameters

Sometimes it is useful to be able to define a default value for an optional or named parameter. The = operator marks the default value. [4] The parameter takes the default value only if the call doesn't pass an argument for that parameter.

[4] This isn't an assignment; it's only a reuse of the = symbol in a different context.

 sub default_vals ($required, ?$optional = 5) { . . . } 

5.2.7 Placeholder Variables

Placeholder variables are a simple alternative to formal parameter lists. They have many of the advantages of ordinary parameters, without the inconvenience of declaring a signature. You just use variables with a caret after the sigil ” $^name , @^name , %^name , or &^name ”within the subroutine's block, and the arguments passed into the subroutine are bound to them.

 @sorted = sort { $^a <=> $^b } @array; 

The order of the parameters is determined by the Unicode sorting order of the placeholders' names, so the following example acts as if it has a formal parameter list of ($^milk, $^sugar, $^tealeaves) :

 $make_tea = {     my $tea = boil $^tealeaves;     combine $tea, $^sugar, $^milk;     return $tea; } 

Placeholders are handy in short subroutines and bare blocks, but soon become unwieldy in anything more complicated.

5.2.8 Return Values

In addition to a signature for the incoming parameters to a subroutine, you can also declare a partial signature, or siglet , for the values returned from a subroutine. Return siglets declare the type of each return value, but they don't bind a named variable to the returned value and can't define a default value for the return. In the declaration, the return signature goes before the sub keyword or after the parameter list attached with the returns keyword.

 sub get_value (Int $incoming) returns Int { . . . } # same as Int sub get_value (Int $incoming) { . . . } 

Both syntaxes have exactly the same effect, but using the returns keyword is usually clearer when the sub has multiple return values:

 sub get_values (Str $incoming) returns (Int, Str) { . . . } 



Perl 6 and Parrot Essentials
Perl 6 and Parrot Essentials, Second Edition
ISBN: 059600737X
EAN: 2147483647
Year: 2003
Pages: 116

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net