class Capture { }
A Capture
is a container for passing arguments to a code object. Captures are the flip-side of Signature
s. Thus, captures are the caller-defined arguments, while signatures are the callee-defined parameters. For example when you call print $a, $b
, the $a, $b
part is a capture.
Captures contain a list-like part for positional arguments and a hash-like part for named arguments, thus behaving as Positional
and Associative
, although it does not actually mix in those roles. Like any other data structure, a stand-alone capture can be created, stored, and used later.
A literal Capture
can be created by prefixing a term with a backslash \
. Commonly, this term will be a List
of terms, from which the forms key => value
and :key<value>
of a Pair
literal will be placed in the named part, and all other terms will be placed in the positional part (including Pair
s of the form 'key' => value
).
my $a = \(42); # Capture with one positional arg my $b = \(1, 2, verbose => True); # Capture with two positional args and one named arg my $c = \(1, 2, :verbose(True)); # same as before my $c = \(1, 2, 'verbose' => True); # Capture with three positional args
To reiterate, named arguments in a capture must be created using one of two ways:
Use an unquoted key naming a parameter, followed by
=>
, followed by the argument. For example,as => by => {1/$_}
.Use a colon-pair literal named after the parameter. For example,
:into(my %leap-years)
.
For example:
sub greet(:$name, :$age) { "$name, $age" } my $d = \(name => 'Mugen', age => 19); # OK my $e = \(:name('Jin'), :age(20)); # OK my $f = \('name' => 'Fuu', 'age' => 15); # Not OK, keys are quoted.
For the greet
subroutine that accepts two named arguments name
and age
, the captures $d
and $e
will work fine while the capture $f
will throw a Too many positionals passed...
error. This is because 'age' => 20
isn't a named argument (as per the two ways of creating one mentioned above) but a positional argument of which greet
expects none. In the context of captures, quoted keys don't create named arguments. Any 'key' => value
is just another positional parameter, thus exercise some caution when creating captures with named arguments.
Once a capture is created, you may use it by prefixing it with a vertical bar |
in a subroutine call, and it will be as if the values in the capture were passed directly to the subroutine as arguments — named arguments will be passed as named arguments and positional arguments will be passed as positional arguments. You may re-use the capture as many times as you want, even with different subroutines.
say greet |$d; # OUTPUT: «Mugen, 19» say greet |$e; # OUTPUT: «Jin, 20»
my $x = \(4, 2, 3, -2); say reverse |$x; # OUTPUT: «(-2 3 2 4)» say sort 5, |$x; # OUTPUT: «(-2 2 3 4 5)» say unique |$x, as => {.abs}; # OUTPUT: «(4 2 3)» say unique |$x, :as({.abs}); # OUTPUT: «(4 2 3)» my $y = \(1, 7, 3, by => {1/$_}); say min |$y; # OUTPUT: «7», same as min 1, 7, 3, by => {1/$_} say max |$y; # OUTPUT: «1», same as max 1, 7, 3, by => {1/$_}
Inside a Signature
, a Capture
may be created by prefixing a sigilless parameter with a vertical bar |
. This packs the remainder of the argument list into that capture parameter.
sub f($a, |c) { say $a; say c; say c.^name; say c.list; # see Methods section say c.hash; # see Methods section } f 1, 2, 3, a => 4, :b(5); # OUTPUT: # 1 # \(2, 3, :a(4), :b(5)) # Capture # (2 3) # Map.new((a => 4, b => 5))
Note that Capture
s are still List
s in that they may contain containers, not just literal values:
my $b = 1; my $c = \(4, 2, $b, 3); say min |$c; # OUTPUT: «1» $b = -5; say min |$c; # OUTPUT: «-5»
Methods§
method list§
method list(Capture:D:)
Returns the positional part of the Capture
.
my Capture $c = \(2, 3, 5, apples => (red => 2)); say $c.list; # OUTPUT: «(2 3 5)»
method hash§
method hash(Capture:D:)
Returns the named/hash part of the Capture
.
my Capture $c = \(2, 3, 5, apples => (red => 2)); say $c.hash; # OUTPUT: «Map.new((:apples(:red(2))))»
method elems§
method elems(Capture:D: --> Int:D)
Returns the number of positional elements in the Capture
.
my Capture $c = \(2, 3, 5, apples => (red => 2)); say $c.elems; # OUTPUT: «3»
method keys§
multi method keys(Capture:D: --> Seq:D)
Returns a Seq
containing all positional keys followed by all named keys. For positional arguments the keys are the respective arguments ordinal position starting from zero.
my $capture = \(2, 3, 5, apples => (red => 2)); say $capture.keys; # OUTPUT: «(0 1 2 apples)»
method values§
multi method values(Capture:D: --> Seq:D)
Returns a Seq
containing all positional values followed by all named argument values.
my $capture = \(2, 3, 5, apples => (red => 2)); say $capture.values; # OUTPUT: «(2 3 5 red => 2)»
method kv§
multi method kv(Capture:D: --> Seq:D)
Returns a Seq
of alternating keys and values. The positional keys and values, if any, comes first followed by the named keys and values.
my $capture = \(2, 3, apples => (red => 2)); say $capture.kv; # OUTPUT: «(0 2 1 3 apples red => 2)»
method pairs§
multi method pairs(Capture:D: --> Seq:D)
Returns all arguments, the positional followed by the named, as a Seq
of Pair
s. Positional arguments have their respective ordinal value, starting at zero, as key while the named arguments have their names as key.
my Capture $c = \(2, 3, apples => (red => 2)); say $c.pairs; # OUTPUT: «(0 => 2 1 => 3 apples => red => 2)»
method antipairs§
multi method antipairs(Capture:D: --> Seq:D)
Returns all arguments, the positional followed by the named, as a Seq
of Pair
s where the keys and values have been swapped, i.e. the value becomes the key and the key becomes the value. This behavior is the opposite of the pairs method.
my $capture = \(2, 3, apples => (red => 2)); say $capture.antipairs; # OUTPUT: «(2 => 0 3 => 1 (red => 2) => apples)»
method Bool§
method Bool(Capture:D: --> Bool:D)
Returns True
if the Capture
contains at least one named or one positional argument.
say \(1,2,3, apples => 2).Bool; # OUTPUT: «True» say \().Bool; # OUTPUT: «False»
method Capture§
method Capture(Capture:D: --> Capture:D)
Returns itself, i.e. the invocant.
say \(1,2,3, apples => 2).Capture; # OUTPUT: «\(1, 2, 3, :apples(2))»
method Numeric§
method Numeric(Capture:D: --> Int:D)
Returns the number of positional elements in the Capture
.
say \(1,2,3, apples => 2).Numeric; # OUTPUT: «3»