Home > Raku > Functional hypering

## Functional hypering

In my last post I used a one-shot-operator to improve neatness. Sadly, by defining custom operators we also improve Rakudo’s slowness. After staring at the code form quite some time, I realised that hyper- and meta-operators are code generators. They produce a new operator in-place, which is then used with two operands. In functional programming we do the same thing by returning a `sub` from a `sub`.

``````multi sub hyperize(&code, '«') {
sub (@little, @large) {
((@little xx *).flat Z @large).flat.map(&code)
}
}

my &hyper-assume = hyperize({&^a.assuming(\$^b)}, '«');

sub sc(\$_) {
.words».&{ hyper-assume((&lc, &uc), .comb)».().join }
}``````

Hyper-operators have a “direction” indicated by using `»` or `«`. Whereby the pointy bit points at the operand that doesn’t stop iteration. In `hyperize` I’m doing the same with a string literal.

However, this is terribadly slow. The culprit is `.assuming`, which has been reported to the authorities and will likely be fixed with RakuAST. In my case I don’t really need the fancy things `.assuming` does.

``````sub simple-assume(&routine, |tail) {
sub (|c) {
my \real-args = \(|tail, |c);
routine(|real-args)
}
}

multi sub hyperize(&code, '«') {
sub (@little, @large) {
((@little xx *).flat Z @large).flat.map(&code)
}
}

my &hyper-assume = hyperize({simple-assume(&^a, \$^b)}, '«');

sub sc(\$_) {
.words».&{ hyper-assume((&lc, &uc), .comb)».().join }
}``````

A speed up of factor 608 seems to be quite acceptable. No kidding, as soon as `.assuming` is involved Rakudo refuses to inline and as a consequence of that to JIT.

I will try to provide a `sub assuming` (right now we only have the method-form), provided I find a reasonable way to implement the advanced stuff, like skipping arguments with a `Whatever`.

Categories: Raku