class Parameter
class Parameter { }
Represents a parameter, for purpose of introspection.
The usual way to obtain a Parameter
object is to create a signature,
and call .params
on it to obtain a list of the parameters.
my $sig = :(Str $x);
my $param = $sig.params[0];
say $param.type; # OUTPUT: «Str()»
See Signature for more information, and also for an explanation on what most of the concepts related to parameters mean.
Methods
method name
method name(Parameter:D: --> Str:D)
Returns the parameter name, which includes all sigils and twigils. This name is used internally when applied to code, or in a declaration to determine the declared the name. This name is not necessarily usable by a caller – if it is, it will also appear as an alias. Often, the name will be chosen descriptively as a form of self-documentation.
If the parameter is anonymous, an empty string will be returned.
Note: Before Rakudo version 2020.08 the return value for an anonymous parameter was Nil.
my Signature $sig = :(Str $x, Bool);
say $sig.params[0].name; # OUTPUT: «$x»
say $sig.params[1].name; # OUTPUT: «»
method usage-name
method usage-name(Parameter:D: --> Str:D)
Returns the parameter name without any sigils and twigils.
If the parameter is anonymous, an empty string will be returned.
Note: Before Rakudo version 2020.08 the return value for an anonymous parameter was Nil.
my Signature $sig = :(Str $x, Str @*l, Bool);
say $sig.params[0].usage-name; # OUTPUT: «x»
say $sig.params[1].usage-name; # OUTPUT: «l»
say $sig.params[2].usage-name; # OUTPUT: «»
method sigil
method sigil(Parameter:D: --> Str:D)
Returns a string containing the parameter's sigil, for a looser definition of "sigil" than what is considered part of the parameter's name. Still returns a sigil even if the parameter is anonymous.
This "sigil" is actually an introspection used to help determine the normal binding style of a parameter, if it has not been altered through a trait.
Sigil | Will bind to | Default behavior |
---|---|---|
$ | Scalar | Generate new Scalar, use instead of Scalar in argument, if any |
@ | Positional | Bind directly to the argument |
@ | PositionalBindFailover | If binding failed, call argument's .cache method, bind to result |
% | Associative | Bind directly to the argument |
& | Callable | Bind directly to the argument |
\ | (anything) | Bind directly to the argument, keep existing Scalar, if any |
Also, |
will bind to all remaining arguments and make new Capture if needed.
method type
Returns the nominal type constraint of the parameter.
method coerce_type
Returns the coercion type of the parameter.
method constraints
Returns additional constraints on the
parameter (usually as an all
-Junction).
method named
method named(Parameter:D: --> Bool:D)
Returns True
if it's a named parameter.
my Signature $sig = :(Str $x, Bool :$is-named);
say $sig.params[0].named; # OUTPUT: «False»
say $sig.params[1].named; # OUTPUT: «True»
method named_names
method named_names(Parameter:D: --> List:D)
Returns the list of externally usable names/aliases for a named parameter.
method positional
method positional(Parameter:D: --> Bool:D)
Returns True
if the parameter is
positional.
my Signature $sig = :(Str $x, Bool :$is-named);
say $sig.params[0].positional; # OUTPUT: «True»
say $sig.params[1].positional; # OUTPUT: «False»
method slurpy
method slurpy(Parameter:D: --> Bool:D)
Returns True
for
slurpy parameters.
method twigil
method twigil(Parameter:D: --> Str:D)
Returns a string containing the twigil part of the parameter's name.
method optional
method optional(Parameter:D: --> Bool:D)
Returns True
for
optional parameters.
method raw
method raw(Parameter:D: --> Bool:D)
Returns True
for raw parameters.
sub f($a, $b is raw, \c) {
my $sig = &?ROUTINE.signature;
for ^$sig.params.elems {
say $sig.params[$_].raw;
}
}
f(17, "4711", 42); # OUTPUT: «FalseTrueTrue»
Raw parameters bind either a variable or a value passed to it, with no decontainerization taking place. That means that if a variable was passed to it, you can assign to the parameter. This is different from rw-parameter which can only bind to variables, never to values.
This is the normal behavior for parameters declared with a
sigil of '\
', which is not really a sigil insofar
as it is only used on the parameter.
sub f(\x) {
x = 5;
}
f(my $x); # works
f(42); # dies
CATCH { default { put .^name, ': ', .Str } };
# OUTPUT: «X::Assignment::RO: Cannot modify an immutable Int»
Other parameters may become raw through use of the 'is raw
'
trait. These still use
their sigil in code.
sub f($x is raw) {
$x = 5;
}
When used with slurpy list parameters, the is raw
trait will cause the list
of arguments given to be packed into a List instead of an Array, which
prevents them from being containerized with Scalar. This is the default
behavior when using +
with a sigilless parameter:
my @types is List = Mu, Any;
say -> *@l { @l }(@types)[0] =:= @types[0]; # OUTPUT: «False»
say -> +@l { @l }(@types)[0] =:= @types[0]; # OUTPUT: «False»
say -> +l { l }(@types)[0] =:= @types[0]; # OUTPUT: «True»
say -> *@l is raw { @l }(@types)[0] =:= @types[0]; # OUTPUT: «True»
method capture
method capture(Parameter:D: --> Bool:D)
Returns True
for parameters that capture the rest of the argument list into
a single Capture object.
sub how_many_extra_positionals($!, |capture) { capture.elems.say }
how_many_extra_positionals(0, 1, 2, 3); # OUTPUT: «3»
say &how_many_extra_positionals.signature.params[1].capture; # OUTPUT: «True»
Like raw parameters, Capture parameters do not force any context on the values bound to them, which is why their sigils are only used in declarations.
method rw
method rw(Parameter:D: --> Bool:D)
Returns True
for is rw
parameters.
my Signature $sig = :(Str $x is rw, Bool :$is-named);
say $sig.params[0].rw; # OUTPUT: «True»
say $sig.params[1].rw; # OUTPUT: «False»
method copy
method copy(Parameter:D: --> Bool:D)
Returns True
for is copy
parameters.
my Signature $sig = :(Str $x, Bool :$is-named is copy);
say $sig.params[0].copy; # OUTPUT: «False»
say $sig.params[1].copy; # OUTPUT: «True»
method readonly
method readonly(Parameter:D: --> Bool:D)
Returns True
for read-only parameters (the default).
my Signature $sig = :(Str $x is rw, Bool :$is-named);
say $sig.params[0].readonly; # OUTPUT: «False»
say $sig.params[1].readonly; # OUTPUT: «True»
method invocant
method invocant(Parameter:D: --> Bool:D)
Returns True
if the parameter is the
invocant parameter.
my Signature $sig = :($i : Str $x is rw, Bool :$is-named);
say $sig.params[0].invocant; # OUTPUT: «True»
say $sig.params[1].invocant; # OUTPUT: «False»
method default
method default(Parameter:D: --> Code:_)
Returns a closure that upon invocation returns the default value for this parameter, or Code if no default was provided.
Note: Before Rakudo version 2020.08 the return value for a parameter with no default value was Any.
my $sig = :($a, $b = 12);
say $sig.params[0].default; # OUTPUT: «(Code)»
say $sig.params[1].default.(); # OUTPUT: «12»
method type_captures
method type_captures(Parameter:D: --> List:D)
Returns a list of variable names of type captures associated with this parameter. Type captures define a type name within the attached code, which is an alias to the type gleaned from the argument during a call.
sub a(::T $x) { T.say }
a(8); # OUTPUT: «(Int)»
say &a.signature.params[0].type_captures; # OUTPUT: «(T)»
sub b($x) { $x.^name.say }
a(8); # OUTPUT: «Int»
The type used may change from call to call. Once they are defined, type captures can be used wherever you would use a type, even later in the same signature:
sub c(::T $x, T $y, $z) { my T $zz = $z };
c(4, 5, 6); # OK
try c(4, 5, "six");
given $! { .message.say };
# OUTPUT: «Type check failed in assignment to $zz; expected Int but got Str ("six")»
try c("four", 5, "six");
given $! { .message.say };
# OUTPUT: «Type check failed in binding to parameter '$y'; expected Str but got Int (5)»
Type captures may be used at the same time as type constraints.
sub d(::T Numeric $x, T $y) {};
d(4, 5); # OK
d(4e0, 5e0); # OK
try d(4e0, 5);
given $! { .message.say };
# OUTPUT: «Type check failed in binding to parameter '$y'; expected Num but got Int (5)»
try d("four", "five");
given $! { .message.say };
# OUTPUT: «Type check failed in binding to parameter '$x'; expected Numeric but got Str ("four")»
method sub_signature
method sub_signature(Parameter:D: --> Signature:_)
If the parameter has a sub-signature, returns a Signature object for it. Otherwise returns Signature.
Note: Before Rakudo version 2020.08 the return value for a parameter with no sub-signature was Any.
my Signature $sig = :(@array ($first, *@rest), @other);
say $sig.params[0].sub_signature; # OUTPUT:«($first, *@rest)»
say $sig.params[1].sub_signature; # OUTPUT:«(Signature)»
method prefix
method prefix(Parameter:D: --> Str:D)
If the parameter is slurpy,
returns the marker (e.g., *
, **
, or +
) the parameter was declared
with. Otherwise, returns an empty string.
my Signature $flat-slurpy = :($a, *@b);
say $flat-slurpy.params[0].prefix; # OUTPUT:«»
say $flat-slurpy.params[1].prefix; # OUTPUT:«*»
my Signature $unflat-slurpy = :($a, **@b);
say $unflat-slurpy.params[0].prefix; # OUTPUT:«»
say $unflat-slurpy.params[1].prefix; # OUTPUT:«**»
my Signature $sar-slurpy = :($a, +@b);
say $sar-slurpy.params[0].prefix; # OUTPUT:«»
say $sar-slurpy.params[1].prefix; # OUTPUT:«+»
method suffix
method suffix(Parameter:D: --> Str:D)
Returns the ?
or !
marker a parameter was declared with, if any. Otherwise,
returns the empty string.
my Signature $pos-sig = :($a, $b?);
say $pos-sig.params[0].suffix; # OUTPUT: «»
say $pos-sig.params[1].suffix; # OUTPUT: «?»
my Signature $named-sig = :(:$a!, :$b);
say $named-sig.params[0].suffix; # OUTPUT: «!»
say $named-sig.params[1].suffix; # OUTPUT: «»
method modifier
method modifier(Parameter:D: --> Str:D)
Returns the type smiley (:U
, :D
, or
:_
) a parameter was declared with. It returns the empty string for the :_
type smiley.
my Signature $sig = :(Str:U $a, UInt:D $b, $c);
say $sig.params[0].modifier; # OUTPUT: «:U»
say $sig.params[1].modifier; # OUTPUT: «:D»
say $sig.params[2].modifier; # OUTPUT: «»
Runtime creation of Parameter objects (6.d, 2019.03 and later)
Parameter.new( ... )
In some situations, specifically when working with the
MetaObject Protocol, it makes sense to create Parameter
objects programmatically. For this purpose, you can call the new
method
with the following named parameters:
name
Optional. The name of the parameter, if any. Can be specified in the same
way as in a Signature. So it may contain specific additional information,
such as a sigil ($
, @
, %
or &
), a :
prefix to indicate a named
parameter, a twigil (.
or !
) to indicate public / private attribute
binding, a postfix !
or ?
to indicate an optional / mandatory parameter,
and the various combinations of +
, *
, **
prefixes to indicate
slurpiness types and |
to indicate a Capture.
type
Optional. The type of the parameter. Assumes Any if not specified.
default
Optional. The value of the parameter if the parameter is optional and no argument has been given for that parameter. Assumes not initialization if no argument has been given, which would fall back to the (implicit) type of the parameter.
where
Optional. Additional constraints to be applied to any argument to match with this parameter. Does not set any additional constraints by default.
is-copy
Optional. Allows one to set the "is copy" flag on the parameter. Does not set the flag by default.
is-raw
Optional. Allows one to set the "is raw" flag on the parameter. Does not set the flag by default.
is-rw
Optional. Allows one to set the "is rw" flag on the parameter. Does not set the flag by default.
named
Optional. Indicates whether the parameter is a named parameter or not.
Should only be specified if the :
prefix is not specified in the name
and a named parameter is required.
optional
Optional. Indicates whether the parameter is optional or not. Should only be
specified if the ?
postfix is not specified in the name and an optional
parameter is required.
mandatory
Optional. Indicates whether the parameter is mandatory or not. Should only be
specified if the !
postfix is not specified in the name and a mandatory
parameter is required.
multi-invocant
Optional. Indicates whether the parameter should be considered in
multi-dispatch or not. Defaults to True
, so one would need to do
:!multi-invocant
to make the parameter not be considered in
multi-dispatch.
sub-signature
Optional. Specifies any Signature that should be applied to the parameter to deconstruct it. By default, no signature is to be applied.