哈维尔在我早期的答案中(引用Wordsworth的答案)发表了一个有趣的评论:
我认为while(true) {}比while(condition){}更具“纯度”。
我无法在300个字符内做出充分回应(抱歉!)
在我的教学和指导中,我非正式地将“复杂性”定义为“我需要记住多少其他代码才能理解这一行或表达式?” 我需要记住的东西越多,代码就越复杂。 代码告诉我的东西越明确,复杂度就越低。
因此,为了降低复杂性,让我从完整性和强度而非纯度的角度回答哈维尔。
我认为这段代码片段:
while (c1) {
// p1
a1;
// p2
...
// pz
az;
}
同时表达两个事情:
- 只要保持为真,整个循环体将会一直重复执行;且
- 在执行时刻1,保证为真。
这两种方式的区别在于视角不同;第一种与整个循环的外部、动态行为有关,而第二种有助于理解我在思考特定的时刻1时可以依赖的内部、静态保证。当然,的净效应可能会使失效,需要我更加深入地思考我在时刻2可以依赖什么等。
让我们放置一个具体的(微小)示例来思考条件和第一步操作:
while (index < length(someString)) {
char c = someString.charAt(index++);
...
}
“外部”问题是,循环显然在
someString
内部执行某些只有在
index
定位在
someString
中时才能完成的操作。这种情况下,我们期望会在循环体内(位置和方式在检查循环体之前是未知的)修改
index
或
someString
,以便最终终止循环。这为思考循环体提供了背景和期望。
“内部”问题是,在点1后面的操作是合法的,因此在阅读点2处的代码时,可以考虑使用已经被合法获得的char值来做什么。(如果
someString
为空引用,我们甚至不能评估条件,但我还假设我们在这个示例的上下文中已经进行了保护!)
相比之下,以下形式的循环:
while (true) {
// p1
a1;
// p2
...
}
让我对两个问题都感到失望。在外部层面上,我不确定这是否意味着我应该期望这个循环永远循环下去(例如操作系统的主事件分派循环),还是有其他事情发生。这使我既没有阅读正文的明确上下文,也没有关于何时结束的进展预期。
在内部层面上,我绝对没有任何关于可能在点1处发生的任何情况的明确保证。条件“true”,当然在任何地方都是真的,是我们可以在程序中任何时候知道的最弱陈述。了解行动的前提条件是非常有价值的信息,当试图思考行动所完成的内容时!
因此,根据我上面描述的逻辑,我建议while (true) ...
习惯用法比while (c1) ...
更加不完整和薄弱,因此更加复杂。