Recent

Author Topic: how to break out early of a case ?  (Read 66564 times)

440bx

  • Hero Member
  • *****
  • Posts: 4029
Re: how to break out early of a case ?
« Reply #30 on: August 16, 2018, 04:53:58 pm »
Actually you are a bit incomplete in  your explanation: those goto's are assembler jumps generated by the compiler. As such they have little to do with an actual high level language construct.
But your answer is more correct than that babbler. 8-)
The two of you should get a room, share your gotos.
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

lucamar

  • Hero Member
  • *****
  • Posts: 4219
Re: how to break out early of a case ?
« Reply #31 on: August 16, 2018, 05:49:11 pm »
The two of you should get a room, share your gotos.

Nah, all my actual GOTOs (from my BASIC days) are rather old and crumbling, although I've got quite a lot of them preserved in (cassette) tapes.  :D

Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

munair

  • Hero Member
  • *****
  • Posts: 798
  • compiler developer @SharpBASIC
    • SharpBASIC
Re: how to break out early of a case ?
« Reply #32 on: May 02, 2020, 05:58:39 pm »
Safe to say there have been _many_ discussions regarding C's fall-through / break functionality for its switch/case statement.

For a long time I have considered this functionality superfluous and I cannot recall one time that I missed it in any project.

However, now that I have come to the point of implementing a switch equivalent in the SharpBASIC compiler, I must admit that I look differently at the fall-through and break features, although IMO 'break' is not necessarily the best statement to leave a switch because it is also strongly associated with 'breaking' loops while a switch doesn't 'loop'. Likewise, 'fall-through' is also not the best term IMO.

So logically, while trying to implement a switch statement with maximum flexibility, I came up with the following solution, which IMO is much more intuitive and safe; unless the programmer specifically specifies a fall-through case with 'also', no fall-through will occur. The keyword 'done' is used to leave the 'when' block. It adds a total of three keywords to control a switch in SharpBASIC: 'also', 'done' and 'other'. Best of all: it works!
Code: Text  [Select][+][-]
  1.   var n: int = 0;
  2.  
  3.   when n
  4.     is 0 do
  5.       n = 1;
  6.     is 10 do
  7.       n = 0;
  8.     also is 1 do         ' "fall-through"
  9.       n = 2;
  10.       done;              ' leave 'when' block
  11.     also is 2 do         ' "fall-through"
  12.       n = 3;
  13.     is other do
  14.       n = -1;
  15.     end;
  16.  
  17.   print n;               ' 2
keep it simple

lucamar

  • Hero Member
  • *****
  • Posts: 4219
Re: how to break out early of a case ?
« Reply #33 on: May 02, 2020, 06:30:51 pm »
unless the programmer specifically specifies a fall-through case with 'also', no fall-through will occur. The keyword 'done' is used to leave the 'when' block. It adds a total of three keywords to control a switch in SharpBASIC: 'also', 'done' and 'other'. Best of all: it works!
Code: Text  [Select][+][-]
  1.   var n: int = 0;
  2.  
  3.   when n
  4.     is 0 do
  5.       n = 1;
  6.     is 10 do
  7.       n = 0;
  8.     also is 1 do         ' "fall-through"
  9.       n = 2;
  10.       done;              ' leave 'when' block
  11.     also is 2 do         ' "fall-through"
  12.       n = 3;
  13.     is other do
  14.       n = -1;
  15.     end;
  16.  
  17.   print n;               ' 2

The "done" thing (if it is like the break 440bx wanted) is nice, and "is Other" is equivalent to "else" and "otherwise" in Pascal, isn't it? But that "also" ... I mean, that:
Code: Text  [Select][+][-]
  1.     is 10 do
  2.       n = 0;
  3.     also is 1 do         ' "fall-through"
looks a tiny absurd: when "n" is 10, it can't be 1, can it? So, what is it supposed to do?

Granted, you go about changing "n" and that might have some bearing with it but it looks a litle confussing (at least to me).
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

munair

  • Hero Member
  • *****
  • Posts: 798
  • compiler developer @SharpBASIC
    • SharpBASIC
Re: how to break out early of a case ?
« Reply #34 on: May 02, 2020, 06:40:55 pm »
The "done" thing (if it is like the break 440bx wanted) is nice, and "is Other" is equivalent to "else" and "otherwise" in Pascal, isn't it? But that "also" ... I mean, that:
Code: Text  [Select][+][-]
  1.     is 10 do
  2.       n = 0;
  3.     also is 1 do         ' "fall-through"
looks a tiny absurd: when "n" is 10, it can't be 1, can it? So, what is it supposed to do?

Granted, you go about changing "n" and that might have some bearing with it but it looks a litle confussing (at least to me).

