REBOL3 tracker
  0.9.12 beta
Ticket #0000539 User: anonymous


TypeBug Statuswaiting Date16-Jan-2009 21:55
Versionalpha 31 CategoryUnspecified Submitted byBrianH
PlatformAll Severityblock Prioritynormal

Summary No [throw] attribute: Mezzanine control functions capture RETURN and EXIT
Description The USE mezzanine needs to add the R3 equivalent of the R2 [throw] function attribute to the closure it creates and executes. What is the new way of specifying this in function specs?

This also affects DO of string/file/url (#904), MODULE and MAKE module! (both), CONTEXT, OBJECT, COLLECT, DP and DT, FIND-ALL (#1718), the proposed ANY-OF and ALL-OF (#637) and KEEP-EACH (#1733), and all other potential mezzanine control and loop functions.
Example code


Assigned ton/a Fixed in- Last Update10-May-2015 08:52

20-Jan-2009 04:34

There needs to be some equivalent to the R2 [throw] function attribute, and this should be discussed in R3 chat.

This bug and #447 are significant regressions compared to R2.
3-Jun-2009 17:12

The lack of a [throw] attribute or some R3 equivalent is blocking every potential mezzanine control or loop function.
Changed severity to: block.
2-Nov-2010 22:34

Changed the ticket to better reflect the scope of the problem. There is a discussion of possible solutions to this problem here:

The COLLECT and USE functions are particularly interesting because they are affected by this bug in two different ways in the same function. The proposal to make RETURN and EXIT be bound to a scope at function creation time would solve the problem with the outer function in COLLECT or USE, but still cause a problem for their inner functions.
3-Nov-2010 06:46

in the core-tests suite
23-Mar-2013 16:45

I do agree that this is blocking. Until resolved R3 should not turn beta in my opinion.
23-Mar-2013 17:08

There has been one advantage to this: It is forcing us to change control functions into native code. That makes R3 faster, and it's not that big a deal when R3 is open source (it was a really big problem before then). Not saying that we shouldn't fix this, just that it accidentally has one good side effect.

Btw, Carl has made it clear that we are unlikely to get the same syntax for this option, since he wants to switch to using set-words for these kinds of function options, like return: is used for routines in R2. Also, the word "throw" is no longer appropriate because returns are no longer thrown, and wasn't appropriate before either because it made no sense unless you knew how returns were implemented in R2 internally. So we need a suggestion for what to call this option before we can fix this.
1-Apr-2015 17:53

As we debate questions like "Plan Minus Four" and other issues...

...going to agree with @Ladislav and others saying that not being able to write effective loop wrappers is blocking. This problem is a fundamental challenge to the basic premises of the language.

Looking for BREAK and CONTINUE is something that functions that wish to consider themselves looping constructs must actively do. Yet we can see that the bias of RETURN must be the opposite...a function should catch it unless told not to. It must be possible to throw a return "past" a function sometimes...BUT the same function might want to sometimes throw past, and sometimes not.

Because we don't have a canon example (that I know of) to really capture it, I'll propose one. Imagine UNLESS did not exist, and someone decided to implement it (they shouldn't need a C compiler to do so). For the sake of discussion let's say they write it like this:

unless: function [condition false-branch] [
    if condition [return none]
    result: none
    forever compose [
        set/any 'result (to-paren false-branch)

(Let's put aside the idea that it is a "crazy" implementation for this particular task. It is simple enough to understand, and applies to cases that are not "crazy" it's a good case to study.)

We see a clear problem in the expectations and handling of `foreach x [1 2 3] [unless x < 2 [break]]` and `foreach x [1 2 3] [unless x < 2 [return]]`. Both the BREAK and the RETURN living in FALSE-BRANCH want to escape their contexts and have the meaning based on where the source was passed in. Yet the BREAK and the RETURN in the body of UNLESS do *not* want to escape.

If we start here we can discuss whose responsibility it is to express what, and what the language limits are to having one's cake and eating it too are here. I don't have a complete solution in mind yet, just some thoughts, and wanted to see if I could elicit what existing thought would propose to the author who wished to use roughly such an implementation would be.
2-Apr-2015 01:01

There's an extensive write-up (examples included) that distils down even more extensive discussions of this issue over the years:

In my perception, we have reached something looking like consensus over using one of the last two options (that is: "Definitional return only, with an option to not redefine RETURN and EXIT" or "Definitional return, with an option to not redefine RETURN and EXIT, dynamic return as a fallback") has emerged. One of the main remaining problems is how to name the function attribute to disable redefinition of RETURN and EXIT.

As an aside: for the purpose of _this_ ticket, BREAK and CONTINUE are non-issues. Simply because you can be careful about how you use loops in your wrapper, but you _can't_ do much about using a FUNCTION! for writing a wrapper function. That said, making dealing with BREAK and CONTINUE easier is certainly something that could be discussed. But under a separate ticket, please.
2-Apr-2015 01:10

Based on some recent attempts of explaining the issue and the proposed fixes, I propose a new name for a "disabling" attribute (for solutions which need it):

- transparent
10-May-2015 08:52

Other suggestions for the attribute name from above wiki article:

- throw (R2 legacy)
- fallthrough
- no-local-return

And another suggestion which @HostileFork and I came up with on SO chat:

- passthru

Date User Field Action Change
14-Sep-2015 10:27 abolka Comment : 0004641 Modified -
10-May-2015 08:52 abolka Comment : 0004641 Modified -
10-May-2015 08:52 abolka Comment : 0004633 Modified -
10-May-2015 08:52 abolka Comment : 0004641 Added -
2-Apr-2015 01:10 abolka Comment : 0004633 Added -
2-Apr-2015 01:02 abolka Comment : 0004632 Modified -
2-Apr-2015 01:01 abolka Comment : 0004632 Added -
1-Apr-2015 17:53 fork Comment : 0004631 Added -
23-Mar-2013 17:11 BrianH Comment : 0003727 Modified -
23-Mar-2013 17:08 BrianH Comment : 0003727 Added -
23-Mar-2013 16:45 Ladislav Comment : 0003726 Added -
3-Nov-2010 07:46 abolka Comment : 0002747 Removed -
3-Nov-2010 06:46 Ladislav Comment : 0002769 Added -
3-Nov-2010 06:43 Ladislav Comment : 0002768 Removed -
3-Nov-2010 06:42 Ladislav Comment : 0002768 Added -
2-Nov-2010 22:36 BrianH Comment : 0002766 Modified -
2-Nov-2010 22:34 BrianH Comment : 0002766 Added -
2-Nov-2010 22:23 BrianH Description Modified -
2-Nov-2010 22:17 BrianH Description Modified -
2-Nov-2010 22:04 BrianH Description Modified -
2-Nov-2010 22:01 BrianH Category Modified => Unspecified
2-Nov-2010 22:01 BrianH Description Modified -
2-Nov-2010 22:01 BrianH Summary Modified No [throw] attribute: USE captures RETURN and EXIT => No [throw] attribute: Mezzanine control functions capture RETURN and EXIT
2-Nov-2010 03:27 abolka Comment : 0002747 Added -
3-Jun-2009 17:13 BrianH Comment : 0000898 Modified -
3-Jun-2009 17:13 BrianH Comment : 0000898 Modified -
3-Jun-2009 17:12 BrianH Comment : 0000898 Added -
3-Jun-2009 17:09 BrianH Summary Modified USE captures RETURN and EXIT => No [throw] attribute: USE captures RETURN and EXIT
3-Jun-2009 17:08 BrianH Severity Modified major => block
20-Jan-2009 04:34 BrianH Comment : 0000340 Added -
20-Jan-2009 04:30 BrianH Status Modified submitted => waiting
16-Jan-2009 21:55 BrianH Ticket Added -