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.

Tags:

Raku