I simply inserted the rubbish 'is 10' test to demonstrate that even though a match was found earlier, the 'when' block continues to execute and tests the new definition of n (1) against every 'also is' it finds. So it is not really a "fall through" but more like a "test again" if the programmer specifies a 'also is' test.

C's default fall-through has been a source of many difficult to find bugs. I know because I read about it; I actually never used C myself, not once!

The "done" thing (if it is like the break 440bx wanted) is nice, and "is Other" is equivalent to "else" and "otherwise" in Pascal, isn't it?

Yes, "is other" is equivalent to "else", and it is shorter than "otherwise". Preferably SharpBASIC uses keywords no longer than 6-7 characters.
« Last Edit: May 02, 2020, 06:45:31 pm by munair »
keep it simple

440bx

  • Hero Member
  • *****
  • Posts: 4029
Re: how to break out early of a case ?
« Reply #35 on: May 02, 2020, 06:41:53 pm »
<...> unless the programmer specifically specifies a fall-through case with 'also', no fall-through will occur.
That's the way to do it.  C making the fall-through the default is yet another design atrocity in that language.

A few things for you to consider:
Code: Pascal  [Select][+][-]
  1.   when n
  2.    is     0 do n =  1;
  3.    is    10 do n =  0;  fall;    ' or "fall-through"
  4.    is     1 do n =  2;  fall;
  5.    is     2 do n =  3;
  6.    is other do n = -1;
  7.  end;
  8.  
I'd rather have the fall-through made explicit instead of implicit by the use of a keyword ("also") that doesn't clearly denote it is meant to fall through.

Also (pun intended),  do you really need the "is" ? ... it seems this would be even more readable (possibly also using a single "is" just after the "n" variable being tested):
Code: Pascal  [Select][+][-]
  1.   when n [is]
  2.     0  do n =  1;
  3.    10  do n =  0;  fall;    ' or "fall-through"
  4.     1  do n =  2;  fall;
  5.     2  do n =  3;
  6.  other do n = -1;
  7.  end;
  8.  

Also (again!) one advantage I see to having an explicit "fall" is that the "fall" can then be made conditional, for instance:
Code: Pascal  [Select][+][-]
  1.   when n
  2.     0  do n =  1;
  3.    10  do n =  0;  if <somecondition> then fall;    ' or "fall-through"
  4.     1  do n =  2;  if <somecondition> then fall;
  5.     2  do n =  3;
  6.  other do n = -1;
  7.  end;
  8.  
now falling through has to be explicitly and clearly stated by the use of a keyword that clearly identifies its purpose and in addition to that, falling or not falling is completely under programmer control. I like that part :)

ETA:
Added [is] after the "n" variable to see how the thing would look with it.




« Last Edit: May 02, 2020, 06:46:34 pm by 440bx »
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

lucamar

  • Hero Member
  • *****
  • Posts: 4219
Re: how to break out early of a case ?
« Reply #36 on: May 02, 2020, 06:56:41 pm »
So it is not really a "fall through" but more like a "test again" if the programmer specifies a 'also is' test.

I think I got it, but just to test my understanding: the equivalent in (current) Pascal would then be someting like,
Code: Pascal  [Select][+][-]
  1.   case n of
  2.   0: n = 1;
  3.   10: begin
  4.       n = 0;
  5.       case n of
  6.       1: n = 2;
  7.       2: n = 3;
  8.       end;
  9.     end;
  10.   else n = -1;
  11.   end;
Is that right?
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

munair

  • Hero Member
  • *****
  • Posts: 798
  • compiler developer @SharpBASIC
    • SharpBASIC
Re: how to break out early of a case ?
« Reply #37 on: May 02, 2020, 07:07:44 pm »
I'd rather have the fall-through made explicit instead of implicit by the use of a keyword ("also") that doesn't clearly denote it is meant to fall through.

As I explained in my previous post, it is not really a fall-through, but more like a 'test again' if 'also' is _explicitly_ included. One can skip several 'is' tests and still "fall through" the next "also is".

Quote
Also (pun intended),  do you really need the "is" ?

Please note that the numbers used in the example are not just treated as ordinal constants. Each test is parsed as an expression. So the 'is' keyword - which is similar to 'else' or 'else if' in an IF block - effectively delimits the previous block. It actually replaces the 'end' keyword that would normally mark the end of a 'do..end' block, similar to Pascal's 'begin..end'. IS eliminates any ambiguity syntax-wise and it also makes it more readable IMO (compare IS with C's CASE).

Quote
Also (again!) one advantage I see to having an explicit "fall" is that the "fall" can then be made conditional

You definitely have a point there. I like the word "fall" because it is short. However, the compiler parsing (nested) IF blocks does not automatically communicate with outer 'when' blocks. If the 'fall' instruction would be inside an IF block then that block must somehow tell the 'when' block what to do. It would require a fall-flag to be passed to every control structure (not just Ifs) that can appear inside a when-block.
« Last Edit: May 02, 2020, 07:16:02 pm by munair »
keep it simple

