The following behavior in Red seems pretty reasonable, doesn't it?
red>> str: "aaa"
== "aaa"
red>> parse str [any [remove "a"]]
== true
red>> str
== ""
So why doesn't R3-Alpha do the same?
r3-alpha>> str: "aaa"
== "aaa"
r3-alpha>> parse str [any [remove "a"]]
== false
r3-alpha>> str
== "aa"
Believe it or not, this was by design. The concept is that if a rule doesn't advance the index, it isn't considered "successful":
I am not a fan. A successful rule is one that matched. The REMOVE matched.
While the REMOVE works in Red, it seems there's still some infinite-loop-avoidance through an advancement in the rules:
red>> parse "a" [any [ahead "a"]]
== false
I'm not sure where to draw the line. Personally I'd think that should be an infinite loop. Last I checked, this is a language where infinite loops are possible in a general sense, and it's counter-intuitive to me to see mystery behaviors trying to avoid them
Not excusing this avoidance in any way, but Parse has a checkered past with infinite loops.
Consider in Rebol 2 the difference hitting ESCAPE while performing the following:
parse "" [any []] ; unbreakable infinite loop
parse "" [any [()]] ; breakable infinite loop
This perhaps explains the reluctance to allow unfettered looping. On initial inspection, R3Alpha eventually returns TRUE for parse "" [while []]
βit may be the unbreakable nature of Parse loops were already mitigated(?).
1 Like
Interesting.
Well that has has been recently addressed, so in Ren-C you can break a forever []
(now CYCLE). You'd be able to break an infinite looping PARSE, too.
[] is a match on any input. And I'd like any [] to be an infinite loop.
I mention in my linked post that sometimes decaying to infinite loops is a feature...and here it certainly can be. Consider any [:(...)]. It may be that on one iteration it evaluates to null and hence vaporizes. But on the next pass it might evaluate to a rule which splices.
(Curiously, there's a difference between any [:(...)]
and any :(...)
, because the first evaluates the group on each pass while the second evaluates just once.)
...and with that...I'm convinced...
The progress rule is bad mojo. Let's toss it.
1 Like
Bad cancellation may have played a role, but I found out what the actual reason was:
Ladislav wanted a: [any b] to be an iterative equivalent of the recursive a: [b a |] Then, he wanted this to produce i = 3
:
a: [a |]
parse "" [(i: 0) 3 [["a" |] (i: i + 1)] end]
If you mix all that in with the desire to have any [... | end]
not be an infinite loop, something has to give somewhere. But I think the "no progress" rule is the wrong answer.
I posted my remarks on the issue....that I think this should be the true purpose of the WHILE vs ANY distinction. ANY and SOME will break on END, but a while won't. So it's actually a: [while b] to be an iterative equivalent of the recursive a: [b a |], with ANY and SOME having the historical behavior.
So WHILE actually has a reason to exist, after all. Who knew. 
1 Like