8

What or how is Raku recursive regex syntax and all match variable in Raku as on try

'hellohelloworldworld' ~~ m{ ^(h\w+?o) (?0) world  };
say "\n=$&"

seems to not work

Please help out solving these.

Mustafa Aydın
  • 17,645
  • 4
  • 15
  • 38
itil memek cantik
  • 1,167
  • 2
  • 11
  • @raiph This question should have an answer regarding "publication of a match variable." Please consider reposting, thx. – jubilatious1 Feb 01 '22 at 21:46
  • @raiph yes but you're citing an answer to a question initially posted 3.5 years ago. I for one expect the compiler to have evolved since then, so that what may have been considered a bug back then has either 1) been enshrined in the docs, or 2) has been obviated. Which is to say...going forward, a 2022 **updated** answer from you regarding *"Publication" of match variables by Rakudo* would be most prized. Regards. – jubilatious1 Feb 01 '22 at 22:51
  • @raiph Still hoping to confirm/refute whether 'publication' of a match-variable is still required (or not). As mentioned previously, I get the desired answer with `say $/ if 'hellohelloworldoworld' ~~ m/ ^(h\w+?o) {$0} world /;`. And I'm running that in REPL version `moar (2021.06)`. – jubilatious1 Feb 01 '22 at 23:59
  • Aaah. I've been playing with the wrong input string (...`worldoworld`). Now I see: `say $/ if 'hellohelloworldworld' ~~ m/ ^(h\w+?o) {} $0 world /;` works properly. My tests indicate "publication" is indeed still required. – jubilatious1 Feb 02 '22 at 16:26
  • 2
    @jubilatious I think it was changed in the question, so not your mistake :-) – Sebastian Feb 02 '22 at 16:46

2 Answers2

8

Raku has dedicated syntax for anonymous recursive regexes :<~~>.

Using this syntax, you could write the regex in your question as:

'hellohelloworldworld' ~~ m{ ^(h\w+?o) <~~>? world  };

say $/; # OUTPUT: «「hellohelloworld」␤
        #          0 => 「hellohello」␤»
codesections
  • 8,900
  • 16
  • 50
  • 3
    "I didn't plagiarize, honest teach!" :) (I prepared an edit of my answer covering self-recursion, and a bogus-but-maybe-interesting "Answer #3", hours ago. But I lost net connection (it's yoyoing today due to Storm Corrie), and then got waylaid, before publishing it (just now).) – raiph Jan 30 '22 at 22:26
  • Confused, because without `<~~>?` the code `say $/ if 'hellohelloworldworld' ~~ m{ ^(h\w+?o) world };` still returns the same result. I'm on REPL version `moar (2021.06)`. – jubilatious1 Feb 02 '22 at 17:58
3

The two answers I expected to see have already been posted, they are:

  1. " {} publication" of a match variable for use later within the same regex/matching operation (technically a backreference):
    > say $/ if 'hellohelloworldworld' ~~ m/ ^(h\w+?o) {} $0 world /;
    「hellohelloworld」
     0 => 「hello」
    > say $/ if 'hellohelloworldworld' ~~ m/ ^(h\w+?o) world /;
    「hellohelloworld」
     0 => 「hellohello」

and,

  1. use of Raku's dedicated " <~~> recursing-match" operator within the regex.

In true TMTOWTDI-spirit, there is however a third option, using Raku's :nd() adverb to achieve a sort of "poor-man's" recursion. Starting from the ['(' \w* ] grouping, you can successively pull out 「(bird」, 「(in」, and 「(nest」 from the input string (bird(in(nest))). Or all three at once (last example):

In the Raku REPL:

> my $nested = "(bird(in(nest)))";
(bird(in(nest)))
> say $nested;
(bird(in(nest)))
> say  $nested ~~ m:1st/ ['(' \w* ] /;
「(bird」
> say  $nested ~~ m:2nd/ ['(' \w* ] /;
「(in」
> say  $nested ~~ m:3rd/ ['(' \w* ] /;
「(nest」
> say  $nested ~~ m:nd(1..3)/ ['(' \w* ] /;
(「(bird」 「(in」 「(nest」)
>

Behind the scenes this is most likely using Raku's :position adverb or :continue adverb, in conjunction with Raku's $/.to match variable:

> say  $nested ~~ m/ ['(' \w* ] /;
「(bird」
> say  $nested ~~ m:pos($/.to)/ ['(' \w* ] / given $nested ~~ m/ ['(' \w* ] /;
「(in」
> say  $nested ~~ m:pos($/.to)/ ['(' \w* ] / given $nested ~~ (m/ ['(' \w* ] / && m:pos($/.to)/ ['(' \w* ] /);
「(nest」
> 

Again, Raku gives you a lot of different ways to approach the problem, which is one of the niceties of the language.

jubilatious1
  • 1,999
  • 10
  • 18