Is INTEGER! in PARSE Too Obfuscating?

There's a bit of a problem in the combinator-based UPARSE with the historical convention of an INTEGER! rule, where if you have two integers in a row it indicates a range of how many things to accept.

rebol2> parse "**" [1 2 "*"]  ; between 1 and 2 stars
== true

rebol2> parse "**" [3 4 "*"]  ; between 3 and 4 stars
== false

It doesn't fit into the "natural" pattern of combinators, e.g. where 1 2 RULE is the same as 1 [2 RULE].

That doesn't mean it can't be done...it just means it would have to be part of the BLOCK! combinator specifically to notice integer sequences (vs dispatching to some generic INTEGER! combinator)

But it brought me to a bigger question of how good an idea it is to have something that acts as a keyword be abstractable. I've often been confused when I see something like:

 parse ... [... something rule ...]

And SOMETHING is actually an integer. It isn't a rule in its own right, it's picking up the next rule...like a keyword.

As a reader, I feel like a keyword like REPEAT is missing here. I don't know how much we want to stick to the rule that every word resolve to a parse rule...if we did, then you'd have to escape out of that with the likes of:

 parse ... [... repeat (2) rule ...]
 parse ... [... repeat (something + 1) rule ...]

But perhaps within PARSE, literal integers could be exempted...assumed to never match integers, but be passed as a parameter.

This doesn't answer what to do about ranges of integers (and BETWEEN is taken). But just pointing out that I don't know that the current super-succinct integer syntax pays off all that well. It might be better to be a little more verbose to make it clear that a repetition is happening.

I had a bit of a thought about the naming gap between COUNT-UP and REPEAT, which made me think about what REPEAT might mean that was different.

If REPEAT appeared in PARSE to mean "try and do this N times, otherwise fail" then it could mean that in ordinary code too.

 data: [a b]
 repeat 3 [not null? take data] then [
     print "Successfully took 3 elements"
 ] else [
     print "Failed to take 3 elements"
 ]

It's a thought on how the word might be used consistently. Not necessarily a great thought, just a thought.

2 Likes

If REPEAT appeared in PARSE to mean "try and do this N times, otherwise fail" then it could mean that in ordinary code too.

Or... if LOOP is the arity-2 form of looping which takes a number, what if it was just the generic arity-2 form...and if you gave it a block it assumed that was the condition?

x: 10
loop [x > 0] [
    print "Counting down"
    x: x - 1
]

loop 10 [
   print "Counting down"
]

This would make WHILE like the truthy-based UNTIL...and it would be the same in PARSE and DO.

data: [a b]
while [take data]

Though we've discussed LOOP being a more powerful dialect, due to the short word. Maybe REPEAT should be the arity-1 while-like thing?

repeat [take data]

And then it would make more sense in PARSE if it were arity-1 there too. Anyway, I feel like the inconsistency of WHILE is a bit jarring at the moment.

Consistency on WHILE and UNTIL was an old-ish question which would be resolved if they were both arity-1. I don't know that making LOOP polymorphic w.r.t. BLOCK! vs. INTEGER! was suggested before, though maybe it was.