Map signature mismatch with Whatever? x vs X vs xx
Let me see if I can get this through clearly. If I don't, please ask.
Short answer: xx
has a special meaning together with Whatever
, so it's not creating a WhateverCode
as in the rest of the examples.
Let's see if I can get this straight with the long answer.
First, definitions. * is called Whatever
. It's generally used in situations in which it's curried
I'm not too happy with this name, which points at functional-language-currying, but does not seem to be used in that sense, but in the sense of stewing or baking. Anyway.
Currying it turns it into WhateverCode
. So an * by itself is Whatever, * with some stuff is WhateverCode, creating a block out of thin air.
However, that does not happen automatically, because some times we need Whatever just be Whatever. You have a few exceptions listed on Whatever
documentation. One of them is using xx
, because xx
together with Whatever
should create infinite lists.
But that's not what I'm doing, you can say. *
is in front of the number to multiply. Well, yes. But this code in Actions.nqp (which generates code from the source) refers to infix xx
. So it does not really matter.
So, back to the short answer: you can't always use *
together with other elements to create code. Some operators, such as that one, .. or ... will have special meaning in the proximity of *, so you'll need to use something else, like placeholder arguments.
The xx
operator is “thunky”.
say( rand xx 2 );
# (0.7080396712923503 0.3938678220039854)
Notice that rand
got executed twice. x
and X
don't do that.
say( rand x 2 );
0.133525574759261740.13352557475926174
say( rand X 1,2 );
((0.2969453468495996 1) (0.2969453468495996 2))
That is xx
sees each side as something sort of like a lambda on their own.
(A “thunk”)
say (* + 1 xx 2);
# ({ ... } { ... })
say (* + 1 xx 2)».(5);
# (6 6)
So you get a sequence of *
repeated twice.
say (* xx 2).map: {.^name}
# (Whatever Whatever)
(The term *
, is an instance of Whatever)
This also means that you can't create a WhateverCode closure with &&
/ and
, ||
/ or
, ^^
/ xor
, or //
.
say (* && 1);
# 1
Note that *
also does something different on the right side of xx
.
It creates an infinite sequence.
say ( 2 xx * ).head(20);
# (2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2)
If xx
wasn't “thunky”, then this would also have created a WhateverCode lambda.