Если кратко, то основная проблематика -- вокруг эффекта "loop-and-a-half" по Дейкстре (может быть здесь на форуме разбираемого в прошлом):
The fact that some loop structures seem to have a natural
exit in the middle has long been recognized. In his 1974
comments on the goto controversy [Knuth74], Don Knuth
outlined his own perspective, as follows:
Цитата:
The iteration statements most often proposed as
alternatives to goto statements have been “while B do
S” and “repeat S until B”. However, in practice the
iterations I encounter very often have the form
Код:
A: S;
if B then goto Z fi;
T;
goto A
Z:
where S and T both represent reasonably long sequences
of code. If S is empty, we have a while loop, and if T
is empty we have a repeat loop, but in the general
case it is a nuisance to avoid the goto statements.
A typical example of such an iteration occurs when S
is the code to acquire or generate a new piece of data, B
is the test for end of data, and T is the processing of that
data.
Loops of this sort, in which some processing must precede
the test, come up quite often in programming and constitute
what Dijkstra has called the
loop-and-a-half problem. The
canonical example of the loop-and-a-half problem is
precisely the one that Knuth describes: reading a set of
input values until some sentinel value appears. If the basic
strategy is expressed in pseudocode, the problem has the
following solution:
Код:
loop
read in a value;
if value = Sentinel then exit;
process the value
endloop;
In this example, the loop/exit/endloop statement is an
extension to the Pascal repertoire and represents a loop that
is terminated only by the execution of the exit statement in
the interior of the loop body. The loop/exit/endloop
extension makes it possible to express the algorithm so that
the input value is read in from the user, tested against the
sentinel, and then processed as necessary.
The loop/exit/endloop approach, however, offends the
sensibilities of many computer science instructors, who
have learned through their experience with Pascal to
“unwind” the loop so that the test appears at the top of the
while loop, as follows:
Код:
read in a value;
while value != Sentinel do begin
process the value;
read in a value
end;
Unfortunately, this approach has two serious drawbacks.
First, it requires two copies of the statements required to
read the input value. Duplication of code presents a serious
maintenance problem, because subsequent edits to one set
of statements may not always be made to the other. The
second drawback is that the order of operations in the loop
is not the one that most people expect. In any English
explanation of the solution strategy, the first step is to read
in a number, and the second is to process it by adding it to
the total. The traditional Pascal approach reverses the order
of the statements within the loop and turns a read/process
strategy into a process/read strategy. As the rest of this
section indicates, there is strong evidence to suggest that
the read/process strategy is more intuitive, in the sense that
it corresponds more closely to the cognitive structures
programmers use to solve such problems.
The problem of code duplication is in some sense
objective. The statements that read in an input value do in
fact appear twice in the program, and it is easy to imagine
that an edit in one copy might not be made symmetrically
in the other. The second problem, however, is inherently
more subjective because it hinges on the question of which
loop order is more “intuitive.” What is intuitive for some
may not be intuitive for others, and it may be that a
preference for one strategy over another represents nothing
more than an individual bias. For that reason, it is
important to rely on empirical measurement of the success
that students have in using the different strategies.
В самом деле, претензии не беспочвенны. Вопросом дублирования операций можно пренебречь, а вот структура шага цикла, действительно, инвертирована (ведь суть то итерационного процесса как такового -- сначала read, затем process).
И там же в нагрузку методология предполагает и ранний return для функций из циклов (прежде всего, для for).
Таковы положения в Стэнфордском университете начала 90-х. Вряд ли они изменились, видимо, как и в прочих учебных заведениях, судя по сегодняшнему мэйнстриму.
К слову, положения в некоторой степени коррелируют со стандартами безопасности, которые были рассмотрены здесь на форуме.
С другой стороны, популярная борьба с "loop-and-a-half" в виде использования функций с "побочными эффектами", чтобы действия по "добыче данных" упрятать в условие цикла, и чтобы всё было "по-структурному" (в т.ч. и в случаях применения побочных эффектов для условий в IF), в целом не соответствует "структурщине" -- подобные функции ведь тогда не есть "предикаты" (не могут быть "защитными выражениями").