-3

This is a derivate of C, so please don't get all angry that it doesn't look correct. It is indeed correct in this implementation.

I have this code:

func() {
    if (handler_1()) goto good;
    if (handler_2()) goto good;
    if (handler_3()) goto good;

    print("BAD");
    goto done;

good:
    print("GOOD");
    goto done;

done:
    print("DONE");
    // do some common stuff
}

I am not particularly happy with the gotos and labels, so I tried to use a do-while instead, but one GOTO is still left.

func() {
    do {
        if (handler_1()) break;
        if (handler_2()) break;
        if (handler_3()) break;

        print("BAD");
        goto done;
    } while(false);

    print("GOOD");

done:
    print("DONE");
    // do some common stuff
}

Note - the language does not use short circuit evaluation:

handler_1() || handler_2() || handler_3()

Would execute always all three handlers before checking the return values. I do not want that.

Available structures: SWITCH, GOTO, LABEL, FOR, WHILE, DO-WHILE, IF_ELSEIF_ELSE. It's also possible to make local variables.

Any ideas how to rewrite this code without using GOTO?

MightyPork
  • 18,270
  • 10
  • 79
  • 133

8 Answers8

7

I'd recommend using a similar syntax to what you often see in the linux kernel.

func() {
    if (!handler_1())
        goto fail;
    if (!handler_2())
        goto fail;
    if (!handler_3())
        goto fail;

    print("success");
    return 0;

fail:
    print("failure");
    return -1;
}
Bill Lynch
  • 80,138
  • 16
  • 128
  • 173
6

here's one variant

func() {
    int good = 0;

    if (handler_1()) 
        good = 1;
    else if (handler_2()) 
        good = 1;
    else if (handler_3()) 
        good = 1

    if (good) {
       print("GOOD");
    } else {  
       print("BAD");
    }

    print("DONE");
    // do some common stuff
}
nos
  • 223,662
  • 58
  • 417
  • 506
  • This looks good. Just one thing, you can use default good = 1, empty statements in the ifs, and good = 0; in the last else. I think. – MightyPork Sep 12 '14 at 18:05
  • @Quentin that would be preferred, but the OP doesn't have a suitable || operator – nos Sep 12 '14 at 19:27
4

Compare this to some of the awful alternatives offered:

handle() {
    if (handler_1()) return true;
    if (handler_2()) return true;
    if (handler_3()) return true;
    return false;
}

func(){
    print(handle() ? "GOOD" : "BAD");
    print("DONE");
    /// do some common stuff
}
Jim Balter
  • 16,163
  • 3
  • 43
  • 66
3

Easy, use a sub-function:

handler_any() {
    if(handler_1())
        return 1;
    if(handler_2())
        return 1;
    return handler_3();
}

func() {
    if (!handler_any()) {
        print("BAD");
    } else {
        print("GOOD");
    }
    print("DONE");
    // do some common stuff
}
Deduplicator
  • 44,692
  • 7
  • 66
  • 118
2
func() {  
   if (handler_1() || handler_2() || handler_3())  
     print("GOOD");   
else  print("BAD");
print("DONE");
    // do some common stuff
}  

I didnt try the code above, but i believe it works. Dont forget to check if this is what you really want your program to do, because maybe I've got the idea wrong.

Btw, i hope i help you, and im sorry about my bad english. Good luck!

Quik19
  • 352
  • 3
  • 13
  • This would be OK in regular C, but here all functions in expression are evaluated first, and after that the expression is checked - so all handlers would be called each time. They are quite slow and call is expensive, so I'd rather avoid that. – MightyPork Sep 12 '14 at 18:27
1

Change this

if (handler_1()) goto good;
if (handler_2()) goto good;
if (handler_3()) goto good;

bad:
    print("BAD");
    goto done;
good:
    print("GOOD");
    goto done;

to something like

bool good = true;
if (!handler_1()) {
  if (!handler_2()) {
    if (!handler_3()) {
      good = false;
    }
  }
}
if (good) {
  printf("Good");
} else {
  printf("Bad");
}
printf("Done");
Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
  • 2
    Adding flag variables just makes the code confusing. Gotos are just fine. – Ira Baxter Sep 12 '14 at 17:50
  • so you want to make fhe code less readable just so that you can call a goto something else. That is one horrible idea – camelccc Sep 12 '14 at 17:52
  • @IraBaxter Edsger Dijkstra might disagree with you (I agree that it's not unreasonable here), but OP specifically asked for a method without goto or label. – Elliott Frisch Sep 12 '14 at 17:52
  • 2
    @camelccc Why is answering OP's question something that I *want*? – Elliott Frisch Sep 12 '14 at 17:53
  • 1
    @ElliottFrisch: You know Dijkstra published that when structured programming just got started? It was not against the occasional `goto`, but against everywhere and always using `goto`. Also, I don't think he ever preached **convoluted coding for dogmatic avoidance of `goto` 101**. – Deduplicator Sep 12 '14 at 18:05
  • @Deduplicator I said *might*, also it's what OP *asked* for. Finally, JWZ isn't totally against regular expressions; despite [*Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems.*](http://regex.info/blog/2006-09-15/247) – Elliott Frisch Sep 12 '14 at 18:19
  • good = handler1() || handler2() || handler3(); is faster than if-branching. – Silviu Burcea Sep 12 '14 at 21:29
  • @SilviuBurcea Read OP's **note** in the question; *the language does not use short circuit evaluation*. – Elliott Frisch Sep 12 '14 at 22:16
  • @SilviuBurcea "is faster than if-branching" -- the compiler generates branches for both. – Jim Balter Jan 17 '17 at 23:12
1

Use a flag variable is_good to indicate:

func() {
    int is_good = 0;

    if (handler_1()) is_good = 1;
    else if (handler_2()) is_good = 1;
    else if (handler_3()) is_good = 1;

    if (is_good == 1) 
    {print("BAD");}
    else
    {print("GOOD");}


    print("DONE");
    // do some common stuff
}
dgg32
  • 1,409
  • 1
  • 13
  • 33
0

This code without gotos and without any flags, will work fine

func() {
        if (!handler_1()) {
                if (!handler_2()) {
                        if (!handler_3()) {
                                print("BAD");
                        }
                        else {
                                print("GOOD");
                        }
                }
                else {
                        print("GOOD");
                }
        }
        else {
                print("GOOD");
        }

        print("DONE");
        // do some common stuff
}