Novices using Rebol2 or Red aren't really clear on how their RETURN works. (Or doesn't work, as the case may be.) RETURN climbs the stack until it finds a function that is willing to accept returns.
Functions in Rebol2/Red that won't accept returns: IF, WHILE, or pretty much any native
Functions in Rebol2/Red that will accept returns: any user FUNC you write
To give a brutally simple example, you cannot implement UNLESS in terms of IF:
rebol2>> foo: func [x] [if not x = 10 [return "not 10"] return "it's 10!"]
rebol2>> foo 20
== "not 10"
rebol2>> unless: func [cond block] [if not cond block]
rebol2>> bar: func [x] [unless x = 10 [return "not 10"] return "it's 10!"]
rebol2>> bar 20
== "it's 10" ; D'oh
That UNLESS, because it's a FUNC and not a native, is a candidate for receiving RETURN. So the UNLESS itself returned "not 10" instead of returning from bar. Execution continued and the `return "it's 10!" ran. I maintain that correct behavior constitutes another must-have, and I was by no means alone in this, nor the first to say so.
>> unless: lambda [cond block] [if not cond (block)] ; see note re: group!
>> bar: function [x] [unless x = 10 [return "not 10"] return "it's 10!"]
>> bar 20
== "not 10"
I do not consider annotating UNLESS to say "I'm the kind of thing that doesn't catch returns" to be remotely acceptable. I'd sooner throw out the project than go that route. Addressing definitional returns wasn't at all trivial...even though conceptually it was understood what needed to be done. It was one of the first things I tried to do in open-sourced R3-Alpha. The rearranging I had to do in order to understand the code well enough to accomplish it laid the groundwork for many features to come.
(Note: The reason you have to put a group! around block is due to soft-quoted branching, and I argue for the tradeoff here.)
"Maybe crazy: bind every return & exit the same way we do bind function arguments/locals, so that they know their scope from the context they are bound to. But then if we write code: [return 1] f: does [do code] it won't work. Trading one limitation for another, plus likely more complexity in interpreter code. And we can't bind break/continue as there is no context for loops..."
I'll point out that in Ren-C you don't trade one limitation for another, because binding propagates from tips of lists downward in evaluation, giving unbound material meaning as it descends. So unless you explicitly bound a RETURN word in a block, it will get its meaning from context, even if definitional.
Making return able to not take an argument (func [...] [if ... [return] ...]) avoids needing a separate definitional EXIT. Also, it's nice to retake the word EXIT for other things.
unless implemented via if is the minimal falsifying test for "control constructs are just functions," and it should appear in every Redbol's documentation as a known-broken example. It doesn't appear in any of them.
The aggravating factor is that it fails silently. No error, no warning — just "it's 10!" when you asked for "not 10". Silent wrong answers are a worse class than errors, and this one sits at the exact point where a user is being encouraged to extend the language.
(You credited this was an R3-era argument, made by people who had the diagnosis right years before Ren-C existed. The shipped semantics went the other way. That makes this a case of analysis that existed and didn't land — which is a harder story than nobody having noticed.)