Хавьер сделал интересный комментарий на мой предыдущий ответ (тот, что цитирует Wordsworth):
Я думаю, что while (true) {} является более «чистой» конструкцией, чем while (условие) {}.
и я не смог ответить адекватно в 300 символов (извините!)
В моем обучении и наставничестве я неофициально определял «сложность» как «Сколько остальной части кода мне нужно иметь в моей голове, чтобы понять эту единственную строку или выражение?» Чем больше вещей я должен иметь в виду, тем сложнее код. Чем больше код говорит мне явно, тем менее сложным.
Итак, с целью уменьшения сложности позвольте мне ответить Хавьеру с точки зрения полноты и силы, а не чистоты.
Я думаю об этом фрагменте кода:
while (c1) {
// p1
a1;
// p2
...
// pz
az;
}
как выражение двух вещей одновременно:
- (все) тело будет повторяться до тех пор, пока
c1
остается верным, а
- в точке 1, где выполняется
a1
, c1
- это гарантированное для удержания.
Разница в перспективе; первое из них связано с внешним динамическим поведением всего цикла в целом, а второе полезно для понимания внутренней статической гарантии, на которую я могу рассчитывать, в частности, думая о a1
. Конечно, чистый эффект a1
может сделать недействительным c1
, что потребует от меня больше думать о том, на что я могу рассчитывать в пункте 2 и т. Д.
Давайте приведем конкретный (крошечный) пример, чтобы подумать об условии и первом действии:
while (index < length(someString)) {
// p1
char c = someString.charAt(index++);
// p2
...
}
«Внешняя» проблема заключается в том, что цикл явно делает что-то внутри someString
, что может быть сделано только до тех пор, пока index
находится в someString
. Это создает ожидание того, что мы будем изменять либо index
, либо someString
внутри тела (в месте и способе, неизвестном до тех пор, пока я не исследую тело), чтобы в конечном итоге произошло прекращение. Это дает мне и контекст, и ожидание для размышления о теле.
«Внутренняя» проблема заключается в том, что мы гарантируем, что действие, следующее за пунктом 1, будет законным, поэтому, читая код в пункте 2, я могу думать о том, что делается со значением char, которое я знаю было юридически получено. (Мы даже не можем оценить условие, если someString
является нулевым ссылочным номером, но я также предполагаю, что мы защитились от этого в контексте этого примера!)
Напротив, петля вида:
while (true) {
// p1
a1;
// p2
...
}
подводит меня к обоим вопросам. На внешнем уровне меня интересует, означает ли это, что я действительно должен ожидать, что этот цикл будет работать вечно (например, цикл диспетчеризации основных событий операционной системы), или происходит что-то еще. Это не дает мне ни явного контекста для чтения тела, ни ожидания того, что представляет собой прогресс в направлении (неопределенного) завершения.
На внутреннем уровне у меня абсолютно нет явных гарантий относительно любых обстоятельств, которые могут иметь место в пункте 1. Условие true
, которое, конечно, везде верно, является самым слабым из возможных утверждений о том, что мы можем знать в любой точке программы. Понимание предпосылок действия - очень ценная информация, когда вы пытаетесь думать о том, что действие выполняет!
Итак, я полагаю, что идиома while (true) ...
гораздо более неполная и слабая и, следовательно, более сложная, чем while (c1) ...
в соответствии с логикой, которую я описал выше.