news:85e8v.227832$gV7.1...@fx21.am4...
C's for loop allows the programmer to explicitly select <, <=, > or >. In
what I understand to be your preferred syntax, though, there is nowhere to
put the <= or >= terminating condition and there's nothing there to tell the
compiler whether X is supposed to increase from A to B or to decrease from A
to B. When the step is a signed variable or an expression that could be
positive or negative and when the semantics of the language state that the
sign of the step controls the direction of iteration how can the compiler
generate code for the loop termination test? It needs to know the direction
so that it knows whether to code the loop test as, say, <= or >=.
Alternatively if the language design is that the direction of the loop is to
be controlled by the relative values of A and B rather than the step the
compiler still has the same problem. It doesn't know whether X should ascend
or descend and, hence, it doesn't know whether to go on while X <= B or to
go on while X >= B. Poor compiler! I think it would have no choice but to
write code for both tests and select between them at run time. Am I wrong?
By contrast I meant that in C one could write
for (i = A; i <= B; i += C) /* for an ascending loop */
or
for (i = A; i >= B; i -= C) /* for a descending loop */
and the job is done. Then there is no ambiguity over whether the loop
variable is expected to increase or decrease. The effect in C doesn't need
to be documented or remembered. What the programmer intends can be expressed
clearly in the source code.
Don't get me wrong. I didn't just choose this at random. When I started on a
design for loops I looked at the kinds of loop control you prefer. I spent
some time on it, went over some of the same ground as I've mentioned and
wrestled with the necessary choices: what I thought the semantics should be
and/or how I could change the syntax so that the programmer's intentions
could be made clear. In the end I realised the transparent simplicity of C's
for statement removed all of those issues and just allows the programmer to
state what is wanted.
That's not to say that there's no way to improve on C's for loop. ;-)
>> Or perhaps the programmer wanted the difference between A and B to
>> control
>> the direction of the iteration and not the step. No one can know unless
>> the syntax is changed so that something is added to the statement like a
>> stepup or stepdown keyword. The whole thing is a terrible bundle of
>> questions and uncertainties.
>
> Maybe. Although over many years of programming the number of times I've
> needed a step other then 1 or -1 has been so few, that I actually removed
> the 'step' option from my for-loops for a couple of decades. I've put it
> back now, but require the direction to be known or indicated at compile
> time, otherwise it assumes positive. A dynamic loop-counting direction is
> too unusual a requirement for it to compromise the simplicity of the
> standard for-loop construct. There any number of ways to code such a thing
> without special language support. But if you say it's easy in C, then the
> C
> version is still there waiting to be dusted off!
Yes, acknowledged that you can have both.
>> Another issue is the terminating value. I remember in Basic having to
>> write things like
>>
>> for i = a to b - 1
>>
>> where the - 1 or something like it had to be added to modify the
>> termination value. C's for loop allows a natural slight adjustment to the
>> termination condition by means of < vs <=. Contrast these two
>>
>> for (i = 0; i < len; i++)
>> for (i = 1; i <= len; i++)
>
> Yes, C is zero-based so 0..N-1 loops might be more common than 1..N.
>
> My languages tend to be 1-based, but are also any-based, so loops might be
>
> for i :=A.lwb to A.upb do ....
>
> But I can also write a for-loop as;
>
> for i in A.bounds do ....
>
> or as just:
>
> for i in A do ...
>
> (This 'in' form expects a range value, one of the new types I suggested in
> my list).
>
> Alternatively, if we are iterating over an array, it's possible to just
> do:
>
> forall x in A do.... # x is each value of A in turn
> forall i,x in A do .... # and here supplies the index too.
>
> These forms will work for arrays of any base include C's 0-based ones.
Am going off topic a bit but I would be interested to hear your views on
this. Because
for x in A
is a good concept but, at the same time, a loop might need to iterate over
two or more arrays rather than just one I have toyed with the following
x = nextof A
Then each time the statement is reached x gets assigned the next value of A.
Of course, this would normally appear in a loop. It could head a loop by
writing something like
loop x = nextof A
... loop body
end loop
It is similar to your x in A approach but also allows other loop controls to
be added to the same loop if required, along the lines of
loop x = nextof A, y = nextof B
... loop body
end loop
Exhaustion of either A or B would terminate the loop. A or B could be
functions that generate sequences.
I like that the above is flexible (and also compact) but I don't think it's
quite right yet. Any thoughts on it?
> I suppose an alternative to 'to', such as 'upto' can indicate a count to
> N-1
> instead of 1, but it hints a bit of tackiness. (I already have, in
> addition,
> 'downto', 'in' and 'inrev'. But so far just writing -1 hasn't been a
> problem, and does away with an extra language feature to document.
>
>> Further, a loop can be controlled by all kinds of things other than a
>> stepping integer if that's what the programmer wants: input, lists,
>> pointers, even floats can make sense with the < or <= qualifiers where
>> they would be inappropriate for the A to B form.
>
> Sure. I'm not saying discard this complex loop completely and just have a
> basic iterative loop. I'm saying have the basic forms too for the simple
> cases: 'for', 'to' and 'do'. Syntax is free!
Syntax is free and I freely acknowledge that you make good syntax choices.
But consider: if a language includes the simpler form then its designer has
to deal with and document its semantics for the age-old issues mentioned
above and earlier. A given programmer may choose not to use the simpler form
at all but if he or she has to read someone else's code the programmer might
still need to learn the complex and somewhat arbitrary rules that the
language applies to those loops.
>> Oh, and one more thing. This is related to the problems with your
>> preference that I mentioned in the earlier post. Significant text has
>> been
>> written about whether the index might be modified during the course of
>> the
>> loop. And also whether the terminating value has to be constant or not.
>> There are a number of permutations: loop index yes, terminating value no,
>> neither, both etc. Different languages have chosen differently and their
>> choices need to be documented in the language definition. These are yet
>> more things for the programmer to remember. Again, C's for loop does away
>> with all of that. The C code shows exactly what the programmer has chosen
>> to be done.
>
> Not really. What happens here:
>
> for (i=0; i<strlen(s); ++i) ?
>
> Is strlen(s) always called once; is it called once if the compiler can
> determine that s won't change; or is it called per-iteration?
As you know, in the expressed form strlen is at least nominally called once
per iteration. An optimising compiler might improve on that if it can prove
that strlen(s) will not change in the loop but the programmer's intention is
clear (even if unwise).
It's easy to rewrite in a better form such as either of these
for (i = strlen(s) - 1; i >= 0; --i)
for (i = 0, slen = strlen(s); i < slen; ++i)
Apart from processing the string in the same order as your original the
latter has the advantage that if the code changes the length of the string
then both slen and i can be adjusted as the iterations progress.
Don't worry. I don't expect to convince you and I can see the appeal of the
simpler form.
James