问题
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?
回答1:
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: /.../;
The magic of Junction
s
Your 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 aJunction
offoo
andbar
.An attempt is made to invoke
grep
with aJunction
as an argument.Because
Junction
is outside the normalAny
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 theJunction
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 invokesgrep
twice per element of the invocant and outputs the results back into a newJunction
of the same type as the incomingJunction
.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 anany
and any result comes inTrue
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 anall
and any result comes inFalse
it can cancel the rest. Etc.)
来源:https://stackoverflow.com/questions/52576542/filtering-elements-matching-two-regexes-in-perl-6