语言设计(异常):为什么要使用 `try`?

3
在我所了解的语言中(包括C++,Java,Javascript,Python,PHP等),我总是看到有try或类似的东西来标记catch的范围。我想知道这是否必要。如果没有try块会有哪些设计问题呢?
例如,考虑下面的代码:
try{
    try{
        do_something_dangerous0();
    }catch (SomeProblem p){
        handle(p);
    }
    try{
        do_something_dangerous1();
    }catch (SomeProblem p){
        handle(p);
    }
}catch (SomeOtherProblem p){
    handle(p);
}

我想象这是一个替代选择。
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);
}

如果你想避免块捕获“太多”,你可以创建一个新的作用域:

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);
}

(我对为什么这个方法无法适用于C++和Java等语言的答案在下面发布,但我没有针对动态语言的答案。)

我不是已经用“如果你想避免一个块捕获“太多”…”来解决了吗? - leewz
在这种特定情况下,你需要使用try代码块,因为你试图做一些需要比当前范围更深的语义要求。如果它足够大以影响清晰度,你可以评论该代码块,但它不必变得不清晰。我正在询问的是,在不需要语义上所需的更深范围的情况下(例如整个函数的catch),使更深层次的范围变为可选的问题。 - leewz
那么你就省了5个字符?但代价是更不规则的语法? - Hot Licks
如果你决心要学习这个,你应该阅读Goodenough - Hot Licks
是的,你可以重新定义一种语言。你也可以消除if语句并用while/break替换它。有很多事情你可以做。但是,计算机语言应该尽可能易于阅读和理解,让人们为了查找catch语句的开头大括号而费力不应该是朝着这个方向取得进展的。 - Hot Licks
显示剩余11条评论
1个回答

4
它对于需要变量声明的语言将无法使用。
try块中的任何语句都可能未能完全执行,包括变量声明和初始化。在具有块作用域的语言中,尤其是需要变量声明的语言,如C ++、Objective C和Java,catch块不共享try块的作用域,因此不允许访问try块的局部变量。无try系统将打破作用域规则。
例如,这是有效的C++代码。
try{
    int x = some_func();
    int y = some_other_func();
}catch(SomeException){
    //...
}

如果将这个转换为,
int x = some_func();
int y = some_other_func();

catch(SomeException){
    //...
}

然后,在大括号作用域规则下,即使可能尚未被声明/初始化,xy也在catch块中可见。
您可以更改作用域规则,以便catch不会看到这些变量声明,但这是一个非常简单和普遍的规则,为节省约七个字符(try{\n }\n)而引入了重大复杂性。您可以使在catch作用域外立即进行变量声明无效,但是在没有像try块这样的东西的情况下,您将无法做任何事情。还可以要求在运行可能抛出异常的任何内容之前声明作用域内的所有变量(类似于旧版C),但这会减少编写代码的自由度并使其更难阅读。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接