NAME

Kavorka::Manual::Signatures - experience the lure of the animal

DESCRIPTION

The signature consists of a list of parameters for the function.

Each parameter is a variable name which will be available within the body of the function. Variable names are assumed to be lexicals unless they look like punctuation variables or escape-character global variables, in which case they'll be implicitly localized within the function.

Parameters are separated with commas, however if one of the commas is replaced by a colon, all parameters to the left are assumed to be invocants and are shifted off @_. If no invocants are explicitly listed as part of the signature, the module implementing the keyword may assume a default invocant - for example, method assumes an invocant called $self while around assumes two invocants called ${^NEXT} and $self.

Positional parameters

Parameters which are not explicitly named, slurpy or invocants, are positional. For example:

If you have any named parameters, they will also be made available in the magic global hash %_. If you pass a hashref (rather than a hash) of named parameters, then %_ will be an alias for the referenced hash.

Long name parameters

Named parameters can be given a different name "inside" and "outside" the function:

fun bar ( :public_house($pub) ) { ... }

The function would be called like this:

bar( public_house => "Rose & Crown" );

... But within the function, the variable would be named $pub.

This feature is shared with Perl 6 signatures.

Long named parameters will be available in %_ under their "outside" name, not their "inside" name.

A function can have multiple long names:

fun xxx ( :foo(:bar(:baz($x))) ) { ... }

This unwieldy syntax is borrowed from Perl 6 signatures.

Kavorka provides an experimental shortcut - you may omit the parentheses:

fun xxx ( :foo :bar :baz $x ) { ... }

Global variables

The variables established by Kavorka are normally plain old lexicals (my variables). However, you can instead make them into localised package variables (our variables):

fun xxx ( Int our $x ) { ... }

Variables containing "::", the special globals $_, @_, and %_, and variables named like ${^HELLO} are automatically localized.

(The other special punctuation variables listed in perlvar are not supported.)

Type constraints are parsed as per dwim_type from Type::Utils, which should mostly do what you mean.

Type constraints for slurpy hashes and arrays are applied to each value in the hash or each item in the array. Type constraints for slurpy references are instead applied to the reference as a whole. Therefore the following are roughly equivalent:

Type constraints may be surrounded with parentheses, in which case, instead of parsing them with dwim_type, they'll be evaluated (at compile time) as an expression which is expected to return a blessed Type::Tiny object, or any other value that Types::TypeTiny can coerce to a Type::Tiny object.

Defaults

Kavorka will use the default if the argument is not given when the function is invoked. If an explicit undef is passed to the function when it is called, this is accepted as the value for the parameter, and the default is not used.

If instead you want the default to take effect when an explicit undef is passed to the function, use //=:

fun foo ( $greeting //= "Hello world" ) {
...
}

This feature is shared with Method::Signatures. Kavorka doesn't support Method::Signatures' when keyword.

||= is also supported for setting defaults. It kicks in when any false value (undef, zero, the empty string, or objects overloading boolification to return false) is passed to the function, though this is rarely of much use.

Slurpy parameters may take defaults:

fun foo ( @bar = (1, 2, 3) ) { ... }

For slurpy references, the syntax is a little unintuitive:

fun foo ( slurpy ArrayRef $bar = (1, 2, 3) ) { ... }

Caveat: the following does not work:

fun foo ($x, $y = $x) { ... }

The lexical variable $x has scope in the body of the sub, but not within the signature itself, so it cannot be used as the default value for $y. This can be worked around by making $x a package variable:

This can be used to switch off slow type constraint checks while keeping the original type constraint in the signature to express your intent.

This trait cannot be used in multi subs, where the type check is instrumental in deciding which candidate sub to dispatch to. It can be used in conjunction with the coerce trait, in which case the type constraint will be checked to determine whether coercion is necessary, but no type check will be performed on the result of the coercion.

Return types

After a Unicode rightwards arrow character (→) or the ASCII equivalent (-->), you may list return type constraints.

For a function which takes three values and returns an integer:

fun foo ($a, $b, $c → Int) { ... }

It is possible to include a return type for functions which take no parameters:

fun foo (→ Int) { ... }

For a function which returns a list in list context, you can use the list and scalar traits to specify return types for each context.

fun foo ($a → Int is scalar, ArrayRef[Int] is list) { ... }

Note that the list of returned values is validated as if it were an arrayref (or a hashref if that seems more appropriate).

If no type constraint is provided for list context, then the type constraint is assumed to be an arrayref of whatever type constraint was given for scalar context.

Return types can be coerced:

fun foo ($a → Int does coerce) { ... }

Return types are implemented using Return::Type which adds a wrapper around your function. Although this wrapper should be invisible to caller (thanks to Scope::Upper), it does add some overhead to your function calls, so return types are a feature to use conservatively.

If a return type has the assumed trait, it will not be checked at run time; we just assume the function is doing its job properly and returning an appropriate value. This avoids the overhead of checking return types at run time, but still includes the return type constraint in the introspection API.