www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 8622] New: Allow labeled breaks to work on *any* block

reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=8622

           Summary: Allow labeled breaks to work on *any* block
           Product: D
           Version: D2
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: enhancement
          Priority: P2
         Component: DMD
        AssignedTo: nobody puremagic.com
        ReportedBy: monarchdodra gmail.com



D gives the possibility of multiple-breaking out (nested) while/for blocks
using labeled breaks.

I think it would be beneficial to extend this to being able to break out of any
"block", as long as it is labeled:

----
void main()
{
    label: {
      // ..code..
      writefln("code1");
      writefln("break..");
      break label;  // jumps to "here:"
      // ..code..
      writefln("code2");
    }
    // break lands here
    writefln("here");
}
----

The main use case here would actually be to replace the "triangle if" pattern:

----
    if(condition1)
    {
        if(condition2)
        {
            if(condition3)
            {
                if(condition4)
                {
                    //DO SOMETHING
                }
            }
        }
    }
----

Which would become

----
    conditional_block:
    {
        if(!condition1) break conditional_block;
        if(!condition2) break conditional_block;
        if(!condition3) break conditional_block;
        if(!condition4) break conditional_block;
        //DO SOMETHING
    }
----

The usual "workaround" to the "triangle if" pattern is to move it to it's own
function, and *return* from it. The disadvantage is that it burdens the
developer with a whole extra function. The "breakable block" has the advantage
of not breaking the logic flow of the current function.

Another workaround, the "do_while_false" is also possible:
----
do:
{
    if(!condition1) break;
    if(!condition2) break;
    if(!condition3) break;
    if(!condition4) break;
    //DO SOMETHING
}while(false);
----
However, my experience is that this pattern tends to be confusing for readers
that expected a loop: The actual condition "while(false)" is only documented
near the end.

Further more, given both the above workarounds, neither scale should you want
to nest a double break.

Conclusion: Generic breakable labeled blocks. It works better and is
clearer/more verbose.

Thank you/

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Sep 05 2012
next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=8622


Andrei Alexandrescu <andrei metalanguage.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |andrei metalanguage.com



07:59:03 PDT ---
This is a sensible feature. However, it has several workarounds and doesn't
enable new patterns. I think we should make additions to the language only if
they have major usefulness.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Sep 05 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=8622




Got it. Thanks.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Sep 05 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=8622




This feature is related to an "expectation bug", in that current spec is very
counterintuitive regarding labeled blocks. I added a couple of "See Also" bugs
where the current behavior of labeled blocks has tripped people up. The
problems are best demonstrated by a code sample (taken from those issues):


    // Problem 1 (not a bug according to spec, but entirely counterintuitive).
    int n;
  label:
    {
        scope(exit) n++;
        n=3;
    }
    writefln("n=%d should be 4", n); // Prints "n=3 should be 4"



    // Problem 2: (counterintuitive AND a bug because should not compile).
  block:
    {
        for (int i = 0; i < 10; i++) {
            if (i == 5) break block;
        }
        writefln("Within block");   // This line IS printed.
    }
    writefln("Outside block");


The common problem for both cases is that a labeled block adds curly braces,
but the code behaves as if the braces weren't there.

In particular, adding a label to a block makes the block's scope disappear.
Consider how the first example would change if "label:" line is commented out.

That trips people up. It could be solved perhaps by simply prohibiting labels
on a block, but monarchdodra's suggestion seems like an really nice solution,
allowing for very intuitive flexibility (e.g. the second example is equivalent
to python's "else" clause on loops, more intuitive, and nearly as concise).

(Note that monarchdodra's suggestion critically depends on labeled blocks.
Unlabeled breaks definitely need to break out of the innermost loop or switch.)

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Dec 19 2012
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=8622





 This is a sensible feature. However, it has several workarounds and doesn't
 enable new patterns. I think we should make additions to the language only if
 they have major usefulness.
Implementing this isn't really an addition to the language, it's the removal of a restriction. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
May 29 2013