Perl experiments with named parameters in signatures
Perl 5.43.5 lets signatures bind name/value pairs to declared lexical parameters. Defaults, unknown-name handling, and positional ordering define the new experiment's contract.
A name/value calling convention is easy to write as a list, but a list alone does not declare which names a function accepts. Perl 5.43.5 brings that declaration into subroutine signatures. Named parameters bind caller-supplied pairs to lexical variables, with required values and defaults expressed where the function is defined.
The development release notes introduce the experiment and identify PPC0024 as its specification. The history records date the release to November 20. This is an experimental extension to signatures, not a statement that every existing signature or name/value API has changed.
I find this direction useful for Perl code whose calls have grown beyond a couple of obvious arguments. The names can make a call understandable without requiring a reader to memorize positions. Putting the accepted names into the signature also gives the interpreter something concrete to check.
A colon marks the parameter declaration
The versioned subroutine documentation describes a named parameter as a scalar variable prefixed with a colon in the signature. The colon is not part of the variable's name inside the function. Callers supply the name without the scalar sigil, paired with its value.
Order does not determine which named variable receives which value. The name does. That allows two calls with their pairs in different orders to bind the same values. The calling form remains a list of pairs, so names can come from literal strings, variables, or an expanded hash.
The following example uses the development interpreter's experimental signature extension.
use v5.42;
no warnings 'experimental::signature_named_parameters';
sub label ($text, :$prefix = "info") {
return "$prefix $text";
}
say label("ready", prefix => "status");
The positional argument fills $text, and the named pair fills $prefix. Omitting the pair uses the default. The warning category names this particular experiment, separately from the status of ordinary signatures. Running the example requires the development implementation even though its baseline declaration uses the preceding stable language version.
Defaults do not make the positional boundary disappear
Named parameters must follow positional parameters in the declaration. Once a signature declares a named parameter, it cannot declare another positional parameter after it. This establishes a boundary in both the signature and the caller's argument list.
The documentation makes an important rule explicit for mixed signatures. Callers must provide values for all positional parameters before supplying named pairs, even when those positional parameters have defaults. A named pair does not instruct the binder to skip unfilled positional slots automatically.
That prevents an ambiguous interpretation of a string followed by another value. The same two list elements could otherwise look like positional values or a name/value pair. The declared boundary provides the interpretation, while the caller supplies enough positional arguments to reach it.
There is another restriction when optional positional parameters exist. All named parameters must then be optional too. Without optional positional parameters, required and optional named parameters can be mixed. The rule reflects the interaction between the two binding mechanisms rather than a general prohibition on required named arguments.
A default belongs to the binding operation
A named parameter without a default is mandatory. Omitting it raises an exception. A defaulting expression supplies the value when the corresponding condition for the default holds, with =, //=, and ||= retaining the documented semantics used by positional parameters.
The defaults execute from left to right as needed. A default can refer to earlier parameters that already have values. This means the signature describes an ordered binding process, even though callers can rearrange their named pairs. Caller pair order and default-expression order are different concerns.
That distinction helps when a default depends on another option. Reading the signature shows which earlier values are available. Rearranging the call's name/value pairs does not rearrange the default evaluation process described by the function definition.
Unknown names can fail or be collected
Without a slurpy parameter, a name that does not match a declaration causes an exception. That gives a misspelled argument name a defined failure behavior. It is a useful change from an interface that silently leaves an unrecognized option unused.
A final slurpy array or hash changes the contract. Unrecognized names and values are collected there. Recognized pairs still bind their declared parameters, while the remainder becomes available through the collection. This allows an API to accept additional options deliberately without making that behavior implicit for every signature.
The slurpy parameter must come last and cannot have a default. Choosing one therefore documents a broader acceptance rule in the declaration itself. It is a different interface decision from enumerating a closed set of named parameters.
My interest is strongest in the closed form for functions with a defined option set. A misspelled name should be distinguishable from an omitted optional value. The experiment lets a signature state that distinction, while retaining an explicit collection form for APIs that need to accept additional pairs.
Named signature parameters remain experimental in this release. Their documented behavior includes lexical binding and exceptions for missing required or unrecognized names. Those rules give the experiment substance beyond a new spelling for a hash of options, because the declaration itself now defines how the argument list becomes local parameter values.