Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

The semantics of the for-loop

35 views
Skip to first unread message

Mark William Hopkins

unread,
Apr 16, 1988, 7:43:29 PM4/16/88
to

The best way out of the difficulties associated with the for-loop is
to define it. I would suggest the following definition:

FOR I := A TO B DO == I := A;
<Statement Sequence> WHILE I < B DO
END <Statement Sequence>;
I := I + 1
END;
IF I = B THEN
<Statment Sequence>
ENDIF

This set-up makes I come out of the loop with the value B.

An alternative, which is closer to the original intent of making
the "control variable" a LOCAL VARIABLE of the FOR-LOOP, is the
following:

FOR I := A TO B DO = PFOR(A, B) where PFOR is declared as the procedure
<Statement Sequence> PROCEDURE PFOR( A, B : TypeName);
VAR I : TypeName;
END BEGIN
Enclose the statements above
END

This does not make the troubles associated with I disappear, but it does
make the restrictions on I less ad-hoc.

Matthew Eric Seitz

unread,
Apr 16, 1988, 11:40:35 PM4/16/88
to
In article <55...@uwmcsd1.UUCP> ma...@csd4.milw.wisc.edu (Mark William Hopkins) writes:
>
> The best way out of the difficulties associated with the for-loop is
>to define it. I would suggest the following definition:
>
>FOR I := A TO B DO == I := A;
> <Statement Sequence> WHILE I < B DO
>END <Statement Sequence>;
> I := I + 1
> END;
> IF I = B THEN
> <Statment Sequence>
> ENDIF
>
>This set-up makes I come out of the loop with the value B.

_Programming_In_Modula-2_ essentially defines the for statement as the following
equivalency

"FOR" ident ":=" expression1 "TO" expression2 [ "BY" ConstExpression ] "DO"
StatementSequence
"END"
is equivalent to

ident ":=" expression1;
"WHILE" ident "<=" expression2 "DO"
StatementSequence
[ident ":=" ident "+" ConstExpression (* if "BY" clause used *) |
ident ":=" ident "+ 1" (* if "BY" clause not used *) ]";"
"END"
(* ident := undefined *)

This means that you can replicate any FOR statement by a WHILE statement with
only two additional lines. Since this is also more explicit and flexible than
a FOR loop, I've started using the WHILE loop exclusively. I imagine Wirth
had similar reasons for dropping the FOR loop from Oberon.

Matthew Seitz
se...@cory.berkeley.edu

Roger Crew

unread,
Apr 17, 1988, 5:34:52 PM4/17/88
to
In article <24...@pasteur.Berkeley.Edu> se...@cory.Berkeley.EDU.UUCP
(Matthew Eric Seitz) writes:
>
> _Programming_In_Modula-2_ essentially defines the for statement as
> the following equivalency
>
> "FOR" ident ":=" expression1 "TO" expression2 [ "BY" ConstExpression ] "DO"
> StatementSequence
> "END"
> is equivalent to
>
> ident ":=" expression1;
> "WHILE" ident "<=" expression2 "DO"
> StatementSequence
> [ident ":=" ident "+" ConstExpression (* if "BY" clause used *) |
> ident ":=" ident "+ 1" (* if "BY" clause not used *) ]";"
> "END"
> (* ident := undefined *)
>

Ouch.

If _Programming_in_Modula-2_ says this,...
well, it's a mistake, plain and simple.

Consider:

FOR ch := 0C TO 255C DO
whatever
END;

which supposedly is equivalent to

ch := 0C;
WHILE ch <= 255C DO
whatever
INC(ch);
END;

If you don't like playing with characters, try FOR i := -2^31 TO 2^31-1
(for 32 bit integers... i.e., MININT and MAXINT, or whatever they happen
to be called these days...).

The WHILE loop will bomb at runtime when it tries to increment 255C.
If you were doing this with integers, you won't be this lucky.

(hint:
in C, for(ch=0;ch<=255;ch++) is an infinite loop when ch is an 8-bit char).

You really do need that second IF statement (or something similar;
if you don't like writing the statement body twice, then you have to
go through contortions like

ident := expression1;
IF ident <= expression2 THEN
LOOP
whatever;
IF ident = expression2 THEN EXIT END;
INC(ident);
END;
END;

And even this general form fails miserably for

FOR ch := 0C TO 255C BY 2 DO
whatever
END;

(unless, or course, you cheat by changing 255C to 254C)

--
Roger (cr...@polya.stanford.edu) ``Beam Wesley into the sun!''

Robert Firth

unread,
Apr 18, 1988, 10:28:18 AM4/18/88
to
In article <24...@pasteur.Berkeley.Edu> se...@cory.Berkeley.EDU.UUCP (Matthew Eric Seitz) writes:

]_Programming_In_Modula-2_ essentially defines the for statement as the following


]equivalency
]
]"FOR" ident ":=" expression1 "TO" expression2 [ "BY" ConstExpression ] "DO"
] StatementSequence
]"END"
]is equivalent to
]
]ident ":=" expression1;
]"WHILE" ident "<=" expression2 "DO"
] StatementSequence
] [ident ":=" ident "+" ConstExpression (* if "BY" clause used *) |
] ident ":=" ident "+ 1" (* if "BY" clause not used *) ]";"
]"END"
](* ident := undefined *)

It does. And thereby perpetuates the design or implementation error that
has cursed FOR-loops since the days of Algol-60: a loop set to end on the
largest value of the associated type will fail.

This is 1988. Let's at least put THAT right!

chr...@cup.portal.com

unread,
Apr 20, 1988, 2:25:13 AM4/20/88
to

In 50...@aw.sei.cmu.edu, fi...@sei.cmu.edu (Robert Firth) quotes an earlier
article about the semantics of FOR loops and says:

>... thereby perpetuates the design or implementation error that


>has cursed FOR-loops since the days of Algol-60: a loop set to end on the
>largest value of the associated type will fail.
>
>This is 1988. Let's at least put THAT right!

This is purely an implementation issue. MacMETH does it correctly, as
I'm sure some other compilers do. At the bottom of the loop, MacMETH
generates an ADDI or SUBI, followed by either a BVC (INTEGER or LONGINT)
or a BCC back to the top of the loop. Note that this correctly handles
FOR u := 0 TO MAX(CARDINAL) BY 2 DO ... END;
Stopping on >= before the increment, rather than > after the increment,
would not help in this case, although I suppose the generated code could
decrement the limit by (stepsize-1) before the loop, and then use a >=
test before increment.

If your compiler doesn't handle these limit situations correctly, gripe
at the vendor until they fix it. (Hi, Eli! :-))

Of course this means that a FOR loop is not EXACTLY equivalent to the
corresponding WHILE, since the WHILE version will either ignore the
carry/overflow or abort execution, depending on the implementation.

Christopher Jewell | If God had meant for us to fly, He
chr...@cup.portal.com | would NEVER have given us the railways.
ucbvax!sun!cup.portal.com!chrisj | -- Flanders & Swan

0 new messages