Wish on a Whatever-Star
The "Whatever-Star" was at first alarming to me! I first noticed it when I learned how to shuffle an entire list. The Whatever-Star can do some other stuff, too. But that's ok, we'll start with this.
my @shuffled = < alice bob carol dave erik frank >.pick(*);
Now... in the past I've tried ".pick(1)" which gets me one name at random. Then ".pick(2)" will give me two, and not repeat. If I put in too many then it'll only give me back what it can, in this case all six names. But ".pick(*)" ... that doesn't even look valid! The documentation says (though I can't recall where) that it is the same as ".pick(Inf)". When I picked more than there were, it stopped when there was nothing to pick. So this makes sense... try to pick an infinite number and we'll just get them all. Nice. Still kinda weird about the '*' though.
So then I, mistakenly, thought that maybe "pick" was special. Maybe they hooked the parser up so that it could, like, "know" that pick could be passed this '*', which I learned is named "Whatever". I couldn't have been closer to the truth! Except without the "special" bit. Time to do a bit of exploring!
Let's try to figure out how this works without resorting to such tedious things as reading documentation, source code, or IRC, shall we? RTFM my eye. If pick is special, then I shouldn't be able to add something that behaves similarly. Wait, let's do this formal like.
THEOREM: (1,2,3,4,5).pick(*) is somehow special, and can't be replicated without modifying the compiler.
PROOF:
Let's start by assuming that it is NOT special, and attempt to do a proof-by-contradiction (constructivists be damned¹). Then we should be able to create our own method that can behave specially when '*' is passed.
First, what class is .pick(*) working on, anyway? Let's ask rakudo.
> (1,2,3,4,5).WHAT
Parcel()
Parcel. OK, whatever that is. So all we gotta do is slap a new method on there and see what we get. (google... google... irc... (yes, contrary to the overall anti-research basis. But it's ok because we're in parenthesis)). OK, here we go.
> use MONKEY_TYPING; augment class Parcel { method yo($x) { say "I like to eat $x." } }
!class_init_384
> (1,2,3,4,5).yo('fishies')
I like to eat fishies.
Well that was easy :) . Now for the BIG TEST!
> (1,2,3,4,5).yo(*)
I like to eat Whatever()<0xb2f5a7c>.
OMG it worked! So I actually get a parameter, and it is an instance of Whatever. Well then.
THEOREM DISPROVED.
I then decided to actually cast about for how things use this. Here's a great example, the Rakudo Any-list pick whatever implementation. You can see that they use multi-methods to easily deal with the Whatever case separately from other passed values.
[1] I actually like constructivists, and welcome a constructive version of this non-proof.
Leave a comment