Filtering elements matching two regexes in Perl 6

假如想象 提交于 2019-12-08 15:53:51

问题


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 & 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.)



来源:https://stackoverflow.com/questions/52576542/filtering-elements-matching-two-regexes-in-perl-6

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!