Home > Raku > Returning the right amount

Returning the right amount

Do you know that look your better halve gives you when you return with the wrong number of items from the groceries? Tell you what, we will write a script for that!

sub buy-eggs($amount --> Seq where *.elems == $amount) {
    my $forgotten-amount = (1..$amount).roll;
    return "egg" xx $amount - $forgotten-amount;
}

say buy-eggs 10;
Cannot do non-typename cases of type_constraint yet
at /home/dex/projects/blog/return-check.raku:3
------> $amount --> Seq where *.elems == $amount⏏) {

Raku failed us! But Raku being Raku we are allowed to help it.

multi sub trait_mod:<is>(Sub $s, :return-where(&condition)) {
    $s.wrap({
        my $ret = callsame;

        if !condition($ret) {
            fail ‚return condition does not match for sub ‘ ~ $s.name ~ ‚ for return value of ‘ ~ $ret.gist;
        }

        $ret
    });
}

Now we can check if a sub returns a certain amount of elements.

sub buy-eggs($amount --> Seq) is return-where(*.elems == 10) {...}

There is a catch though. In contrast to a where-clause a trait does not have access to variables in the scope of the signature. We can use a POST phaser for that.

sub buy-eggs($amount --> Seq) {
    my $forgotten-amount = (1..$amount).roll;
    return "egg" xx $amount - $forgotten-amount;

    POST { $_ == $amount or fail "back to the store!" }
}

A proper where clause on the return check would be nice for documentation. If we can move any input and output validation into the signature that signature becomes a description of the input and output values. And quite in contrast to hand written documentation it stays in sync with the code.

I hope that the prospect of spouse agro will convince the core devs to add where clauses to return checks.

Categories: Raku
  1. Samuel Chase
    May 26, 2020 at 07:20

    Nice, learnt about POST phasers. 😂

  1. June 1, 2020 at 13:39

Leave a comment