Something is going on here that I don't quite understand.
> my @arr = <ac bc abc>
> @arr.grep: (( * ~~ /a/ ) && ( * ~~ /b/ ))
(bc abc)
But
> @arr.grep(* ~~ /a/).grep(* ~~ /b/)
(abc)
What's the reason?
You've come up with perfectly cromulent solutions.
Another would be:
my @arr = <ac bc abc>
@arr.grep: { $_ ~~ /a/ && $_ ~~ /b/ }
(abc)
The rest of this answer just explains the problem. The problem in this question is a more complicated version of the problem covered at WhateverStar &&
WhateverStar.
The logical ops don't execute their arguments if they're code.
So { $_ ~~ /a/ } && { $_ ~~ /b/ }
returns { $_ ~~ /b/ }
.
Or * ~~ /a/ && * ~~ /b/
returns * ~~ /b/
.
At the same time, grep
does execute its matcher if it's code or if it's a regex, so these are all the same:
foo.grep: { $_ ~~ /.../ }
foo.grep: * ~~ /.../;
foo.grep: /.../;
Junction
sYour Junction
solution seems natural. I'd love it if someone could explain what I'm missing in the following. While I expected it to work, it's bending my head to figure out how it actually works but I think it's something like (but not quite):
foo & bar
becomes a Junction
of foo
and bar
.
An attempt is made to invoke grep
with a Junction
as an argument.
Because Junction
is outside the normal Any
value hierarchy, most routines don't have a matching signature. grep
doesn't.
When you invoke a routine and there is no corresponding signature then the initial dispatch fails and we hit a dispatch fallback handler. This may be the method one.
If the dispatch fallback handler sees there are Junction
arguments then it extracts the individual values in the Junction
and fires up logically parallel "threads" (currently never actual threads, but the compiler is allowed to make them real threads if it thinks that is a good idea) corresponding to those values. Thus it invokes grep
twice per element of the invocant and outputs the results back into a new Junction
of the same type as the incoming Junction
.
In boolean context, a Junction
collapses to a single result.
(If a Junction
is in an overall boolean context then it can (parallel) short-circuits based on results. If it's an any
and any result comes in True
then it can cancel the rest -- or not do them in the first place if it's actually doing things sequentially, as is currently always the case. If it's an all
and any result comes in False
it can cancel the rest. Etc.)
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