Page 1 of 2

break from if

PostPosted: Wed Jan 29, 2014 10:00 pm
by kobi7
Sometimes I wish there would be a 'break from if' statement.
the same idea of what you have with branches, only arbitrary predicate.
for example if you have some code after the "if-else ladder", or you just prefer one return statement for the whole function, but you don't want your code to go deep in ifs.
one option is to use early return, and keep shallow "if ... return, if ... return", taking into account that subsequent ifs are already elses to the first, since it has a return statement there.

I think an additional construct that jumps to the result could make code more readable. (kind of like what is done with require and ensure, pre and post code)

I know this is a somewhat exotic feature request.
what do you think?
examples can follow if you desire. (I have a real one too)

Re: break from if

PostPosted: Thu Jan 30, 2014 12:45 am
by Charles
I think you'll need examples to show exactly what you want and why.

Re: break from if

PostPosted: Sat Feb 01, 2014 5:33 am
by hopscc
I'm guessing its this sort of thing
Code: Select all
block:
    if conda
       doA
       doB
    else if condB
       doBA
       doBB
       break
    if condC
        doCA
        doCB
       break
    doSomethingElse
 


Actioned now using a subroutine
def doX
if .condA
.doA
.doB
else if .condB
.doBA
.doBB
return
if .condC
.doCA
.doCB
return
.doSomethingElse

or with some temp vars and conditions

if .condA
.doA
.doB
else if condB
.doBA
.doBB
ret1 = true
if ret1, return
if condC
.doCA
.doCB
ret2 = true
if ret2, return
.doSomethingElse

Re: break from if

PostPosted: Thu Feb 06, 2014 8:37 am
by kobi7
before I know how it should look, does anyone think it's a good idea. I am not sure myself.
to explain, the idea was to have a block of code, inside a function, that would get executed last and return the value.
similar to ensure, the section could be called 'post'. after a function changes some variables, it may call e.g. 'finish' then the code would continue from the post section, do something with the variables and return the value.
this "do something with the variables" is supposedly common to all the cases. thus refactoring further.

def someMethod(x as int, y as int) as Tuple<of int,int,int>
d as int
if x < y
d = 2*x
finish
if 2*y > x**2
d = 8*y - 3*x
finish
if ... (x10)
.....
post
res = Tuple<of int,int,int>(x,y,d)
# maybe something else
return res

looking at it, it looks very similar to branching cases, only with an arbitrary condition.

Re: break from if

PostPosted: Thu Feb 06, 2014 1:10 pm
by Charles
How does it differ from try..finally ?

Re: break from if

PostPosted: Fri Feb 07, 2014 5:47 am
by kobi7
Charles wrote:How does it differ from try..finally ?


it's almost identical, except for returning results.
to be honest, I am not sure it's a good idea. it introduces a new code-flow structure.
it may be going towards pattern matching.

what do you think, and does it look/smell good, if this would have been a type of branching.
branch a,b,c # all the variables that participate
on a < b <= c
.do1
on a**2 - c > 0
.do2
on c > a
.do3(c)

Re: break from if

PostPosted: Sun Feb 09, 2014 7:41 pm
by hopscc
just try-finally wont get you the step-over-some-code effect
need to throw and catch as well
def someMethod(x as int, y as int) as Tuple<of int,int,int>
d as int
try
if x < y
d = 2*x
# what goes here
if 2*y > x**2
d = 8*y - 3*x
# what goes here?
if ... (x10)
.....
finally
res = Tuple<of int,int,int>(x,y,d)
# maybe something else
return res


would have to do sommat like
def someMethod(x as int, y as int) as Tuple<of int,int,int>
d as int
jumpNormalFlow = AbortCodeFlowException() # special purpose exc
try
if x < y
d = 2*x
throw jumpNormalFlow
if 2*y > x**2
d = 8*y - 3*x
throw jumpNormalFlow
if ... (x10)
.....
catch AbortCodeFlowException
pass # swallow exception cos we just want the aborted execution flow
finally
res = Tuple<of int,int,int>(x,y,d)
# maybe something else
return res


Generally not reccommended

Its actually just a forward goto :shock:
def someMethod(x as int, y as int) as Tuple<of int,int,int>
d as int
if x < y
d = 2*x
goto finish
if 2*y > x**2
d = 8*y - 3*x
goto finish
if ... (x10)
.....
finish: # invented format for a label
res = Tuple<of int,int,int>(x,y,d)
# maybe something else
return res


Can do this now with an infinite loop with one pass and judicious escaping:
def someMethod(x as int, y as int) as Tuple<of int,int,int>
d as int
while not onepassDone
onepassDone = true # exit at end of loop
if x < y
d = 2*x
break
if 2*y > x**2
d = 8*y - 3*x
break
if ... (x10)
.....

res = Tuple<of int,int,int>(x,y,d)
# maybe something else
return res


? Formalise perhaps as an explicit block thats escapable?
def someMethod(x as int, y as int) as Tuple<of int,int,int>
d as int
block # new keyword denoting an anonymous block of code
if x < y
d = 2*x
break # break out of the nearest enclosing block
if 2*y > x**2
d = 8*y - 3*x
break
if ... (x10)
.....

res = Tuple<of int,int,int>(x,y,d)
# maybe something else
return res


Which is clearer?
How necessary/useful/commonly used is this actually?

Re: break from if

PostPosted: Mon Feb 10, 2014 1:37 am
by nerdzero
hopscc wrote:Its actually just a forward goto

Yeah, I think this is what that would boil down to. Sometimes I miss goto statements. Simpler days...okay maybe not all the time :) http://xkcd.com/292/

Kobi, you want a way to bail out from a deeply nested if but always calling some common code before returning; that way you can have a single return statement in the method, right?

It's ultimately a style issue. I used to be very anti-multiple return statements but eventually my taste changed when I kept having to go very deep in if statements and write redundant code or helper methods in else clauses.

I'm not sure it makes sense to have this as a language feature because you generally don't realize you need this kind of construct until it's too late (i.e. the code is probably already in need of restructuring by that point).

Re: break from if

PostPosted: Mon Feb 10, 2014 3:03 am
by hopscc
I'm not sure it makes sense to have this as a language feature


Me neither,
Well there are ways of doing this now - but they are relatively ugly - perhaps thats a good thing
perhaps if the situation is common enough or the structure useful enough then having a specific feature would both make
use more acceptable and more obvious ( clarify intent...)

I've wondered a couple of times of the utility of an anon block tho...
Obvious other uses:
  • constrain variable dcl to a more limited scope
  • holder for anon code (to ref for lambdas, closures and anon functions)

Re: break from if

PostPosted: Mon Feb 10, 2014 3:35 pm
by Charles
hopscc wrote:just try-finally wont get you the step-over-some-code effect
need to throw and catch as well

Or slap some "else" keywords before all those "if"s inside the "try" that came before the "finally". Unless I'm reading that example poorly.

Like nerdzero, I will "return" where needed. On a related note, I will use nested methods, often with similar names and the "if...return" in the nested method:

class A

def foo(i as int) as int
# <set up code here>
r = _foo(i)
# <finishing up code here>
return r

def _foo(i as int) as int
if ...
return ...
if ...
return ...
if ...
return ...
return 2 * i