From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.3 required=5.0 tests=BAYES_00,INVALID_MSGID autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,2acb7591d4833271 X-Google-Attributes: gid103376,public From: dewar@merv.cs.nyu.edu (Robert Dewar) Subject: Re: loop step function Date: 1997/01/30 Message-ID: #1/1 X-Deja-AN: 213213451 references: <32E93C0B.36A@cloud9.net> <1997Jan24.192209.1@eisner> <32EF6187.3F54BC7E@escmail.orl.lmco.com> organization: New York University newsgroups: comp.lang.ada Date: 1997-01-30T00:00:00+00:00 List-Id: Larry Kilgallen wrote: > As regards FOR loops, you could say: > > for BY_ONE from 1 to 20 loop > declare > USEFUL_VALUE : INTEGER := BY_ONE*2; > begin > my_procedure ( USEFUL_VALUE ); > end; > end loop; Ted Dennision responded >Wouldn't that allocate and deallocate stack space in a loop? Yuck. >Why not just replace - > my_procedure ( USEFUL_VALUE ); >with > my_procedure ( USEFUL_VALUE*2 ); Robert replies (note: in the following discussion I assume that Larry's Pascal style slip "from 1 to 20" is replaced by proper Ada: "in 1 .. 20" -- it is always a good idea to compile examples you post to CLA, since it can confuse students to see wrong code!) No, of course not! Any compiler one can imagine using would merge the frame of the block with the frame of the enclosing procedure. It is only when objects of large or dynamic length are declared locally in blocks that there is allocation acivity. Worrying about the above code is an example of knowing enough to cause oneself trouble, but not enough to do the right thing -- declaring scalar objects like this in nested blocks is good Ada style! The one thing I would change in the above quote is that I would put the keyword 'constant' before INTEGER (and I would not use all upper case identifiers :-) Ted's suggestion of replacing the parameter in the call misses the point. Remember that we are modeling the effect of step here, and there may be many references to Useful_Value in the loop. So, "yuck" is not an appropriate reaction to this code. Larry's general paradigm for translating stepping loops is good style, and has no efficiency penalty. Ted says: >In this case, though, the newbie may be right. The while loop is liable >to be more efficient Robert replies: This depends on the compiler you are using. Compilers that do extensive loop optimization may well recognize useful_Value as an induction variable of the loop. Then test replacement is possible and By_One can be completely eliminated from the code yielding code that is equivalent to the for loop. This is all pretty standard optimization stuff -- see for example the treatment of optimization in the Dragon book. Trying this out on GCC, we don't quite do that well (GCC concentrates more on local peephole optimization rather than on loop optimizations of this type), but on the other hand, in the program: with Text_IO; use Text_IO; procedure t is Useful_Value : Integer; begin for By_One in 1 .. 20 loop declare Useful_Value : Integer := By_One*2; begin Put (Integer'Image (Useful_Value)); end; end loop; Useful_Value := 2; while Useful_Value < 20 * 2 loop Put (Integer'Image (Useful_Value)); Useful_Value := Useful_Value + 2; end loop; end; The first loop has only one additional register instruction compared to the second, hardly enough to get excited about! It would be interesting to examine what happens on other compilers with the above test program.