7

Just for the heck of it, I am trying to match a junction against a regex with the m// operator in raku (search for Explicit topic match on that page).

In the perl6 REPL:

> any('a','b') ~~ m/./
False

Afterwards, no matter how I call m// I get an immutable-match complaint:

> 'x' ~~ m/./
Cannot modify an immutable Match (「a」)
  in block <unit> at <unknown file> line 1

Question

What is happening behind the scenes here?

Discussion

The problem seems to stem from the fact that the $/ special variable is set to the junction

any(「a」, 「b」)

after the junction match, and it seems to be that 「a」 in the junction that's raising the complaint.

As soon as I do anything that changes $/ to something else, functionality is restored:

> $/=Any
(Any)
> 'x' ~~ m/./
「x」

or

> 'x' ~~ /./
「x」
> 'x' ~~ m/./
「x」

(so matching with // first, so as to change $/, and then match with m//).

Clarification

I am not trying to "achieve" anything beyond what the question's asking: I simply want to understand this behavior.

Edit

For cross-reference purposes, this is now also a rakudo github issue, as suggested by @jjmerelo.

Elizabeth Mattijsen
  • 25,654
  • 3
  • 75
  • 105
grobber
  • 1,083
  • 1
  • 9
  • 20
  • 1
    It's probably a bug, but the actual mechanism for this bug would have to be researched. – jjmerelo Nov 02 '20 at 18:04
  • Thanks; at least I'm not the only one baffled by this :). On a related note, I was also surprised by the original match `any('a','b') ~~ m/./` returning `False`; I'd definitely expect a `True` there.. – grobber Nov 02 '20 at 18:16
  • 2
    i was preparing an answer, but you have answered exactly the same in your edit while I was doing it. The problem seems to be that $/ is not assigned using the normal mechanism, but a mechanism that finds the immutable 'a'. I would have to go into the source to find it out. But this is definitely an issue, it would be nice if you raised it in the Rakudo repo. – jjmerelo Nov 02 '20 at 18:25
  • @jjmerelo: thank you, I'll do that soon (raise an issue). – grobber Nov 02 '20 at 18:38
  • 1
    re `False`. The `m/.../` is an "Explicit topic match". It matches against `$_`. What value is `$_` set to? The sub-expression `m/.../` is being evaluated within an outer expression, which is `LHS ~~ RHS`. And that's the smart match operator which temporarily binds `$_` to the LHS for the duration of evaluating the RHS and then applying the `.ACCEPT` method to the result of that evaluation. So it successfully matches `any('a','b')` producing a junction of match objects `any(「a」, 「b」)`. Then the smart match itself evaluates. And `any('a','b') ~~ any(「a」, 「b」)` is (appropriately I think) `False`. – raiph Nov 02 '20 at 19:48
  • 2
    Golfed. `$/ = any 42; say 'x' ~~ m/./` yields `Cannot modify an immutable...`. – raiph Nov 02 '20 at 19:55
  • @raiph Thanks for that; I've replied more fully [on github](https://github.com/rakudo/rakudo/issues/4002). – grobber Nov 02 '20 at 20:32
  • 1
    This was a bug: fixed with https://github.com/rakudo/rakudo/commit/5b3691817a – Elizabeth Mattijsen Nov 03 '20 at 10:08

2 Answers2

4

The side issue of whether the match should return False or True is settled, I think, in the comment by @raiph.

On the other hand, the main problem of receiving the immutable Match error was, it seems, a bug, with a commit that at least on my system fixes it.

So the problem was (as per the commit message) that regex match objects were not expected to be junctions.

grobber
  • 1,083
  • 1
  • 9
  • 20
  • 1
    "regex match objects were not expected to be junctions". Just to clarify, it's limited to just match objects assigned/bound to `$/` (other scenarios involving match objects being junctions should in theory work, modulo other bugs) when combined with 13 private/internal methods of the `Str` class (other methods should in theory work with `$/`, modulo other bugs). – raiph Nov 02 '20 at 22:28
  • 2
    The problem was not really that they were not expected to be Junctions. The problem was some Match internals processing that passed the `$/` container around for assignment, but which did *not* have a `Mu` constraint. This caused the assignment to be tried to *each* of the eigenstates of the Junction and fail on the first( because eigenstates are immutable) instead of assigning to the container that contained the Junction (and thus replacing it). https://github.com/rakudo/rakudo/commit/5b3691817a fixes that. – Elizabeth Mattijsen Nov 03 '20 at 10:13
1

The following may all be poppycock. But I'm going to publish my immediate reaction, eat dessert, then explore further. :)

Code that works

say any('a','b') ~~ /./; # False
say 'x' ~~ /./;          # 「x」

The difference? I dropped the ms.

Why the difference?

They have different meanings.

What you presumably meant in these cases was to do regex matching of the regexes on the RHS of ~~ against the values on the LHS of ~~.

But I think what you've actually written is sub-expressions on the RHS of the ~~ that first do a regex match against $_, and then a subsequent match (just a smart match, not a regex match) of the result of the preceding regex match (i.e. a match object or Nil) against the values on the LHS of the ~~.

I've yet to explore why you get the immutable stuff but I think the above is a first step. I'll delete this answer later if it turns out to be nonsense. :)

raiph
  • 31,607
  • 3
  • 62
  • 111
  • Thanks; for clarification, I know `'x' ~~ /./` (no `m`) works: I mention this in the post, where I write that running that *first* resets `$/` and "unblocks" `'x' ~~ m/./` as well. – grobber Nov 02 '20 at 19:22
  • Yeah, I see that now I've eaten my dessert. :) Deleting... – raiph Nov 02 '20 at 19:26
  • Now everything's been sorted out, I think it makes sense to undelete this. After all, my analysis, as far as it went, was right, and might be helpful to later readers. In summary, don't write `foo ~~ m/bar/`, because it's not going to do anything sensible. – raiph Nov 03 '20 at 18:09