Question

In the languages where I've seen exceptions (C++, Java, Javascript, Python, PHP, ...), I always see try, or something similar, to mark the scope of a catch. I wonder if it's necessary. What are the design issues with NOT having try blocks?

For example, take this:

try{
    try{
        do_something_dangerous0();
    }catch (SomeProblem p){
        handle(p);
    }
    try{
        do_something_dangerous1();
    }catch (SomeProblem p){
        handle(p);
    }
}catch (SomeOtherProblem p){
    handle(p);
}

I imagine this as an alternative.

do_something_dangerous0();

catch (SomeProblem p){
    handle(p);
}

do_something_dangerous1();

catch (SomeProblem p){
    //catches from only the second unless the first also threw
    handle(p);
}

catch (SomeOtherProblem p){
    //catches from either, because no other block up there would
    handle(p);
}

If you want to avoid a block catching "too much", you can make a new scope:

do_something_dangerous2();

{
    do_something_dangerous3();

    catch (SomeProblem p){
        //does not catch from do_something_dangerous2()
        //because if that throws, it won't reach in here
        handle(p);
    }
}

catch (SomeProblem p){
    handle(p);
}

catch (SomeOtherProblem p){
    handle(p);
}

(My answer for why this won't work for languages like C++ and Java, at least, is posted as an answer below, but I don't have an answer for dynamic languages.)

No correct solution

OTHER TIPS

It wouldn't work for languages which require variable declarations, at least.

Any statement in the try block may fail to fully execute, including declarations and initializations of variables. In languages with block scoping, especially languages that require variable declarations like C++, Objective C, and Java, the catch block does not share the scope of the try block, so it is not allowed to access the try's local variables. The try-less system would break scoping rules.

For example, this is valid C++ code.

try{
    int x = some_func();
    int y = some_other_func();
}catch(SomeException){
    //...
}

If this were converted to,

int x = some_func();
int y = some_other_func();

catch(SomeException){
    //...
}

then, under the brace scoping rules, x and y are in-scope for the catch block, even though they might not be declared/initialized yet.

You can change the scoping rules so that the catch won't see those variable declarations, but that's a major complication of a very simple and pervasive rule to save on about seven characters (try{\n }\n). You can make it so that you can't do variable declarations immediately outside the scope of a catch, but then you can't do much without something like try blocks anyway. You can require all variables in a scope to be declared before running anything that can throw (similar to old C), but that takes away some freedom in structuring code and makes it harder to read.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top