### Archive

Archive for February, 2022

## Looplessly simple

February 22, 2022 1 comment

PWC#153 is asking us to do two things that are almost comically simple, given we omit loops.

Task one would like us to output the first 10 left factorials.

``````sub MAIN() {
my \leftfact = [\+] 0, 1, * * ++\$ … ∞;
say leftfact[1..10];
}``````

I’m doing so by writing down the definition of left factorials as a sequence and then indexing into the resulting lazy list.

In the 2nd task we need to check if the sum of the factorials of a digit equal that number.

``````sub MAIN(Int() \$n) {
my \fact = 1, * * ++\$ … ∞;
say fact[\$n.comb].sum == \$n ?? 1 !! 0
}``````

Again, I write down the definition of a factorial to get a lazy list in return. Then I can index into that list with a list of chars. Thankfully, Raku is considered enough to turn that list of chars into `Int`s for me. The sum is then checked against the whole number.

If you wonder what numbers are factorions, we can calculate them all.

``````my \fact = 1, * * ++\$ … ∞;
fact[0..10];
.say for (^∞).hyper(:batch(1000)).grep({ fact[.comb].sum == .Int });``````

Hypering and sequences don’t really mix. State variables even less so. Luckily we only ever need the factorials of 0 to 10. I prime the lazy list with those values and happily hyper away.

I had a peak into the solutions on Rosattacode for left factorials. While scrolling past so many loops I had to think of Mr T.

Categories: Raku

## Fuzzy commands

February 9, 2022 1 comment

Reading can make one learned. Today I had a peak into lizmat´s new module shorten-sub-commands and learned about `Parameter.constraint_list`. We need this method to introspect a routines literal parameters.

``````use MONKEY-TYPING;
augment class Parameter {
method literal {
!self.name && !self.named && self.type ~~ Str|Numeric && self.constraint_list == 1
!! Nil
}
}

multi sub foo('literal', 42) { }
multi sub foo(\$not-a-literal, 42) { }
.say for &foo.candidates».signature».params».literal;

# OUTOUT: (literal 42)
#         (Nil 42)``````

We can generalise lizmat´s idea of transforming command line arguments.

``````multi sub MAIN('foo', |c) { say 'foo', @*ARGS[0] }
multi sub MAIN('Barbara', |c) { say ['bar', @*ARGS[0]] }

sub transform-first-arg(Mu:D \$test is raw, &mapper) {
&MAIN.add_dispatchee: sub (Str:D \$subcommand, |c) is hidden-from-USAGE {
my &this-candidate := &?ROUTINE;
my @real-subcommands = &MAIN.candidates.grep(* !=:= &this-candidate)».signature».params».[0]».literal;
if \$subcommand ~~ \$test {
MAIN(mapper(\$subcommand), |c)
}
}
}

transform-first-arg({ .lc.contains(<fo ba>.any) }, { .trans: ['fo', /:i ba.*/] => ['foo', 'Barbara'] });``````

This program is now very generous when it comes to it’s first argument. Even `!./% bAR` will result in the right `MAIN`-candidate to be called.

I used `augment` because this doesn’t feel like an ENODOC. One needs to know quite a lot of the internal workings of `Parameter` to make use of `method constraint_list`. We may have to support more then just string and numeral literals in the future. So maybe there is a PR in order.

Categories: Raku