1

How do you fake conditionals that don't nest in a language that doesn't allow goto? I want to do the following:

if (condition1)
    action1;
if (!condition1 && condition2)
    action2;
if (!condition2 && condition3)
    action3;

Without:

  1. Needlessly evaluating any condition more than once.
  2. Needlessly storing the result of any such evaluation in a variable.
  3. Needlessly specifying more than once that any action should be performed.

The original snippet fails to meet requirement 1.

The following snippet fails to meet requirement 2:

if (condition1) {
    action1;
    c2 = false;
}
else if (c2 = condition2)
    action2;

if (!c2 && condition3)
    action3;

And the following snippet fails to meet requirement 3:

if (condition1) {
    action1;
    if (condition3)
        action3;
}
else if (condition2)
    action2;
else if (condition3)
    action3;

EDIT:

  1. It is impossible that condition1 and condition2 be true simultaneously.

  2. It is impossible that condition2 and condition3 be true simultaneously.

Here is the original code (in JavaScript):

// If only the array of elements was specified,
// wrap it inside an object.
if (info.constructor !== Object)
    info = {children: info};

// If no array of elements was specified, create
// an empty array of elements.
if (!info.children)
    info.children = [];

// If, instead of an array of elements, we have
// a single element, wrap it inside an array.
if (info.children.constructor !== Array)
    info.children = [info.children];
isekaijin
  • 19,076
  • 18
  • 85
  • 153
  • Doesn't your third example also violate the constraint against nested conditionals? – Ted Hopp Feb 28 '11 at 22:02
  • I don't have any constraints against nested conditionals. My only constraints are: "Don't write code more than once" (original restriction 3) and "Don't execute what doesn't have to be executed" (original restrictions 1 and 2). – isekaijin Feb 28 '11 at 22:06
  • Ah, I misunderstood. What does the title of the post mean? – Ted Hopp Feb 28 '11 at 22:09
  • I mean: How to, without using goto, write optimal code that requires goto to make it optimal? – isekaijin Feb 28 '11 at 22:11
  • You didn't state whether action1, action2, action3 need to be called in any particular order ? – Paul R Feb 28 '11 at 22:24
  • If both Action[i] and Action[j] are to be executed, Action[i] must precede Action[j] if and only if i < j. – isekaijin Feb 28 '11 at 22:28
  • Your snippets are not all equivalent (I assume the correct result is also a constraint). If all are true, the first snippet only executes action1. The second and third snippets execute action1 and action2. – jtpereyda Feb 28 '11 at 23:32
  • It is impossible that all conditions are true. That is what allows me to say the snippets are equivalent. – isekaijin Feb 28 '11 at 23:55
  • Coming back years later, I realized that this specific scenario can be solved with only ifs: `if(c2) { a2; } else { if(c1) a1; if(c3) a3; }` (because anything else being true at the same time as c2 is impossible). – Brilliand Jan 30 '18 at 23:17
  • The only thing I realized is that pattern matching and recursion are actually more powerful than if and imperative loops... – isekaijin Jan 31 '18 at 05:17

2 Answers2

3

Truth Table

 C1 C2 C3  Action
 0  0  0   None
 0  0  1   A3
 0  1  0   A2
 0  1  1   A2
 1  0  0   A1
 1  0  1   A1+A3
 1  1  0   A1
 1  1  1   A1

Is switch/case against the rules? :)

switch(C1*4 + C2*2 + C1) {
  case 7: case 6: case 4:  A1; break;
  case 5: A1; A3; break;
  case 3: case 2: A2; break;
  case 1: A3; break;
}
TimFoolery
  • 1,895
  • 1
  • 19
  • 29
1

So how do you do this with goto anyway? This immediately comes to mind, but doesn't have quite the same result:

if(condition1) {
    action1;
    goto a;
}
if(condition2) {
    action2;
    goto b;
}
a:
if(condition3) {
    //This will run if condition1 && condition2 && condition3
    action3;
}
b:

Either way, you do have a few tricks that can break out of nested "if"s. Try:

do {
    if(condition1) {
        action1;
    } elseif(condition2) {
        action2;
        break;
    }
    if(condition3) {
        action3;
    }
} while(false);

It's essentially a goto, but...

That version will duplicate the goto construct that I imagined, rather than the one in the OP. Note that "return" works about the same, in case that looks cleaner in your code (and it might be able to push the hack a bit further by returning a boolean).

Brilliand
  • 13,404
  • 6
  • 46
  • 58
  • The one you imagined was exactly what I was trying to do with `goto`s. I forgot to mention there were impossible combinations of `condition1`, `condition2` and `condition3`. – isekaijin Mar 01 '11 at 00:06
  • I disagree that it "is essentially a goto." It accomplishes the same thing, in this case, but in a completely different way. I like the solution for this problem, but it wouldn't work in more complicated scenarios. – TimFoolery Mar 01 '11 at 00:08
  • In more complicated scenarios, I would "simply" need nested do loops. Ugly, but not as ugly as duplicating code or performing needless comparisons. – isekaijin Mar 01 '11 at 00:11