The Raku docs say that Code.assuming
Returns a Callable that implements the same behavior as the original, but has the values passed to .assuming already bound to the corresponding parameters.
What is the difference between using .assuming
and wrapping the Code in an anonymous Block (or Sub) that calls the inner function with some parameters already bound?
For instance, in the code below, what is the difference between &surname-public
(an example the docs provide for .assuming
) and &surname-block
;
sub longer-names ( $first, $middle, $last, $suffix ) {
say "Name is $first $middle $last $suffix";
}
my &surname-public = &longer-names.assuming( *, *, 'Public', * );
my &surname-block = -> $a,$b,$c { longer-names($a, $b, 'Public', $c) }
surname-public( 'Joe', 'Q.', 'Jr.'); # OUTPUT: «Name is Joe Q. Public Jr.»
surname-block( 'Joe', 'Q.', 'Jr.'); # OUTPUT: «Name is Joe Q. Public Jr.»
I see that .assuming
saves a bit of length and could, in some contexts, be a bit clearer. But I strongly suspect that I'm missing some other difference.
There really isn't a difference.
While the code to implement .assuming()
is almost 300 lines, the important bit is only about ten lines of code.
$f = EVAL sprintf(
'{ my $res = (my proto __PRIMED_ANON (%s) { {*} });
my multi __PRIMED_ANON (|%s(%s)) {
my %%chash := %s.hash;
$self(%s%s |{ %%ahash, %%chash });
};
$res }()',
$primed_sig, $capwrap, $primed_sig, $capwrap,
(flat @clist).join(", "),
(@clist ?? ',' !! '')
);
The rest of the code in .assuming
is mostly about pulling information out of the signatures.
Let's take your code and insert it into that sprintf
.
(Not exactly the same, but close enough for our purposes.)
{
my $res = (
# $primed_sig v----------------------v
my proto __PRIMED_ANON ($first, $middle, $suffix) { {*} }
);
# $capwrap vv
# $primed_sig v----------------------v
my multi __PRIMED_ANON (|__ ($first, $middle, $suffix)) {
# $capwrap vv
my %chash := __.hash;
# v---------------------------v @clist
$self(__[0], __[1], 'Public', __[2], |{ %ahash, %chash });
};
# return the proto
$res
}()
If we simplify it, and tailor it to your code
my &surname-public = {
my $res = (
my proto __PRIMED_ANON ($first, $middle, $suffix) { {*} }
);
my multi __PRIMED_ANON ( $first, $middle, $suffix ) {
longer-names( $first, $middle, 'Public', $suffix )
};
$res
}()
We can simplify it further by just using a pointy block.
my &surname-public = -> $first, $middle, $suffix {
longer-names( $first, $middle, 'Public', $suffix )
};
Also by just using single letter parameter names.
my &surname-public = -> $a,$b,$c { longer-names($a, $b, 'Public', $c) }
Like I said, there really isn't a difference.
In the future, it may be more beneficial to use .assuming()
. After it gets rewritten to use RakuAST.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With