munair

  • Hero Member
  • *****
  • Posts: 798
  • compiler developer @SharpBASIC
    • SharpBASIC
Re: how to break out early of a case ?
« Reply #38 on: May 02, 2020, 07:13:15 pm »
So it is not really a "fall through" but more like a "test again" if the programmer specifies a 'also is' test.

I think I got it, but just to test my understanding: the equivalent in (current) Pascal would then be someting like,
Code: Pascal  [Select][+][-]
  1.   case n of
  2.   0: n = 1;
  3.   10: begin
  4.       n = 0;
  5.       case n of
  6.       1: n = 2;
  7.       2: n = 3;
  8.       end;
  9.     end;
  10.   else n = -1;
  11.   end;
Is that right?

No because the additional "also is" tests do not depend on the "is 10" test. Because n already had a match in the "is 0' test, the "is 10" test is simply being skipped, not just because n <> 10, but because it is not a "also is" test.
keep it simple

munair

  • Hero Member
  • *****
  • Posts: 798
  • compiler developer @SharpBASIC
    • SharpBASIC
Re: how to break out early of a case ?
« Reply #39 on: May 02, 2020, 07:25:49 pm »
A conditional 'fall' can be replaced by an opposite conditional 'leave' for which a jump address is already passed:
Code: Text  [Select][+][-]
  1.   when n
  2.     is 0 do
  3.       n = 1;
  4.     also is 1 do
  5.       n = 2;
  6.       if n == 2 do ' (sic)
  7.         leave;
  8.       end;
  9.     also is 2 do
  10.       n = 3;
  11.     end;

EDIT: 'done' has been replaced by 'leave'.
« Last Edit: May 02, 2020, 08:19:54 pm by munair »
keep it simple

440bx

  • Hero Member
  • *****
  • Posts: 4029
Re: how to break out early of a case ?
« Reply #40 on: May 02, 2020, 08:09:35 pm »
EDIT: 'done' has been replaced by 'leave'.
I like "leave" better.  I think it makes the intention clearer.
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

JdeHaan

  • Full Member
  • ***
  • Posts: 118
Re: how to break out early of a case ?
« Reply #41 on: May 02, 2020, 08:12:04 pm »
I know the discussion is about breaking out of a case statement, but it got my mind spinning. What about a case expression, like this:

Code: Pascal  [Select][+][-]
  1. function Fibonacci(n: Integer): Integer;
  2. begin
  3.   Result := case n of
  4.     <1.  : 0;
  5.      1, 2: 1;
  6.      else Fibonacci(n-1) + Fibonacci(n-2);
  7. end;
  8.  

'else' should be mandatory, to determine the end of the expression.

Sorry for the off-topic...

munair

  • Hero Member
  • *****
  • Posts: 798
  • compiler developer @SharpBASIC
    • SharpBASIC
Re: how to break out early of a case ?
« Reply #42 on: May 02, 2020, 08:18:47 pm »
I know the discussion is about breaking out of a case statement, but it got my mind spinning. What about a case expression, like this:

Code: Pascal  [Select][+][-]
  1. function Fibonacci(n: Integer): Integer;
  2. begin
  3.   Result := case n of
  4.     <1.  : 0;
  5.      1, 2: 1;
  6.      else Fibonacci(n-1) + Fibonacci(n-2);
  7. end;
  8.  

'else' should be mandatory, to determine the end of the expression.

Sorry for the off-topic...

That is another reason why a test should start with a keyword like 'is' or 'case'. It is really similar to the IF structure in this respect. In addition, in the case of SharpBASIC, it allows for syntax like:
Code: Pascal  [Select][+][-]
  1. when n is 1 to 10 do
  2.   print n;
  3. end;
« Last Edit: May 03, 2020, 08:46:46 am by munair »
keep it simple

munair

  • Hero Member
  • *****
  • Posts: 798
  • compiler developer @SharpBASIC
    • SharpBASIC
Re: how to break out early of a case ?
« Reply #43 on: May 02, 2020, 10:11:56 pm »
Am I correct in assuming that if fall-through is not the default like in C, a break / leave statement is not necessary?
Code: Text  [Select][+][-]
  1.   when n
  2.     is 0 do
  3.       n = 1;
  4.       fall;
  5.     is 1 do
  6.       n = 2;
  7.     is 2 do
  8.       n = 3;
  9.     is 3 do
  10.       n = 4;
  11.     end;
« Last Edit: May 03, 2020, 08:42:23 am by munair »
keep it simple

440bx

  • Hero Member
  • *****
  • Posts: 4029
Re: how to break out early of a case ?
« Reply #44 on: May 02, 2020, 10:45:08 pm »
fall through _is_ the default in C, which can be a very annoying characteristic.
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

 

TinyPortal © 2005-2018