trijezdci
2016-08-30 15:05:33 UTC
I think removing generic FOR loops is a mistake. They are used for a lot
more than just iterating over ARRAYs and limiting them to only that will
result in inconvenience when for example summing the results obtained by
calling a function whilst doing an integration for instance.
Have you looked at the actual syntax of the FOR IN statement?more than just iterating over ARRAYs and limiting them to only that will
result in inconvenience when for example summing the results obtained by
calling a function whilst doing an integration for instance.
It allows ordinal range expressions, so you can also do
FOR n IN [0 .. 100] OF CARDINAL DO
sum := sum + n
END
I did't want to blow up the chart with variations of use cases, the chart has to remain generic enough to keep it all concise but here are the use cases:
(* iterating over enums and their subranges *)
FOR item IN EnumType DO ... END;
FOR item IN [v1 .. v2] OF EnumType DO ... END;
(* iterating over countable types and their subranges *)
FOR value IN CountableType DO ... END;
FOR value IN [v1 .. v2] OF CountableType DO ... END;
(* iterating over sets and multisets *)
FOR elem IN set DO ... END;
FOR elem, count IN multiSet DO ... END;
(* iterating over arrays *)
FOR index IN array DO ... END;
FOR index, value IN array DO ... END;
(* iterating over dictionaries, incl. trees *)
FOR key IN dictionary DO ... END;
FOR key, value IN dictionary DO ... END;
(* iterating over sequential lists *)
FOR item IN list DO ... END;
The FOR IN syntax also has an optional ascender or descender.
FOR item++ IN iterableExpr DO ... END;
FOR item-- IN iterableExpr DO ... END;
For enumerations, countable types and ordered collections, the default is always ascending. For unordered collections, the iteration direction is implementation defined and the use of an ascender or descender will cause a compile time error.
Note that since multisets, dictionaries and lists do not have type constructors in Modula-2 and must therefore be user defined, the use of the FOR syntax with these requires binding of an iterator procedure to the FOR statement and binding requires conformance to a blueprint for consistency and integrity.
It is also necessary to iterate repeatedly over some arrays with a
sequence of unusual strides for example in the computation of an FFT.
The FOR IN statement is actually closer to math notation than is the FOR TO BY statement. In math notation you compute the stride in the body:sequence of unusual strides for example in the computation of an FFT.
99
-
\ 2 * n + 1
/
-
n = 0
FOR n IN [0 .. 99] OF CARDINAL DO
sum := sum + 2 * n + 1
END;
This is the most "natural" representation if you consider math notation to be the defining cultural context that everybody is expected to be familiar with.
The reason why the syntax of early programming languages did not closely follow the math notation and compute the stride in the header is simply because it was inefficient and compiler technology wasn't able to optimise it yet.
The required optimisation technique is called loop invariant code motion and it has been around since at least the 1970s. It is well understood and pretty standard in modern compilers.
In other words, in the days when for loop syntax with stride parameters in the loop header was first designed this was a necessary optimisation, but in our day and age doing so would be premature optimisation and thus unnecessary.