Here is the behavior of changing a REPEAT variable in Rebol2 and R3-Alpha:
rebol2>> repeat n 3 [print "What happens?" n: 3]
What happens?
== 3
Here's that same behavior in Red:
red>> repeat n 3 [print "What happens?" n: 3]
What happens?
What happens?
What happens?
== 3
One might then ask what happens if you set the loop variable to something not even an integer. In Rebol2, it just exits the loop. In R3-Alpha, it errors:
r3-alpha>> repeat n 3 [print "What happens?" n: <boo>]
What happens?
** Script error: tag! type is not allowed here
Is there always a clear meaning?
Not necessarily. What about FOR-EACH?
foreach x [1 2 3] [x: "what should this do?"]
If you put on your imagination hat, you might imagine this as a way to mutate the series being iterated. In that world, changing X would actually change the element in the array. But Rebol's model isn't completely geared for this...though it could be done (by marking the variable with a bit, observing if that bit is cleared in an overwrite, and doing a write-back if clear).
That's not necessarily a bad imagination-hat to have on--though I'd worry about implementing a feature exploiting bit-level knowledge that a user couldn't do themselves. (So it would have to rely on equality, and write back non-equal things--just having an optimization that avoided the test if the bit hadn't been mucked with.)
(Note: C++ can do this through "references", and it is the difference between for (auto x : collection) {...} and for (auto &x : collection).)
But even if you could stretch and come up with a meaning in FOR-EACH, the broader point is it's not always possible. Some iterations that put values in a variable may not be able to sensibly understand a change made to the iteration variable, and interpret it in a way that affects the next iteration.
What about performance?
Red's decision on REPEAT gives it a certain freedom from trying to figure out the meaning of any changes to the variable. The iteration holds internal state--images that into a variable for you---and if you change it that's just for your temporary purposes in the loop. There's no fetch of the loop variable on each iteration, only a write.
But Red clearly thinks it's important enough in FORALL to pay attention to changes to the iterated variable, because that works:
red>> forall data [probe data data: next data]
[1 2 3 4]
[3 4]
== [4]
In fact, in a fairly rare case of Red not repeating a bug in R3-Alpha, they fully fetch the variable each time through the FORALL.
Paying attention to changes to the variable is not going to be the most performant choice. By avoiding the fetch of a potentially modified N in the REPEAT loop above, Red doesn't have to re-fetch the variable on each loop iteration to make sure you didn't change it into a TAG!, or whatever.
But I think it is worth noting that it is now 6 years since R3-Alpha was open sourced, and 7 years since Red's announcement. When you think about making decisions based on "performance", e.g. the speed of a REPEAT loop, choosing something less flexible for purposes of marginal efficiency makes less sense than ever.
Solutions?
Being able to change loop variables allows more patterns of solution. The FORALL case is a good one (Ren-C calls this category FOR-NEXT because you can change the series to whatever you like, and it runs a NEXT on it at each iteration). I think it would be less expressive to not be able to see response from the iteration to a change, and by extension one would argue that changing the index in a REPEAT (or plain FOR) should also have an effect.
Yet I've pointed out it doesn't always make sense--such as in FOR-EACH.
One idea that comes to mind could be to PROTECT any loop variables whose modification cannot semantically be mapped back into meaning for the next iteration. If you find you can't change a variable, then that means that the loop wouldn't be able to react if you did.
I like that because it feels like it's giving feedback to the user about the contract of the loop. Though it might appear to "waste" a variable slot you could otherwise use as a temporary.
What do you think? Should loops lock any variables from modification if they can't meaningfully interpret a modification to affect the next iteration?