* > 20 && * %% 5
used in grep
seems wrong, does is equal to a WhateverCode lambda that takes 2 arguments? As this explain on SO
> my @a = 1,12,15,20,25,30,35,37;
> @a.grep: * > 20 && * %% 5 # The result seems strange, expected (25 30 35)
(15 20 25 30 35)
> @a.grep: * %% 5 && * > 20
(25 30 35 37)
> @a.grep: { $_>20 && $_ %% 5 }
(25 30 35)
> @a.grep: all(* > 20, * %% 5)
(25 30 35)
> @a.grep: -> $a { all($a > 20, $a %% 5) }
(25 30 35)
> @a.grep: -> $a {$a > 20 && $a %% 5}
(25 30 35)
my &or = * == 1 || * == 2 ;
my &and = * == 1 && * == 2 ;
say .signature, .(1), .(2)
for &or, ∧
displays:
(;; $whatevercode_arg_1 is raw)TrueFalse
(;; $whatevercode_arg_4 is raw)FalseTrue
I still don't know what's going on [ed: that is, I didn't at the time I wrote this paragraph; I kept what I wrote in this answer as the mystery unfolded], but it's clear that the signature is for just one arg and the result is as per just the right hand expression for the &and
and the left hand for the &or
which means the code doesn't seem to have, er, left the result that's, er, right. Investigation continues... (and no, I'm not det remiker).
So, it looks like the logical ops (&&
, ||
, and
, or
, etc.) don't do Whatever
-currying. Which is fair enough given that "not all operators and syntactic constructs curry *
(or Whatever
-stars) to WhateverCode
". Logical, even, given their nature. They probably ought to be added to the table of exceptions on that page though.
In the meantime, operators like ==
do Whatever
curry. Again, that's fair enough given "subexpressions may impose their own Whatever star rules".
So it makes sense that &or
and &and
turn in to...
Aha! Got it. The * == 1
and * == 2
are evaluated at compile-time and turn into WhateverCode
s. As WhateverCode
s they are just bits of code. They are defined. They are True
. (This ignores calling them at run-time.) Then along comes the &&
and evaluates to the right hand WhateverCode
. (The ||
would evaluate to its left hand WhateverCode
.)
Hence the behavior we see.
Per prompting by @HåkonHægland, the code that would work is therefore code that doesn't rely on logical ops Whatever
-currying, i.e.:
my @a = 1,12,15,20,25,30,35,37;
say @a.grep: { $_ > 20 && $_ %% 5 } # (25 30 35)
Now we have to figure out what doc edits to propose...
Actually, before we do that, confirm that logical ops are supposed to not Whatever
-curry...
And to start that ball rolling, I just trawled the results of a search for TimToady
comments on #perl6 about "currying" (there were none on #perl6-dev), looking for ones pertinent to the case we have here.
First, one from 2017 that's arguably relevant to any doc edits:
the design docs actually try to avoid the word "currying" ... but it's hard to get people to use words differently than they do
Next, one from 2015 about &&
and ||
and such:
||
and&&
and such are really control flow operators, turned rather rapidly into 'if' and 'unless' ... those ops can be curried with.assuming
, I assume
And finally a couple from 2010 that also seem potentially important (though perhaps one or more are no longer applicable?):
all operators autocurry a
WhateverCode
, whether or not they curry aWhatever
I think we can keep the current mechanism as a fallback for operators that still want to curry at run time
> my $d = * + * + *
> $d.arity
3
> my $e = * == 1 || * == 2 || * == 3
> $e.arity
1
as the doc say:
Returns the minimum number of positional arguments that must be passed in order to call the code object.
so I think the all three star in * == 1 || * == 2 || * == 3
is the same thing.
> my $e = * == 1 && * == 2 && * > 3
> $e(1)
False
> $e(2)
False
> $e(3)
False
> $e(4)
True
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With