Article Publishing
~ language design and messy if statement solution
Often you will have a function with an if statement that you hate, because if statements can make code indented heavily or nested, whereas a procedure/func that reads from top to bottom without wiggling across the screen is easier to read as a human. So, programmers have some solutions (or hacks) to these problems... Use Goto statements to get out of if statements in order to not carry to many control variables or booleans around. Or, use a return statement (or exit in some languages).

Let's try to develop a solution to the problem without resorting to multiple exit path solutions (essentially goto solutions. RETURN is just really a goto.)

The solution? If statement shortforms. Kind of like a case statement you can use later without the issue of setting up a full fledged switch/case statement. Here is how it looks in pseudo code:

(first we show the bad "if nest" we do not want to see in programs)
proc example(max: integer);
var i: integer;
begin
  if (max < 80) and (max > 0) and (NotOdd(max)) then
    if Day = Thursday then
      for i := 1 to max do
        // this nest is deep now and ugly..
        // ...
      end;
    end;
  end;
end;

So a partial solution to this problem is:
 
function Verified(max: integer): boolean;
begin
  result := false;
  if (max < 80) and (max > 0) and (NotOdd(max)) then 
    if Day = Thursday then
      result := true;
    end;
  end;
end;

proc example(max: integer);
var i: integer;
begin
  if Verified(max) then
    for i := 1 to max do
      // this nest is less ugly and deep
      // but it is still a nest, a loop inside an if statement
    end;
  end;
end;

What is an alternative language design that would be more elegant?
What are the drawbacks of supposed elegant request?

Imagine a language that looks as follows:
proc example(max: integer);
var 
  i: integer;
  Verified: LogicLabel;
begin
  // sets up a if statement to use later statement
  Verified := (max < 80) and (max > 0) and (NotOdd(max)) and (Day = Thursday);

  Verified:
    // this code is only executed if the Proceed if check logic is true
    for i := 1 to max do
      // this nest is less ugly and deep
      // ...
    end;
  end;

  !Verified:
    // this code only executed if Proceed logic is false (not Thursday, etc.)
    for i := 1 to max do
      //
      // ...
    end;
  end;

  // more coding ..
  // ..
  print("Status message");

  Verified:
    // it can even be called again later, as it's a shortform that can be reused, 
    // whereas a case statement forces you to use it inside the case statement
  end;
end;

The language specification/standard would have to specify whether the label rechecks the logic when the label is reused, or whether the first original logic check is used and no recheck is done.

How is this different than if statements?
proc example(max: integer);
var 
  i: integer;
  Verified: LogicLabel;
begin

  Verified := (max < 80) and (max > 0) and (NotOdd(max)) and (Day = Thursday);

  if Verified then
    for i := 1 to max do
      // this nest is getting a bit deep
      // ... not sure if I like loops inside if statement nests
    end;
  end;

  if !Verified then
    for i := 1 to max do
      //
      // ...
    end;
  end;
end;

How is this different than a CASE or SWITCH statement as in below?
proc example(max: integer);
var 
  i: integer;
  Verified: boolean;
begin

  Verified := (max < 80) and (max > 0) and (NotOdd(max)) and (Day = Thursday);

  case Verified() of

    true:
      for i := 1 to max do
        // is this nest is less ugly and deep as part of a case statement?
        // it's okay, but is it optimal? 
      end;
    end;
  
    false:
      for i := 1 to max do
        //
        // ...
      end;
  end;
end;

In code you often see goto, exit, or return statements to get out of nesting:
proc example(max: integer);
var 
  i: integer;
  Verified: boolean;
  FoundItem: boolean = false;
begin

  Verified := (max < 80) and (max > 0) and (NotOdd(max)) and (Day = Thursday);

  if Verified then
    for i := 1 to max do
      // this nest is getting a bit deep
      // ... not sure if I like loops inside if statement nests
      // ...
      FoundItem := true; 
    end;
  end;
  
  if FoundItem then return;  // exit function.. this is like a GOTO

  if !Verified then
    for i := 1 to max do
      //
      // ...
    end;
  end;
end;

In the above an alternative is an if check that can get ugly:
  if (!FoundItem) and (!Verified) then // <--- this gets ugly
    for i := 1 to max do
      //
      // ... this nest is starting to annoy...
    end;
  end;

Solution without using GOTO or RETURN (multiple exit points are bad)...
proc example(max: integer);
var 
  i: integer;
  Verified: LogicLabel;
  FoundItem: LogicLabel: false;
begin

  Verified := (max < 80) and (max > 0) and (NotOdd(max)) and (Day = Thursday);

  Verified:
    for i := 1 to max do
      // 
      // ... 
      // ...
      FoundItem := true; 
    end;
  end;
  
  !Verified and !FoundItem:
    for i := 1 to max do
      //
      // ...
    end;
  end;
end;

Is the syntax sugar worthwhile, using a LogicLabel (BooleanLabel)? It avoids ugly if statements.. creates almost a CASE/switch that can be used at any time, reusing an if statement at your will. Avoids using GOTO or return statements... let's the function exit with only one default return path. But is it worth it?

Alternative names: guard labels, reusable logic statements, logic shortform statements, shortform logic labels.

And of course, someone must have thought of something similar in languages already.

If so did they implement it elegantly? Was it worth it? Did it complicate the compiler or was it elegant to parse at compile time? Certainly if you warn the compiler ahead of time with a declaration, it may be much easier to compile, compared to langauges that have automagical type inference or similar features (even Algol had these debates). What did Algol have for solving the deep ugly if nest issues?
Copyright © War Strategists, M.G. Consequences 2009-2017    Help! Edit Page