Sign In/My Account | View Cart  
advertisement


Listen Print

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.

Pages: 1, 2, 3, 4

Next Pagearrow