abcscagz@csuna.UUCP (stepanek/cs assoc) (01/26/89)
In article <739@jupiter.iis.UUCP> heiser@iis.ethz.ch (Gernot Heiser) writes: > >worst features. C's 'for' is really a 'while' with an initialization clause and >a designated spot that may contain an incrementation clause. What I consider a >"real" 'for' (as opposed to the while/repeat/loop family) is a construct that >executes a specific number ot times, the iteration count being determined >BEFORE the processing of the body starts. This is what is really needed most of >the time in numerical programs. The other cases are exactly what while/repeat/ >loop constructs are for. Actually, C's "for" can be duplicated EXACTLY by C's "do ... while" loops. Consider: for (i = 0; i <= 17; ++i) { stuff(); more_stuff(); } versus: i = 0; do { stuff(); more_stuff(); } while (++i <= 17); These two iterations are indistinguishable from one another. The "for" term in C is totally superfluous and is only included because it makes it look like languages that have a more "for"-ish "for" statement, like Pascal or Modula. (I won't even get into Algol's "for" here....) -- Jeff Boeing: ...!csun.edu!csuna!abcscagz (formerly tracer@stb.UUCP) -------------------------------------------------------------------------- "When Polly's in trouble I am not slow / It's hip, hip, hip and away I go!" -- Underdog
hascall@atanasoff.cs.iastate.edu (John Hascall) (01/27/89)
In article <739@jupiter.iis.UUCP> heiser@iis.ethz.ch (Gernot Heiser) writes: >worst features. C's 'for' is really a 'while' with an initialization clause and >a designated spot that may contain an incrementation clause. What I consider a >"real" 'for' (as opposed to the while/repeat/loop family) is a construct that >executes a specific number ot times, the iteration count being determined >BEFORE the processing of the body starts. This is what is really needed most of ^^^^^^ I can't count the number of times this has nailed C novices who have had experience with other languages (i.e., FORTRAN). For example: for ( i=0; i < fn_with_side_effects(x); i++ ) { blue_dog_moon_up(); } >the time in numerical programs. The other cases are exactly what while/repeat/ >loop constructs are for. As far as I can see, the main purpose of C's "for" is to save space, which is one of C's strengths (to some, probably not to MIS/COBOL types [oh! sorry, this isn't the misc.jobs.misc C/COBOL-CS/MIS flamewar?]) John Hascall ISU Comp Center
bowles@eris.berkeley.edu (Jeff A. Bowles) (01/28/89)
In article <738@atanasoff.cs.iastate.edu> hascall@atanasoff.cs.iastate.edu (John Hascall) writes: >In article <739@jupiter.iis.UUCP> heiser@iis.ethz.ch (Gernot Heiser) writes: > >>worst features. C's 'for' is really a 'while' with an initialization clause and >>a designated spot that may contain an incrementation clause. What I consider a >>"real" 'for' (as opposed to the while/repeat/loop family) is a construct that >>executes a specific number ot times, the iteration count being determined >>BEFORE the processing of the body starts.... I hate to fan flames like this, but I can't resist. I have strong reservations about certain things in C, but the "for" loop is something that's really kinda nice: 1. It's not restrictive on the types of the indices, because it defines a more general construct. If I had a nickel for every time, in Fortran, that I needed a loop that ran from 0.0 to 1.0 by 0.1 (or the like) and had to use INTEGER to do it. Or Pascal, which lacked the "step" clause so that you couldn't increment by more than what the language-designer wanted. 2. Yes, you're right, it's redundant - the "while (expr) statement;" and the "do statement; while (expr)" and the "for (expr;expr;expr) statement;" have a lot of redundancy, probably for brevity. So? 3. Because it's not restrictive on the types, and because I don't have to know EXACTLY how many times it will run through the body, I can do things like: for (p = headoflist; p != NULL; p = p->l_next) process(p); The article said that you could code loops that run a arbitrary number of times, using something like: for (i = 0; i < thingwithsideeffects(i); i++) munge(); And while the author of the article is correct, you can code garbage like this in most languages. Fault the coder, in this case. The only thing I really miss is something you Unix-types will recognize from awk (and perhaps from Algol 68?) - for (t in table) process(table[t]); But that's another story.... Jeff Bowles
ags@s.cc.purdue.edu (Dave Seaman) (01/28/89)
In article <19579@agate.BERKELEY.EDU> bowles@eris.berkeley.edu (Jeff A. Bowles) writes: > If I had a nickel for every time, in Fortran, > that I needed a loop that ran from 0.0 to 1.0 by 0.1 (or the like) and > had to use INTEGER to do it. Fortran does not require an integer. The control variable of a DO loop may be integer, real, or double precision. It is perfectly legal to write: REAL X . . . DO 10 X=0.0, 1.0, 0.1 . . . according to the current standard, but this has been recognized as a mistake which will probably be rectified in the next standard. You can't even tell how many iterations you will get from the DO statement above (10? 11? how do you know?). Why anyone would want to add this deficiency to a language that doesn't currently have broken FOR statements is beyond me. -- Dave Seaman ags@j.cc.purdue.edu
arrom@aplcen.apl.jhu.edu (Ken Arromdee) (01/28/89)
>Actually, C's "for" can be duplicated EXACTLY by C's "do ... while" loops.
I suspect you're going to get an awful lot of flames for saying this. What
about
for(i=0; i<=j; i++)
printf("%d\n",i);
Since a do-while loop has the test condition at the termination of the loop,
it is not possible to produce an equivalent do-while version, for the
behavior will differ if j is less than 0.
--
EARTH --Kenneth Arromdee
smog | bricks UUCP: ....!jhunix!ins_akaa
AIR mud FIRE INTERNET: arromdee@crabcake.cs.jhu.edu
soda water | tequila BITNET: g49i0188@jhuvm
WATER (please, no mail to arrom@aplcen)
jlg@lanl.gov (Jim Giles) (01/28/89)
From article <19579@agate.BERKELEY.EDU>, by bowles@eris.berkeley.edu (Jeff A. Bowles): > [...] > 1. It's not restrictive on the types of the indices, because it defines a > more general construct. If I had a nickel for every time, in Fortran, > that I needed a loop that ran from 0.0 to 1.0 by 0.1 (or the like) and > had to use INTEGER to do it. Or Pascal, which lacked the "step" clause > so that you couldn't increment by more than what the language-designer > wanted. > [...] > Jeff Bowles ALL standard conforming Fortran processors allow the following: DO 10 i=0.0,1.0,0.1 The standard committee now considers this to be a mistake and is likely to remove it in 8x, but for the moment this is a standard feature. It is considered a mistake because the standard doesn't make any constraints on the accuracy of floating-point arithmetic. So the trip count on a loop with floating-point limits is not well-defined. The C for-loop is even worse in this regard - the trip count is not precomputed. Consider the following: for (x=0.0; x<=1.0, x+=0.1) {...} The value of x for each trip through the loop is a sum of 0.1+ ... +0.1, a value which suffers round-off or truncation on each successive add. If the four operations in the computation of the Fortran trip count lead to ambiguous results, the 11 adds in the above are even worse. For a loop from 0.0 to 1000.0 by 0.01 on a 32-bit floating-point machine, the round-off of the last 100 adds is comparable to the increment itself! This may be another reason for the undesireable feature in C of assuming double precision as the default floating-point. J. Giles
gwyn@smoke.BRL.MIL (Doug Gwyn ) (01/28/89)
In article <1611@csuna.UUCP> abcscagz@csuna.csun.edu (Jeff Boeing) writes: >Actually, C's "for" can be duplicated EXACTLY by C's "do ... while" loops. Only in the sense that, given "if" and any looping construct, any of the other looping constructs can be simulated. But there is no obvious straightforward mapping of a general "for" onto "do...while". For one thing, a "for" need not execute the controlled statement at all whereas "do...while" always executes it at least once. The other thing to beware of is the behavior of "continue". Many programmers have been confused by trying to map "for" into "while" and not realizing that "continue" does different things in the two cases.
gwyn@smoke.BRL.MIL (Doug Gwyn ) (01/28/89)
In article <19579@agate.BERKELEY.EDU> bowles@eris.berkeley.edu (Jeff A. Bowles) writes: >... the "for" loop is something that's really kinda nice: The main purpose of "for" in C is to collect all the loop control pieces together on a single line to make them more evident: for ( p = head.next; p != &head; p = p->next ) ... Certainly this particular can be accomplished in numerous ways, but it's hard to imagine anything that would be clearer than that.
gwyn@smoke.BRL.MIL (Doug Gwyn ) (01/28/89)
In article <8515@lanl.gov> jlg@lanl.gov (Jim Giles) writes: > for (x=0.0; x<=1.0, x+=0.1) {...} >For a loop from 0.0 to 1000.0 by 0.01 on a 32-bit floating-point machine, >the round-off of the last 100 adds is comparable to the increment itself! >This may be another reason for the undesireable feature in C of assuming >double precision as the default floating-point. No, I don't think so. I've never known anyone to recommend a loop like the above. The reasons for defaulting floating-point computations to double precision in original C (no longer required in ANSI C) were that it was easier to support on the PDP-11 that way and that numerical applications were so rare in the UNIX C environment that the potential loss of speed for such applications was not considered significant.
crew@Polya.Stanford.EDU (Roger Crew) (01/28/89)
Here's a quiz: How would you write the following in C? VAR a, b, c : Char; ... FOR c = a TO b DO ... END; You can even assume that the body of the loop affects neither a nor b. Hint: the answer is *not* char a, b, c; ... for (c = a; c <= b; ++c) { ... } (just try a = 0 and b = 255 in the case of 8 bit chars). -- Roger Crew Copyright 1989 -- All Rights Reserved. (so there!) Usenet: {arpa gateways, decwrl, uunet, rutgers}!polya.stanford.edu!crew Internet: crew@polya.Stanford.EDU
guy@auspex.UUCP (Guy Harris) (01/28/89)
>Actually, C's "for" can be duplicated EXACTLY by C's "do ... while" >loops. No, they can't. for (i = 0; i < N; i++) /* N is a *variable* here */ stuff; isn't duplicated by i = 0; do stuff; while (++i < N); because, if N is 0, the first loop will be executed 0 times and the second loop will be executed 1 time. It *is* duplicated by i = 0; while (i < N) { stuff; i++; } as long as "stuff" doesn't include a "continue" (see p. 60 of K&R Second Edition; there's probably similar stuff somewhere in the First Edition). >These two iterations are indistinguishable from one another. The "for" term >in C is totally superfluous and is only included because it makes it look like >languages that have a more "for"-ish "for" statement, like Pascal or Modula. Well, to quote something else from p. 60: The "for" is preferable when there is a simple initialization since it keeps the loop control statements close together and visible at the top of the loop. Whether you agree with that opinion or not is your business; however, it seems the reason "for" was included wasn't solely to "make it look like languages that have a more 'for'-ish 'for' statement", but because DMR felt the "for" statement had merits of its own.
Devin_E_Ben-Hur@cup.portal.com (01/29/89)
Jeff Boeing writes: > Actually, C's "for" can be duplicated EXACTLY by C's "do ... while" loops. > Consider: > > for (i = 0; i <= 17; ++i) > { > stuff(); > more_stuff(); > } > > versus: > > i = 0; > do { > stuff(); > more_stuff(); > } while (++i <= 17); > > > These two iterations are indistinguishable from one another. The "for" term > in C is totally superfluous and is only included because it makes it look > languages that have a more "for"-ish "for" statement, like Pascal or Modula. Nope. This is the actual equivalent code: i = 0; while (i <= 17) { stuff(); more_stuff(); continue_here: ++i; } The for loop tests at the first iteration, and a continue statement will branch to the increment not to the test. The C for statement is a convenience allowing the programmer to place all loop control statements in one place instead of spreading them all over the loop. I've always thought the limits placed on Pascal & Modula's for statements were silly, but that's just MHO. Devin_Ben-Hur@cup.portal.com ...!ucbvax!sun!cup.portal.com!devin_e_ben-hur
abcscagz@csuna.UUCP (stepanek/cs assoc) (01/29/89)
Hoo boy, did I ever mess up in my last posting.
I forgot that a C "for" loop may be executed zero times.
So, let me rephrase my conviction that a C "for" loop is superfluous
because it can be replaced by an equivalent "while" loop, NOT an
equivalent "do ... while" loop:
for (i = 0; i <= 17; i = sqr(i) + 2)
<stuff>;
versus:
i = 0;
while (i <= 17)
{
<stuff>;
i = sqr(i) + 2;
}
There. I hope I have redeemed myself in the face of my previous blasphemy.
And now that I think about it, it IS nice to have final incrementational
conditions in the loop declaration rather than at the end of the loop-body,
as the "while" case forces you to do.
(Although I do still believe that the initial "statement" field of a
"for" loop is superfluous.)
--
Jeff Boeing: ...!csun.edu!csuna!abcscagz (formerly tracer@stb.UUCP)
--------------------------------------------------------------------------
"When Polly's in trouble I am not slow / It's hup, hup, hup and awaay I go!"
-- Underdog
jlg@lanl.gov (Jim Giles) (01/29/89)
From article <9527@smoke.BRL.MIL>, by gwyn@smoke.BRL.MIL (Doug Gwyn ): > In article <8515@lanl.gov> jlg@lanl.gov (Jim Giles) writes: >> for (x=0.0; x<=1.0, x+=0.1) {...} >>For a loop from 0.0 to 1000.0 by 0.01 on a 32-bit floating-point machine, >>the round-off of the last 100 adds is comparable to the increment itself! >> [...] > > No, I don't think so. I've never known anyone to recommend a loop > like the above. [...] I know of at least one person who recommended such a loop - the person I was originally responding to. He felt that the above loop was a clear advantage over what Fortran DO loops could do. He was wrong on both counts (Fortran CAN do it and it's not an improvement). J. Giles
chris@mimsy.UUCP (Chris Torek) (01/30/89)
[followups redirected to comp.lang.misc] In article <8515@lanl.gov> jlg@lanl.gov (Jim Giles) writes: >[the floating point DO-loop construct] is considered a mistake because >the standard doesn't make any constraints on the accuracy of floating- >point arithmetic. So the trip count on a loop with floating-point >limits is not well-defined. (True in both C and FORTRAN.) >The C for-loop is even worse in this regard - the trip count is not >precomputed. That this is worse is mere opinion (or perhaps contentiousness). >Consider the following: > > for (x=0.0; x<=1.0, x+=0.1) {...} Or consider: tripcount = (int)((1.0-0.0)/0.1) + 1; /* or should this be rounded rather than truncated? */ /* (I have no F77 reference handy, sorry) */ for (x = 0.0; --tripcount >= 0; x += 0.1) ... which (in theory) does what the F77 construct DO label X = 0.0, 1.0, 0.1 does. But suppose the task is to find the accumulated error? for (i = 0, x = 0.0; x <= 1.0; i++, x += 0.1) /* void */; printf("[0.0,1.0] count took %d steps; x-1.0=%g\n", i, x - 1.0); which in F77 can be written (I will use `WHILE' here for conciseness and to avoid those blasted statement numbers) X = 0.0 I = 0 WHILE (X .LE. 1.0) DO X = X + 0.1 I = I + 1 ENDWHILE ! (I forget whether PRINT * puts spaces around numbers) PRINT *, '[0.0,1.0] count took', I, 'steps; x-1.0=', X-1.0 Not really that different after all (although the FORTRAN version is in ugly uppercase :-) ). >The value of x for each trip through the loop is a sum of 0.1+ ... +0.1, >a value which suffers round-off or truncation on each successive add. >If the four operations in the computation of the Fortran trip count >lead to ambiguous results, the 11 adds in the above are even worse. Any programmer worth his pay is aware of the method by which the trip count is determined, and will write the appropriate code in the appropriate situation. It is true that situations demanding floating point loop counters are rare. In any case, the generalised `for' loop construct in C is very worthwhile, although a specialised precomputed-count loop construct (a la most other Algol/FORTRANnish languages) might be nice. C's `for' fits a number of situations well, such as for (p = head; p != NULL; p = p->next) for simple list traversal, or for (p = head.next; p != &head; p = p->next) for circular queues, or for (x = init; fn1(x) < fn2(x); x = fn3(x)) for essentially arbitrary stepping around a graph of two functions looking for a crossover. For loops with a fixed iteration limit, a construct like for i in [1..N) do is often better, since it is clearer and allows the compiler to use shadowing or downcounts or whatnot without requiring it to determine that the limit is in fact fixed. It is sometimes worthwhile in C to recode something like for (i = 1; i < f(); i++) /* where f() is a pure function */ as for (j = f(), i = 1; --j > 0; i++) or (clearer but sometimes slower) for (i = 1, j = f(); i < j; i++) and this sort of nonsense is really best left to the compiler. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
schmidt@blanche.ics.uci.edu (Doug Schmidt) (01/30/89)
In article <1626@csuna.UUCP> abcscagz@csuna.csun.edu (Jeff Boeing) writes: ++Hoo boy, did I ever mess up in my last posting. ++I forgot that a C "for" loop may be executed zero times. ++So, let me rephrase my conviction that a C "for" loop is superfluous ++because it can be replaced by an equivalent "while" loop, NOT an ++equivalent "do ... while" loop: I don't think you've gone far enough. After all, can't both a while loop and a for loop be replaced by an if statement and a goto? ++ ++ for (i = 0; i <= 17; i = sqr(i) + 2) ++ <stuff>; ++ versus i = 0; LOOP_HEAD: if (i <= 17) { <stuff> i = sqr(i) + 2; goto LOOP_HEAD; } In fact, aren't all high-level control constructs superfluous? Doug p.s. ;-) ...... -- schmidt@ics.uci.edu (ARPA) | Per me si va nella citta' dolente. office: (714) 856-4043 | Per me si va nell'eterno dolore. | Per me si va tra la perduta gente. | Lasciate ogni speranza o voi ch'entrate.
bill@twwells.uucp (T. William Wells) (01/30/89)
In article <1626@csuna.UUCP> abcscagz@csuna.csun.edu (Jeff Boeing) writes:
: Hoo boy, did I ever mess up in my last posting.
: I forgot that a C "for" loop may be executed zero times.
: So, let me rephrase my conviction that a C "for" loop is superfluous
: because it can be replaced by an equivalent "while" loop, NOT an
: equivalent "do ... while" loop:
C is superfluous because it can be replaced by an equivalent assembly
program.
---
The C for loop exists because it encapsulates the common initialize,
test, and update control structure; it does not exist because such
encapsulation can't be written any other way, or to save keystrokes,
or any other such irrelevant reason.
---
Bill
{ uunet!proxftl | novavax } !twwells!bill
diamond@csl.sony.JUNET (Norman Diamond) (01/30/89)
In article <19579@agate.BERKELEY.EDU>, bowles@eris.berkeley.edu (Jeff A. Bowles) writes: [Praising C's for-loop over other languages' iterators] > If I had a nickel for every time, in Fortran, > that I needed a loop that ran from 0.0 to 1.0 by 0.1 (or the like) and > had to use INTEGER to do it. If you do such iterations in floating-point, adding 0.1 each time instead of multiplying an integer by 0.1, you will lose a lot of nickels. I wouldn't mind receiving them. (The Vancouver Stock Exchange did that kind of thing. Eventually their computed index of stock prices became about half of the correct value, and they finally noticed they had a bug.) > Or Pascal, which lacked the "step" clause > so that you couldn't increment by more than what the language-designer > wanted. This was not due to what the language designer wanted. Remember that he only had resources available for a small compiler and had to provide maximal assistance to novice students in error checking. Testing "for" statements for overflow when the stepsize is not 1 is more difficult. Now if you had complained that the modern version, i.e. the draft ISO Extended Pascal standard, still doesn't allow it, then I would agree with your complaint. > The only thing I really miss is something you Unix-types will recognize > from awk (and perhaps from Algol 68?) - > for (t in table) > process(table[t]); > But that's another story.... Do you mean: for (t in some_set) process (table[t]) ? At least the draft Extended Pascal standard has this one. -- Norman Diamond, Sony Computer Science Lab (diamond%csl.sony.jp@relay.cs.net) The above opinions are my own. | Why are programmers criticized for If they're also your opinions, | re-inventing the wheel, when car you're infringing my copyright. | manufacturers are praised for it?
john@frog.UUCP (John Woods) (01/30/89)
In article <19579@agate.BERKELEY.EDU>, bowles@eris.berkeley.edu (Jeff A. Bowles) writes: > If I had a nickel for every time, in Fortran, > that I needed a loop that ran from 0.0 to 1.0 by 0.1 (or the like) ...you'd be broke. You NEVER need a loop that runs from 0.0 to 1.0 by 0.1. 1/10 is a repeating fraction in binary, and thus .1+.1+.1+.1+.1+.1+.1+.1+.1+.1 does NOT equal 1.0. Read "The Elements of Programming Style" for more tidbits on this and other programming topics. -- John Woods, Charles River Data Systems, Framingham MA, (508) 626-1101 ...!decvax!frog!john, john@frog.UUCP, ...!mit-eddie!jfw, jfw@eddie.mit.edu Presumably this means that it is vital to get the wrong answers quickly. Kernighan and Plauger, The Elements of Programming Style
fransvo@htsa.uucp (Frans van Otten) (01/30/89)
In article <6224@paris.ics.uci.edu> Doug Schmidt <schmidt@blanche.ics.uci.edu> writes: >I don't think you've gone far enough. After all, can't both a while >loop and a for loop be replaced by an if statement and a goto? >[..] >In fact, aren't all high-level control constructs superfluous? > >Doug And I propose to change the name of this newsgroup. It should be comp.lang.not_modula2_but_c ! -- Frans van Otten Algemene Hogeschool Amsterdam Technische en Maritieme Faculteit fransvo@htsa.uucp
dg@lakart.UUCP (David Goodenough) (01/31/89)
From article <1611@csuna.UUCP>, by abcscagz@csuna.UUCP (stepanek/cs assoc): > Actually, C's "for" can be duplicated EXACTLY by C's "do ... while" loops. > Consider: > > for (i = 0; i <= 17; ++i) > { > stuff(); > more_stuff(); > } > > versus: > > i = 0; > do { > stuff(); > more_stuff(); > } while (++i <= 17); Yes, but how about: for (i = 0; i <= a; i++) { lots_of_stuff(); } against: i = 0; do { lots_of_stuff(); } while (++i <= a); when the value of a is (say) -5. Are you _SURE_ these two are the same? Better would be to say a for loop can be replaced by a while loop: i = 0; while (i <= a /* or 17 */) { lots_of_stuff(); i++; } -- dg@lakart.UUCP - David Goodenough +---+ IHS | +-+-+ ....... !harvard!xait!lakart!dg +-+-+ | AKA: dg%lakart.uucp@xait.xerox.com +---+
barmar@think.COM (Barry Margolin) (01/31/89)
In article <1381@X.UUCP> john@frog.UUCP (John Woods) writes: ]In article <19579@agate.BERKELEY.EDU>, bowles@eris.berkeley.edu (Jeff A. Bowles) writes: ]> If I had a nickel for every time, in Fortran, ]> that I needed a loop that ran from 0.0 to 1.0 by 0.1 (or the like) ]...you'd be broke. You NEVER need a loop that runs from 0.0 to 1.0 by 0.1. ]1/10 is a repeating fraction in binary Just because Fortran can't do it doesn't mean that he doesn't NEED it; it just means he can't GET it. Since the real world mostly works in decimal, I imagine that the need is frequent. Luckily, there are well-known and easy ways around this problem. Barry Margolin Thinking Machines Corp. barmar@think.com {uunet,harvard}!think!barmar
marti@ethz.UUCP (Robert Marti) (01/31/89)
Please stop cross-posting this drivel about for-loops in C to comp.lang.modula2! (Gernot, are you listening, too?) Those Modula-2 hackers who don't know that a for-loop in C can be expressed as a while-loop but not as a do-loop probably couldn't care less ... -- Robert Marti Phone: +41 1 256 52 36 Institut fur Informatik ETH Zentrum CSNET/ARPA: marti%ifi.ethz.ch@relay.cs.net CH-8092 Zurich, Switzerland UUCP: ...uunet!mcvax!ethz!marti
flint@gistdev.UUCP (02/01/89)
I've always felt that it should be the job of programming languages to let me say what I want to do concisely, and then they should do it the way I want. Therefore, there is no reason I can see that the language should not let you have an increment of .1, since it is quite clear exactly what I want it to do in this case: the compiler ought to be able to see (easily) that it needs to set up a dummy integer counter to actually control the loop, and divide by 10 at the top of the loop for you to give you the index you use. By doing so, it allows experienced people to do less typing, and protects beginners from their ignorance- you win both ways. (It cannot necessarily deal with the round-off problems at the end of the loop of course: in the example cited, the question was whether to run the loop for 10 or 11 iterations. However, if the compiler does one division to make that decision & then codes an integer loop for you it's much more likely it will be what you wanted.) Flint Pellett, Global Information Systems Technology, Inc. 1800 Woodfield Drive, Savoy, IL 61874 (217) 352-1165 INTERNET: flint%gistdev@uxc.cso.uiuc.edu UUCP: {uunet,pur-ee,convex}!uiucuxc!gistdev!flint
hascall@atanasoff.cs.iastate.edu (John Hascall) (02/03/89)
In article <7800002@gistdev> flint@gistdev.UUCP writes: > ... Therefore, there is no reason I can see that the language should not >let you have an increment of .1, since it is quite clear exactly what I >want it to do in this case: the compiler ought to be able to see (easily) >that it needs to set up a dummy integer counter to actually control the >loop, and divide by 10 at the top of the loop for you to give you the index How's it supposed to know to use 10? When I do 1.0/0.1, I get 9.99999985... Well, it's pretty close to 10, let's use that :-) > ... in the example cited, the question was whether to run the loop for >10 or 11 iterations. However, if the compiler does one division to make >that decision & then codes an integer loop for you it's much more likely >it will be what you wanted.) That's the whole problem with this! I don't want code that's LIKELY to be what I wanted... I want the damn thing to do what I asked for. What's so hard about writing: for (i=0; i<10; i++) { f = 0.1*i; /* etc */ } John Hascall ISU Comp Center
bph@buengc.BU.EDU (Blair P. Houghton) (02/03/89)
In article <7800002@gistdev> flint@gistdev.UUCP writes: > >I've always felt that it should be the job of programming languages to let >me say what I want to do concisely, and then they should do it the way I >want. From the DEC Ultrix fortune-cookie file: "When someone says 'I want a programming language in which I need only say what I wish done,' give him a lollipop." So, would you like grape or lime? --Blair "I always like to do the right thing..."
geoff@warwick.UUCP (Geoff Rimmer) (02/03/89)
In article <6419@polya.Stanford.EDU> crew@Polya.Stanford.EDU (Roger Crew) writes: >Here's a quiz: >How would you write the following in C? > > VAR a, b, c : Char; > ... > FOR c = a TO b DO ... END; > >You can even assume that the body of the loop affects neither a nor b. >Hint: the answer is *not* > > char a, b, c; > ... > for (c = a; c <= b; ++c) { ... } > >(just try a = 0 and b = 255 in the case of 8 bit chars). >-- What a stupid question. If you are going to count from 0 to 255, you wouldn't use char in the first place - you'd use unsigned char, or int. I can't see what you're getting at, at all. Go back to writing Fortran. Let the *real* programmers use C. :-) >Roger Crew Copyright 1989 -- All Rights Reserved. (so there!) >Usenet: {arpa gateways, decwrl, uunet, rutgers}!polya.stanford.edu!crew >Internet: crew@polya.Stanford.EDU ------------------------------------------------------------ Geoff Rimmer, Computer Science, Warwick University, England. geoff@uk.ac.warwick.emerald "I didn't ask to be made. No consulted me or considered my feelings in the matter, not that anyone considered that I might *have* feelings. After I was made, I was left in a dark room for six months, and me with this terrible pain in all the diodes down my left side. My one and only true friend was a small rat. One day it climbed into a cavity of my inner leg and died. I've a horrible feeling it's still there." - Marvin, The Hitch Hiker's Guide to the Galaxy. ------------------------------------------------------------
sbigham@dukeac.UUCP (Scott Bigham) (02/03/89)
In article <7800002@gistdev> flint@gistdev.UUCP writes: > >I've always felt that it should be the job of programming languages to let >me say what I want to do concisely, and then they should do it the way I >want. What you want, it seems, is a programming language that can read your mind. > Therefore, there is no reason I can see that the language should not >let you have an increment of .1, since it is quite clear exactly what I >want it to do in this case: Obvious to you. How do you explain it to the compiler? > the compiler ought to be able to see (easily) >that it needs to set up a dummy integer counter to actually control the >loop, and divide by 10 at the top of the loop for you to give you the index >you use. That's not at all obvious, and in many cases it's not even possible. How do you resolve this loop? for (i=0.0;i<100.0;i+=PI); In the general case, such optimizations as you describe would require lots of convolutions and aren't useful often enough to be worth it. If you really want the compiler to use an integer, tell it to. > By doing so, it allows experienced people to do less typing, and >protects beginners from their ignorance- you win both ways. Not necessarily what we want to do. If you shelter beginners from their mistakes, they can't learn from them. Remember: for every situation in which the compiler does exactly what you want, there are at least ten people who think the compiler should do it differently. >Flint Pellett, Global Information Systems Technology, Inc. >1800 Woodfield Drive, Savoy, IL 61874 (217) 352-1165 >INTERNET: flint%gistdev@uxc.cso.uiuc.edu >UUCP: {uunet,pur-ee,convex}!uiucuxc!gistdev!flint sbigham -- Scott Bigham "The opinions expressed above are Internet sbigham@dukeac.ac.duke.edu (c) 1989 Hacker Ltd. and cannot be USENET sbigham@dukeac.UUCP copied or distributed without a ...!mcnc!ecsgate!dukeac!sbigham Darn Good Reason."
flint@gistdev.UUCP (02/04/89)
/* Written 10:02 am Feb 2, 1989 by atanasoff.cs.iastate.edu!hascall in gistdev:comp.lang.c */
In article <7800002@gistdev> flint@gistdev.UUCP writes:
How's it supposed to know to use 10?
When I do 1.0/0.1, I get 9.99999985... Well, it's pretty close to 10,
let's use that :-)
I guess it is obvious to me, not to others: If the increment that the user
wrote was 0.1, with one digit to the right of the decimal point, the
compiler should obviously use 10 as the denominator because 0.1 = 1/10. If
the user wrote a loop that incremented by 0.127, the compiler writer should
use 1000 for the divisor, because the user had 3 digits to the right of the
decimal. Any increment the user can type into their program can be exactly
represented as a fraction unless the compiler is stupid enough to throw
the information away. (IE, they use PI for the increment: where did you
get PI? Someplace had a #define PI 3.1415926. If the user gave you
7 digits of precision, use 10 ** 7 as the divisor that gives the floating
point value you need.)
It should be noted that I advocated doing this to "simple" loops where it
works, not to every loop. In the
do 10 i=0,1,0.1
case, you can KNOW to run this loop exactly 11 times: but not if you stupidly
try to divide 1/0.1 with binary based arithmetic, where it might round to a
result less than 10. Your user wrote the loop in decimal, and in decimal the
arithmetic produces an exact result. Think the math is too complex a task
for your compiler to do? Then try this simple trick:
What the programmer wrote in their code: do 10 i=2.5,3.75,0.25
Move the decimal points in the text 2 places right: do 10 i=250,375,25
(Manipulate the text string if you feel the need.)
Bingo, you've got an integer loop, you know to get the floating loop
index you divide by (10 ** 2) or 100 (because you slid the decimal places
2 positions in order to get rid of all the digits right of the decimal
points.) Note that in some loops, where i isn't even used in the body of
the loop, you can dispense with the floating point altogether now.
You can certainly argue that doing the above won't protect you in every
single case, and you're right, it won't. But that sounds to me a lot like
arguing that you shouldn't have optimizers because they might change the
code to not be exactly what the programmer wrote. I believe that in all
the examples presented so far you do know exactly what the programmer wanted
you to do.
Flint Pellett, Global Information Systems Technology, Inc.
1800 Woodfield Drive, Savoy, IL 61874 (217) 352-1165
INTERNET: flint%gistdev@uxc.cso.uiuc.edu
UUCP: {uunet,pur-ee,convex}!uiucuxc!gistdev!flint
hascall@atanasoff.cs.iastate.edu (John Hascall) (02/06/89)
In article <7800003@gistdev> flint@gistdev.UUCP writes: >It should be noted that I advocated doing this to "simple" loops where it >works, not to every loop. In the > do 10 i=0,1,0.1 >case, you can KNOW to run this loop exactly 11 times: but not if you stupidly >try to divide 1/0.1 with binary based arithmetic, where it might round to a >result less than 10. Your user wrote the loop in decimal, and in decimal the >arithmetic produces an exact result. Think the math is too complex a task >for your compiler to do? Then try this simple trick: >What the programmer wrote in their code: do 10 i=2.5,3.75,0.25 >Move the decimal points in the text 2 places right: do 10 i=250,375,25 >(Manipulate the text string if you feel the need.) >Bingo, you've got an integer loop, you know to get the floating loop >index you divide by (10 ** 2) or 100 (because you slid the decimal places >2 positions in order to get rid of all the digits right of the decimal >points.) Sure, it works in some simple cases, but how do you propose to handle: start = expression-which-gives_2.5 end = expression-which-gives_3.75 incr = expression-which-gives_0.25 do 10 i=start,end,incr now we don't know which power of 10 to use, having no "textual" information from the users program. Or how about: do i=0.0, 4.0, 2.0/3.0 I suppose now our compiler has to do fractions too...because to you and I the meaning is clear, but to a compiler it's: do i=0.0, 4.0, 0.6666667 giving the sequence: instead of the expected: 0.0000000 0.0000000 0.6666667 0.6666667 1.3333334 1.3333333 2.0000001 2.0000000 2.6666668 2.6666667 3.3333335 3.3333333 --------- 4.0000000 4.0000002 --------- 4.3333333 I don't know who said it, but, "If you make a system fool-proof, only a fool will use it" John Hascall ISU Comp Center p.s. liberally apply :-)'s above, I just like to disagree, it provokes thought.
crew@Polya.Stanford.EDU (Roger Crew) (02/07/89)
In article <1004@ubu.warwick.UUCP>, geoff@warwick (Geoff Rimmer) writes: > In article <6419@polya.Stanford.EDU> crew@Polya.Stanford.EDU (Roger Crew) writes: > >Here's a quiz: > >How would you write the following in C? > > > > VAR a, b, c : Char; > > ... > > FOR c = a TO b DO ... END; > > [ ... yup, this discussion ...] > > What a stupid question. If you are going to count from 0 to 255, you > wouldn't use char in the first place - you'd use unsigned char, or > int. I can't see what you're getting at, at all. I'll grant that, for the benefit of compilers that *have* signed chars, I actually did intend to say ``unsigned char'' rather than ``char''. The fact of the matter is, however, that unsigned char a; for( c=0; c<=255; ++c) {...} still doesn't work. You can try it if you like, or you can read the submissions from the other 10 posters who understand what's going on... The fact that I was using chars signed or unsigned is irrelevant to the point I was trying to make, namely that the semantics of C for-loops and Modula/Pascal for-loops are entirely different -- it is not simply a case of one being more general than the other. While it's fairly obvious that a general C for-loop often can't be written as a Modula for-loop, it's not so obvious (or at least, *I* didn't think it was completely obvious...) that to do a general Modula for-loop in C *also* requires strange contortions. As for *why* I'd want to be counting with chars, just consider any application requiring some kind of array indexed by chars, e.g., VAR font : ARRAY Char OF Bitmap; It's an obvious thing to do in Modula. I suppose this also illustrates the danger of carrying over one languages way of thinking into another, a problem that does not confine itself to for-loops. > Go back to writing Fortran. Let the *real* programmers use C. :-) I'll let this statement speak for itself. :=) -- Roger Crew ``Beam Wesley into the sun!'' Usenet: {arpa gateways, decwrl, uunet, rutgers}!polya.stanford.edu!crew Internet: crew@polya.Stanford.EDU
flint@gistdev.UUCP (02/07/89)
/* Written 12:19 pm Feb 5, 1989 by atanasoff.cs.iastate.edu!hascall in gistdev:comp.lang.c */ > Sure, it works in some simple cases, but how do you propose to > handle: > > start = expression-which-gives_2.5 > end = expression-which-gives_3.75 > incr = expression-which-gives_0.25 > do 10 i=start,end,incr > > now we don't know which power of 10 to use, having no "textual" > information from the users program. From my previous posting: (as George Bush would say: "Read my lips" :-) ) >>It should be noted that I advocated doing this to "simple" loops where it >>works, not to every loop. I believe we both just said the same thing, so I'll assume you are agreeing with me: you just provided an example of a case you can't optimize as I stated there would be. > Or how about: > > do i=0.0, 4.0, 2.0/3.0 > > I suppose now our compiler has to do fractions too...because to > you and I the meaning is clear, but to a compiler it's: > > do i=0.0, 4.0, 0.6666667 The compiler has two choices here: 1. Do the division right away, as you just did (something I believe is an error: to use your arguments, "if I wanted 0.666667 instead of 2/3, I would have said 0.66667!"), or 2. be smart, and multiply the denominators through: this is exactly what it is doing in the case of decimals. ie, (so that it is obvious :-) ), this loop: (Why are we debating this using Fortran syntax for God's sake?) do i = 3.25,4.1,.1 is really the same (when written in terms of fractions) as this one: do i = 325./100.,41./10.,1./10. and when you multiply everything by 100 and it becomes integer, ie: do i = 325,410,10 So if your user had written (hascall's previous example below) > do i=0.0, 4.0, 2.0/3.0 you just multiply everything by 3 to convert it into this: do i=0,12,2 float=i/3.0 And if they wrote this: do i=2./3.,15./4.,1./12. You can multiply each by 12 to get this loop: do i=8,45,1 float=i/12.0 (How to decide what the smallest integer value to multiply through by is left as a 7th grade level arithmetic exercise for the reader.) In other words, I was already advocating that the compiler do fractions, you assumed that I only wanted it to deal with the specific case where the denominators in the fractions are powers of 10. If the user writes 2/3 in their code instead of 0.667, and the compiler can make use of the extra information that 2/3 conveys, then it ought to do so. I don't think (but I could be wrong: it has happened before :-) ) that there is any loop you can write that contains only constants for the loop start/end/increment that cannot be converted into an integer controlled loop in a straightforward manner. If you can optimize someone's program for speed, you ought to be willing to optimize it for accuracy as well.
wald-david@CS.YALE.EDU (david wald) (02/08/89)
In article <7800004@gistdev> flint@gistdev.UUCP writes: >/* Written 12:19 pm Feb 5, 1989 by atanasoff.cs.iastate.edu!hascall in gistdev:comp.lang.c */ >> Sure, it works in some simple cases, but how do you propose to >> handle: >> ["do" loop with non-constant start, end and increment] >> >> now we don't know which power of 10 to use, having no "textual" >> information from the users program. > >From my previous posting: (as George Bush would say: "Read my lips" :-) ) >>>It should be noted that I advocated doing this to "simple" loops where it >>>works, not to every loop. > >I believe we both just said the same thing, so I'll assume you are agreeing >with me: you just provided an example of a case you can't optimize as I >stated there would be. > >> Or how about: >> >> do i=0.0, 4.0, 2.0/3.0 > >The compiler has two choices here: 1. Do the division right away, as you >just did (something I believe is an error: to use your arguments, "if I wanted >0.666667 instead of 2/3, I would have said 0.66667!"), or 2. be smart, and >multiply the denominators through: this is exactly what it is doing in the >case of decimals. ... >(How to decide what the smallest integer value to multiply through by is left >as a 7th grade level arithmetic exercise for the reader.) > >In other words, I was already advocating that the compiler do fractions, >you assumed that I only wanted it to deal with the specific case where >the denominators in the fractions are powers of 10. If the user writes >2/3 in their code instead of 0.667, and the compiler can make use of the >extra information that 2/3 conveys, then it ought to do so. > >I don't think (but I could be wrong: it has happened before :-) ) that >there is any loop you can write that contains only constants for the >loop start/end/increment that cannot be converted into an integer >controlled loop in a straightforward manner. If you can optimize someone's >program for speed, you ought to be willing to optimize it for accuracy >as well. This bothers me a bit, for the following reason (and I'm switching back to for(;;) syntax, since I later assume a system with a C-like preprocessor): You seem to be advocating different semantics for a for(;;) loop based on whether the expressions it contains are constant or not. In a couple of examples we've seen that the for(;;) construct will loop a different number of times depending on whether or not the denomonator is multiplied away. At what point do you proclaim the compiler "smart enough"? Is it enough to deal with constant expressions? How about constant expressions hidden by macros? (Clearly, there's no way of dealing with the former and not the latter, but you now can have something which may appear to be in function syntax, but actually turns into a constant expression.) What if there's a macro defined as: #ifdef _SOME_WEIRD_FEATURE_FLAG # define macro(x) some_nonconstant_function_of(x) #else # define macro(x) 3 #endif and you produce code that goes for(i=0; i<=4; i += 2/macro(j)) some_expression_affecting_j; What does your friendly-and-intelligent compiler do? And how do you, as programmer, know how long your loop is going to go? Remember that the compiler will never see the macro nonsense, only the expressions that substitute for it. If you require the programmer to know whether the macro above evaluates to a constant or not, you are eliminating all the code-hiding benefits of macros, since the programmer must know what's inside them. The programer must also take the feature flag into account in the middle of a program, perhaps multiple times, whereas the absence of the "optimization" might allow it to be hidden in a header file. Finally, as has been stated ad nauseum in this forum, an optimization should never change the semantics of a program, because you never know when it's going to be done. What if a slightly smarter version of this "optimization" is employed, such that it can find non-constant expressions that are nevertheless compiler-provably constant for the duration of the loop. You get even better benifits, in your terms, but even more disagreement between compilers that do and don't change their loop semantics in different circumstances, depending on how good they are at finding constant expressions. If I'm writing code, I want to know how long I'm going to loop, no matter what compiler my code is compiled with. That's a fairly basic issue. If compilers actually "have a choice" about this sort of interpretation, I don't know this. ============================================================================ David Wald wald-david@yale.UUCP waldave@yalevm.bitnet wald-david@cs.yale.edu "A monk, a clone and a ferengi decide to go bowling together..." ============================================================================
ark@alice.UUCP (Andrew Koenig) (02/08/89)
In article <7800004@gistdev>, flint@gistdev.UUCP writes: > So if your user had written (hascall's previous example below) > > do i=0.0, 4.0, 2.0/3.0 > you just multiply everything by 3 to convert it into this: > do i=0,12,2 > float=i/3.0 Sure, this could be done. It has a nasty side effect, though: do i = 0.0, 4.0, 2.0/3.0 will mean something different from x = 2.0 y = 3.0 do i = 0.0, 4.0, x/y I would rather have a system whose behavior doesn't change when I replace a value by another identical value. -- --Andrew Koenig ark@europa.att.com
henry@utzoo.uucp (Henry Spencer) (02/09/89)
In article <2026@buengc.BU.EDU> bph@buengc.bu.edu (Blair P. Houghton) writes: > "When someone says 'I want a programming language in which I > need only say what I wish done,' give him a lollipop." There are a number of such languages, actually: English is an example. The compilers are known as "graduate students". Unfortunately, they tend to be available only in Computer Science departments... -- Allegedly heard aboard Mir: "A | Henry Spencer at U of Toronto Zoology toast to comrade Van Allen!!" | uunet!attcan!utzoo!henry henry@zoo.toronto.edu