class WhateverCode

Code object constructed by Whatever-currying

class WhateverCode is Code { }

WhateverCode objects are the result of Whatever-currying. See the Whatever documentation for details.

When you wish to control how a method or function interprets any Whatever star, you may use multi dispatch with Whatever and WhateverCode parameters to do so, as in the following example:

class Cycle {
      has $.pos;
      has @.vals;
}
 
multi sub get-val(Cycle $cInt $idx{
      $c.vals[$idx % $c.vals.elems]
}
 
# Define what to do with a stand-alone * as the second argument 
multi sub get-val(Cycle $cWhatever $idx{
    get-val($c$c.pos);
}
 
# Define what to do with a * WhateverCode in an expression 
multi sub get-val(Cycle $cWhateverCode $idx{
    get-val($c$idx($c.pos));
}
 
my Cycle $c .= new(:pos(2), :vals(0..^10));
 
say get-val($c3);   # OUTPUT: «3␤» 
say get-val($c*);   # OUTPUT: «2␤» 
say get-val($c*-1); # OUTPUT: «1␤»

The WhateverCode does the Callable role, so it should be possible to introspect the type of Callable it contains; for instance, continuing the previous example, we can add a multi that handles a WhateverCode with two arguments via checking the signature:

# Define what to do with two * in an expression 
multi sub get-val(Cycle $cWhateverCode $idx where { .arity == 2 }{
    get-val($c$idx($c.pos$c.vals.elems));
}
 
say get-val($c* + * div 2); # 2 + 10/2 = 7 

Note, though, that subexpressions may impose their own Whatever star rules:

my @a = (012);
say get-val($c@a[*-1]) # 2, because the star belongs to the Array class 

This can make the ownership of Whatever stars become confusing rather quickly, so be careful not to overdo it.

You may instead type-constrain using Callable type in order to accept any Callable, including WhateverCode:

sub run-with-rand (Callable $code{ $code(rand};
run-with-rand *.say;           # OUTPUT: «0.773672071688484␤» 
run-with-rand {.say};          # OUTPUT: «0.38673179353983␤» 
run-with-rand sub { $^v.say }# OUTPUT: «0.0589543603685792␤»

Type-constraining with &-sigiled parameter works equally well and is shorter to type:

sub run-with-rand (&code{ code time };

Type Graph

Type relations for WhateverCode
perl6-type-graph WhateverCode WhateverCode Code Code WhateverCode->Code Mu Mu Any Any Any->Mu Callable Callable Code->Any Code->Callable

Expand above chart

Routines supplied by class Code

WhateverCode inherits from class Code, which provides the following routines:

(Code) 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.

(Code) method arity

Defined as:

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␤»

(Code) method assuming

method assuming(Callable:D $self: |primers)

Returns a Callable that 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){ cnow - 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: *, /\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␤»

(Code) method count

Defined as:

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␤»

(Code) method of

Defined as:

method of(Code:D: --> Mu)

Returns the return type constraint of the Code:

say -> () --> Int {}.of# OUTPUT: «(Int)␤»

(Code) method signature

Defined as:

multi method signature(Code:D: --> Signature:D)

Returns the Signature object for this code object, which describes its parameters.

sub a(Int $oneStr $two{};
say &a.signature# OUTPUT: «(Int $one, Str $two)␤»

(Code) 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: «()␤»

(Code) method Str

Defined as:

multi method Str(Code:D: --> Str:D)

Will output the method name, but also produce a warning. Use .perl or .gist instead.

sub marine() { }
say ~&marine;
# OUTPUT: «Sub object coerced to string (please use .gist or .perl to do that)␤marine␤» 
say &marine.Str;
# OUTPUT: «Sub object coerced to string (please use .gist or .perl to do that)␤marine␤» 
say &marine.perl# OUTPUT: «sub marine { #`(Sub|94280758332168) ... }␤»

(Code) method file

Defined as:

method file(Code:D: --> Str:D)

Returns the name of the file in which the code object was declared.

say &infix:<+>.file;

(Code) method line

Defined as

method line(Code:D: --> Int:D)

Returns the line number in which the code object was declared.

say &infix:<+>.line;

Routines supplied by role Callable

WhateverCode inherits from class Code, which does role Callable, which provides the following routines:

(Callable) method CALL-ME

method CALL-ME(Callable:D $self: |arguments)

This method is required for postfix:«( )» and postfix:«.( )». It's what makes an object actually call-able and needs to be overloaded to let a given object act like a routine. If the object needs to be stored in a &-sigiled container, is has to implement Callable.

class A does Callable {
    submethod CALL-ME(|c){ 'called' }
}
my &a = A;
say a(); # OUTPUT: «called␤»

Applying the Callable role is not a requirement to make an object callable; if a class simply wants to add subroutine-like semantics in a regular scalar container, the submethod CALL-ME can be used for that.

class A {
    has @.values;
    submethod CALL-ME(Int $x where 0 <= * < @!values.elems{
        @!values[$x]
    }
}
my $a = A.new: values => [4,5,6,7]
say $a(2); # OUTPUT: «6␤»

(Callable) method Capture

Defined as:

method Capture()

Throws X::Cannot::Capture.