问题
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 Junctions
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 & barbecomes aJunctionoffooandbar.An attempt is made to invoke
grepwith aJunctionas an argument.Because
Junctionis outside the normalAnyvalue hierarchy, most routines don't have a matching signature.grepdoesn'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
Junctionarguments then it extracts the individual values in theJunctionand 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 invokesgreptwice per element of the invocant and outputs the results back into a newJunctionof the same type as the incomingJunction.In boolean context, a
Junctioncollapses to a single result.(If a
Junctionis in an overall boolean context then it can (parallel) short-circuits based on results. If it's ananyand any result comes inTruethen 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 analland any result comes inFalseit can cancel the rest. Etc.)
来源:https://stackoverflow.com/questions/52576542/filtering-elements-matching-two-regexes-in-perl-6