• FOR TO BY vs FOR IN

    From trijezdci@21:1/5 to Martin Brown on Tue Aug 30 08:05:33 2016
    On Tuesday, 30 August 2016 18:22:01 UTC+9, Martin Brown wrote:

    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?

    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:

    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.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From trijezdci@21:1/5 to All on Tue Aug 30 13:18:11 2016
    I have now split the row for the FOR statement into two: one row qualified (ordinal) and the other row qualified (collection). This way the chart covers at least two FOR statement scenarios of R10 which seems a reasonable compromise between concise and
    exhaustive.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From rugxulo@gmail.com@21:1/5 to trijezdci on Thu Sep 1 15:56:30 2016
    Hi,

    On Tuesday, August 30, 2016 at 10:05:34 AM UTC-5, trijezdci wrote:
    On Tuesday, 30 August 2016 18:22:01 UTC+9, Martin Brown wrote:

    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.

    Just to state the obvious ....

    Wirth removed "FOR" in the original Oberon (although it was later added
    back in -2 and -07 revisions).

    You don't direly need it, you can simulate it with WHILE, albeit a tiny
    bit more verbose.

    If I had to guess, it's because of all the corner cases and restrictions encountered with it (esp. Pascal), but I could be wrong. (Don't modify
    it from within the loop, keep it in a register, don't jump into loops,
    what does it reliably contain afterwards [if anything], etc.)

    I'm not really saying it's a good idea to remove, just mentioning that
    it isn't always as obvious as it seems.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From trijezdci@21:1/5 to rug...@gmail.com on Thu Sep 1 18:15:53 2016
    On Friday, 2 September 2016 07:56:31 UTC+9, rug...@gmail.com wrote:

    Wirth removed "FOR" in the original Oberon (although it was later added
    back in -2 and -07 revisions).

    You don't direly need it, you can simulate it with WHILE, albeit a tiny
    bit more verbose.

    Indeed. If simplicity of implementation was the only concern, you could dispense with WHILE, REPEAT and FOR, only providing the LOOP statement.


    If I had to guess, it's because of all the corner cases and restrictions encountered with it (esp. Pascal), but I could be wrong. (Don't modify
    it from within the loop, keep it in a register, don't jump into loops,
    what does it reliably contain afterwards [if anything], etc.)

    We addressed all those issues in our FOR loop design.

    The loop variants are implicitly declared within the loop header, they have loop scope only, the loop control variant is immutable within the loop body.


    FOR n IN [0.99] OF CARDINAL DO
    (* n is immutable *)
    END;
    (* n does is no longer in scope here *)


    FOR index, value IN array DO
    (* index is immutable, value is mutable *)
    END;
    (* index and value are no longer in scope here *)


    Of course you could do a similar thing with the FOR TO BY loop, like

    FOR n := 0 TO 99 OF CARDINAL DO
    (* n is immutable *)
    END;
    (* n is no longer in scope here *)


    I'm not really saying it's a good idea to remove, just mentioning that
    it isn't always as obvious as it seems.

    For Wirth, language design has always been custom design for a specific project on a specific platform. This affords very compact languages since you can throw out everything you are unlikely to need in your next project.

    However, this is a luxury most of us cannot afford. If you design for a wider purpose you cannot as easily dispense with facilities just because you won't need them for the next project. Weighing the pros and cons becomes more involved and you are likely
    to have a less compact language.

    Nevertheless, Modula-2 remains a very compact language even with the FOR loop.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)