BrowserREPL-button-tip-on BrowserREPL-button-tip-off

EditButtonTip 2024-05-28

class WhateverCode

Code object constructed by Whatever-priming

class WhateverCode is Code { }
Code

WhateverCode objects are the result of Whatever-priming. 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 get-val(Cycle $c, Int $idx) {
      $c.vals[$idx % $c.vals.elems]
}

# Define what to do with a stand-alone * as the second argument
multi get-val(Cycle $c, Whatever $idx) {
    get-val($c, $c.pos);
}

# Define what to do with a * WhateverCode in an expression
multi get-val(Cycle $c, WhateverCode $idx) {
    get-val($c, $idx($c.pos));
}

my Cycle $c .= new(:pos(2), :vals(0..^10));

say get-val($c, 3);   # OUTPUT: «3␤»
say get-val($c, *);   # OUTPUT: «2␤»
say get-val($c, *-1); # OUTPUT: «1␤»
Code

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 get-val(Cycle $c, WhateverCode $idx where { .arity == 2 }) {
    get-val($c, $idx($c.pos, $c.vals.elems));
}

say get-val($c, * + * div 2); # 2 + 10/2 = 7
Code

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

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

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

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

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

Class relation diagram§

Rakudo Type Relation for WhateverCode WhateverCode WhateverCode Code Code WhateverCode->Code is