class Code
class Code is Any does Callable {}
Code
is the ultimate base class of all code objects in Raku. It
exposes functionality that all code objects have. While thunks are
directly of type Code
, most code objects (such as those resulting
from blocks, subroutines or methods) will belong to some subclass of Code
.
Methods
method ACCEPTS
multi method ACCEPTS(Code:D: Mu $topic)
Usually calls the code object and passes $topic
as an argument.
However, when called on a code object that takes no arguments, the code
object is invoked with no arguments and $topic
is dropped. The
result of the call is returned.
method arity
method arity(Code:D: --> Int:D)
Returns the minimum number of positional arguments that must be passed in order to call the code object. Any optional or slurpy parameters in the code object's Signature do not contribute, nor do named parameters.
sub argless() { }
sub args($a, $b?) { }
sub slurpy($a, $b, *@c) { }
say &argless.arity; # OUTPUT: Ā«0ā¤Ā»
say &args.arity; # OUTPUT: Ā«1ā¤Ā»
say &slurpy.arity; # OUTPUT: Ā«2ā¤Ā»
method assuming
method assuming(Callable:D $self: |primers)
Returns a new Callable that has been primed
with the arguments passed to assuming
. In other words, the new function
implements the same behavior as the original, but has the values passed to
.assuming
already bound to the corresponding parameters.
my sub slow($n){ my $i = 0; $i++ while $i < $n; $i };
# takes only one parameter and as such wont forward $n
sub bench(&c){ c, now - ENTER now };
say &slow.assuming(10000000).&bench; # OUTPUT: Ā«(10000000 7.5508834)ā¤Ā»
For a sub with arity greater than one, you can use Whatever * for all of the positional parameters that are not "assumed".
sub first-and-last ( $first, $last ) {
say "Name is $first $last";
}
my &surname-smith = &first-and-last.assuming( *, 'Smith' );
&surname-smith.( 'Joe' ); # OUTPUT: Ā«Name is Joe Smithā¤Ā»
You can handle any combination of assumed and not assumed positional parameters:
sub longer-names ( $first, $middle, $last, $suffix ) {
say "Name is $first $middle $last $suffix";
}
my &surname-public = &longer-names.assuming( *, *, 'Public', * );
&surname-public.( 'Joe', 'Q.', 'Jr.'); # OUTPUT: Ā«Name is Joe Q. Public Jr.ā¤Ā»
Named parameters can be assumed as well:
sub foo { say "$^a $^b $:foo $:bar" }
&foo.assuming(13, :42foo)(24, :72bar); # OUTPUT: Ā«13 24 42 72ā¤Ā»
And you can use .assuming
on all types of Callables,
including Methods and Blocks:
# We use a Whatever star for the invocant:
my &comber = Str.^lookup('comb').assuming: *, /P \w+/;
say comber 'Perl is awesome! Python is great! And PHP is OK too';
# OUTPUT: Ā«(Perl Python PHP)ā¤Ā»
my &learner = {
"It took me $:months months to learn $^lang"
}.assuming: 'Raku';
say learner :6months; # OUTPUT: Ā«It took me 6 months to learn Rakuā¤Ā»
method count
method count(Code:D: --> Real:D)
Returns the maximum number of positional arguments that may be passed
when calling the code object. For code objects that can accept any
number of positional arguments (that is, they have a slurpy parameter),
count
will return Inf
. Named parameters do not contribute.
sub argless() { }
sub args($a, $b?) { }
sub slurpy($a, $b, *@c) { }
say &argless.count; # OUTPUT: Ā«0ā¤Ā»
say &args.count; # OUTPUT: Ā«2ā¤Ā»
say &slurpy.count; # OUTPUT: Ā«Infā¤Ā»
method of
method of(Code:D: --> Mu)
Returns the return type constraint
of the Code
:
say -> () --> Int {}.of; # OUTPUT: Ā«(Int)ā¤Ā»
method signature
multi method signature(Code:D: --> Signature:D)
Returns the Signature object for this code object, which describes its parameters.
sub a(Int $one, Str $two) {};
say &a.signature; # OUTPUT: Ā«(Int $one, Str $two)ā¤Ā»
method cando
method cando(Capture $c)
Returns a list of candidates that can be called with the given
Capture. Since Code
objects do not have any multiple
dispatch, this either returns a list with the object, or an empty list.
my $single = \'a'; # a single argument Capture
my $plural = \('a', 42); # a two argument Capture
my &block = { say $^a }; # a Block object, that is a subclass of Code, taking one argument
say &block.cando($single); # OUTPUT: Ā«(-> $a { #`(Block|94212856419136) ... })ā¤Ā»
say &block.cando($plural); # OUTPUT: Ā«()ā¤Ā»
method Str
multi method Str(Code:D: --> Str:D)
Will output the method name, but also produce a warning. Use .raku
or
.gist
instead.
sub marine() { }
say ~&marine;
# OUTPUT: Ā«Sub object coerced to string (please use .gist or .raku to do that)ā¤marineā¤Ā»
say &marine.Str;
# OUTPUT: Ā«Sub object coerced to string (please use .gist or .raku to do that)ā¤marineā¤Ā»
say &marine.raku; # OUTPUT: Ā«sub marine { #`(Sub|94280758332168) ... }ā¤Ā»
method file
method file(Code:D: --> Str:D)
Returns the name of the file in which the code object was declared.
say &infix:<+>.file; # OUTPUT: Ā«SETTING::src/core.c/Numeric.rakumodā¤Ā»
method line
method line(Code:D: --> Int:D)
Returns the line number in the source code at which the code object's declaration begins.
say &infix:<+>.line; # OUTPUT: Ā«208ā¤Ā»
If the code object was generated automatically (and thus not
declared in the source code), then line
returns the line on which
the enclosing scope's declaration begins. For example, when called on
an automatically generated accessor method produced by the has $.name
syntax, line
returns the line on which the method's class's
declaration begins.
For example, if you have the following source file:
class Food { # Line 1
has $.ingredients; # Line 2
# Line 3
method eat {}; # Line 4
} # Line 5
Then the line
method would give you the following output:
say Food.^lookup('eat').line; # OUTPUT: Ā«4ā¤Ā»
say Food.^lookup('ingredients').line; # OUTPUT: Ā«1ā¤Ā»
method bytecode-size
method bytecode-size(--> Int:D)
Note: this method has been available in Rakudo compiler on the MoarVM backend only, starting from 2022.06 release.
Returns the number of bytes that the code object occupies in memory. Note
that if the code object is in fact a multi
, then the bytecode size will
be reported for the proto
. You can use the .candidates
method to
obtain each candidate, and then call the bytecode-size
methods on them.
say &grep.bytecode-size; # OUTPUT: Ā«114ā¤Ā»
say &grep.cadidates>>.bytecode-size; # OUTPUT: Ā«424ā¤258ā¤Ā»
method is-implementation-detail
method is-implementation-detail(--> False)
Note: this method has been available in Rakudo compiler starting from 2020.05 release.
Returns True
if the code object was marked with
is implementation-detail trait,
False
otherwise.