5 ms·
> The right way to generalize "for", i.e. with iterators, was introduced by Alphard in the same year with C, i.e. in 1974.) (Compare "for (I=0;I<N;I+=5) {" of C
by alexeiz 3y ago
> The right way to generalize "for", i.e. with iterators, was introduced by Alphard in the same year with C, i.e. in 1974.) (Compare "for (I=0;I<N;I+=5) {" of C with "for I from 0 to N by 5 do" or "for I in 0:N:5 do" of previous languages.
Really? How do you do the C's equivalent of `for(i = 0; i < N && j < M; i++, j++)` with your `for I from 0 to N` syntax? The for loop in C is extremely flexible and it captures the idea of the loop perfectly: there is the initialization block, the exit condition and the iteration. In other languages at that time the for loop was written in terms of a range, but without a strong range abstraction such loop is really primitive and limited in applicability.
- nyssos 3y ago> In other languages at that time the for loop was written in terms of a range, but without a strong range abstraction such loop is really primitive and limited in applicability. That's a good thing: it gives you a clear syntactic marker for "this loop definitely terminates". There's already a full power anything-goes looping construct: `while`.
- professoretc 3y agoBut `while` doesn't restrict the scope of the variable(s) to just the loop. I believe there was a proposal to add while(int i = 0; i < 100) { ... } as a valid syntax to C++ (which would restrict the scope of i to the loop), as you can already do if(int i = f(); i > 0) { ... } but it didn't go anywhere.
- justincredible 3y ago[dead]
- a_e_k 3y agoI'd just use a for with an empty update clause for that: for (int i = 0; i < 100; ) { ... }
- MrJohz 3y agoI interpreted that line to be two separate clauses: firstly, a note that the statement that the correct generalisation for for loops is iterators, which were introduced in Alphard; secondly, an unrelated point about how the C-style generalised for loop is more verbose for the simple case than existing syntaxes. That is, the commenter was not asserting the supremacy of "from 0 to N" as a for-loop construct, but rather asserting the supremacy of iterators, and pointing out how poor the C-style syntax is even compared to its less-generalised cousins.
- adrian_b 3y agoBefore C and Alphard, all the "for" loops had control variables that took all values of some arithmetic progression. Even today, such simple loops with arithmetic progressions include an overwhelming majority of all "for" loops. The C syntax made writing these simple "for" loops more difficult, by having to write a lot of redundant symbols, instead of writing the minimum number of separators. Also for reading, the redundant symbols obscure the meaningful text. The C syntax allows the writing of "for" loops where the values of the control variables are not taken from a progression, but they are for instance the values of the links of a linked list. This kind of "for" loops can be written in a simple way by using iterators, without complicating the syntax of the loops with simple arithmetic progressions. In modern C++ there is no longer any case when you would want to use the C kind of "for", but the kinds of loops used by languages like C++ already existed in languages introduced at about the same time with C, e.g. Alphard and Clu.
- a_e_k 3y agoAnother good real-world one that I've done is something like: for (bit = 1; bit <= 128; bit <<= 1) Personally, I like the flexibility.
- bxparks 3y agoHeh, hopefully not too often. First I thought this loops 128 times. Then 7 times. Then 8 times. Then I thought "undefined behavior" if bit is a uint8_t. But then I thought, I don't have freaking clue because I can't keep all of C's implicit casting and arithmetic operation rules in my head.
- adrian_b 3y agoA better syntax for loops with geometric progressions like this would be obtained by modifying the syntax for writing arithmetic progressions (e.g. "a:b:c") by using a different separator symbol. For example, if the separator for geometric progressions would be ":>", your loop example would become "for bit in 1:>128:>2". Another example of (non-ASCII) separator would be "for bit in 1⋮128⋮2"
- kazinator 3y agoSuch syntax benefits from a comprehensive target language to compile into, in terms of which it can be understood, if necessary.
- ordu 3y agofor-loop in C is still primitive and limited in applicability, while it makes the most frequent use-case much more difficult. For example, it is normal practice to do some of initialization outside of a loop. It is normal to deal with finishing loop by using goto or if-branching after the loop (think of a search, that can be succesful or not). It is normal to ignore update counter part of loop and do updates in a body of the loop, because either updates are too big to squeese them between into for, or you need to do something between updating your counter and checking for the necessity of running another iteration. With all this said I know 2 another approaches to the problem. 1. Common Lisp approach: create really flexible loop clause, allowing to represent any loop in a structural way. I'd recommend to look at cl-iterate package for CL, to see what happens to maniacs who had chosen this way. 2. A less ambitious approach defining some simple loops for most frequent cases (while, range iteration, iteration by iterator) and a loop for a general case looking like "loop { iteration }". I personally prefer the second approach. I loved C-way, then I was a big fun of a Lisp-way, but now I believe that it is silly to create a whole new language just to write iteration, and a half-baked attempt to cover with for-loop more cases then just range iteration has more downsides than upsides.
- adrian_b 3y agoYour example would be "for i in o:N for j in o:M do". Equivalent syntax was used in Fortran for writing cycles in a simpler way than in C already 20 years before C. ("do 10 i=0,N do 20 j=0,M") The only case when the C "for" is useful is when the third operation is neither an addition nor a subtraction. The most frequent such case is when the operation is a link dereferencing, for accessing a linked list. Such cases, for visiting all members of some non-array aggregate data, e.g. linked lists or trees, are solved more clearly with iterators.
- f1shy 3y agoWhat you are doing there is no for. Not in the mathematical sense of “for all values in a set”. The semantic of the word “for” should matter. If you want to iterate 2 variables i and j is much better to do it explicitly. It will be much more readable.
- kazinator 3y agoUsing the for(;;) loop in Awk, and the C preprocessor, in a project called cppawk, I created a loop facility that has multiple clauses of different types, that can combine in parallel or as Cartesian-product, and are programmer-definable. https://www.kylheku.com/cgit/cppawk/tree/cppawk-iter.1 https://www.kylheku.com/cgit/cppawk/tree/cppawk-iter.1 The above manual page includes an example of how to define an alpha_range clause that iterates over string ranges like alpha_range(var, "000", "999") or alpha_range(var, "AAA", "ZZZ"). There is a conditional clause if(...) which takes a condition and another clause as arguments. The iteration of the other clause is suspended while the condition is false. At the shell prompt: add the values of the odd integers in the range 1 to 50. $ cppawk ' > #include <iter.h> > > BEGIN { > loop (range (i, 1, 50), > if (i % 2 == 1, summing (sum, i))) > ; > print sum > } > ' 625 Though if is an Awk keyword, this isn't a problem because if is a clause, not an ordinary expression. Moreover, though the clause is defined by macros, none of them are called if; they have if embedded in their name.