I don’t need conditionals either
While reading John A De Goes’ blog post about how to rid functions of variables tied to conditions, I wondered how I would do that in Perl 6.
The objective of his first example is to compare two strings case insensitive. Easy!
say "abc".fc eq "Abc".fc;
And then my mind started to wander off. I took a mental note and finished reading about ridding of ifs. Returning to my mental note I concluded: “There must be a nicer way to write that!”. It’s Perl 6 after all.
How about the function combinator?
my &ieq = &infix:<eq> ∘ &fc;
That didn’t work because ∘
cares about the number of arguments of its first operand but doesn’t about its second. What I actually need would be a loop over the two strings calling .fc
on each of them.
my @l = <abc Abc>>>.fc;
So I tried to fix the function combinator resulting in a gist. It’s now special cased for the 2nd operand to have just one argument. I felt a bit uneasy about that solution. Maybe because it would require a PR to Rakudo.
And then I realised that I might just bind a pointy to a operator name. I didn’t doc that so I checked and we indeed missed that spot. Short test via camelia.
my &infix:<foo> := -> {}
That worked. So let’s have a case insensitive string compare infix operator.
my &infix:<ieq> = -> |l { [eq] l>>.fc }; say "abc" ieq "Abc"; # OUTPUT«True»
Nice, short and no conditionals that could confuse John.
Why didn’t you just do
sub infix:<ieq> ( |l ) { [eq] l».fc }
?As I wrote, I had an idea and the idea surprisingly worked. (That form is not even in roast, nor is it in any S??) Sadly I do not know how my brain works so I can’t possibly tell you why I had that idea. Of cause you can use the boring syntax if you like, but that wouldn’t make an interesting blog post, would it?
After thinking about it a while, I may understand why I picked this very functional form. The boring way will inject an operator into the local scope and you can’t redefine the actual code object bound to it. By using an &-sigiled container, you can assign a different sub or block later. That again can save you quite a few conditionals. It’s a bit like using higher order functions without the actual function.
Rakudo contains another such trick with a one shot local method that’s basically just there to redefine self. Very Zen that. see: https://github.com/rakudo/rakudo/blob/9d3b6d0731681babfb92e13a4a9f76f75728621e/src/core/IO/Path.pm#L23