home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #18 / NN_1992_18.iso / spool / comp / lang / cplus / 12756 < prev    next >
Encoding:
Internet Message Format  |  1992-08-21  |  4.3 KB

  1. Path: sparky!uunet!usc!cs.utexas.edu!devnull!rgp
  2. From: rgp@mpd.tandem.com (Ramon Pantin)
  3. Newsgroups: comp.lang.c++
  4. Subject: Re: Tiny proposal for named loops.
  5. Message-ID: <2294@devnull.mpd.tandem.com>
  6. Date: 22 Aug 92 07:17:56 GMT
  7. References: <aldavi01.714376080@starbase.spd.louisville.edu> <rmartin.714435942@dirac>
  8. Sender: news@devnull.mpd.tandem.com
  9. Organization: Tandem Computers, Micro-Products Division
  10. Lines: 125
  11.  
  12. In article <rmartin.714435942@dirac> rmartin@dirac.Rational.COM (Bob Martin) writes:
  13. >
  14. >IMHO breaks and continues should be avoided, not improved.  As you
  15. >say, they are a form of goto.  Don't use them, except in case
  16. >statements where you must :-( use break.
  17.  
  18. Pretty dogmatic huh?
  19. I imagine that you only have one return statement at the end of
  20. your functions (I'm not going to even ask you about gotos).
  21.  
  22. >State variables are preferable to breaks and continues.  Judicious use
  23. >of them allows all loops and blocks to be exited at the same place.
  24.  
  25. So what?
  26.  
  27. >This benefit outweighs the disadvantage of using a flag.
  28.  
  29. You call that a benefit?
  30.  
  31. IMNSHO, each "state variable" that you invent to avoid using a
  32. break, continue or return, when it is natural to do so, is just a
  33. replacement for immediately expressing your intentions:
  34.  
  35.     - Break, I'm done with this loop, lets get out of it.
  36.     - Continue, I'm done with this case, the code that follows
  37.       doesn't apply to this case, lets go to the next iteration.
  38.     - Return, I'm done, lets get out of this function.
  39.  
  40. Instead your code saves in a state variable what your intentions are
  41. Then your code "judiciously" proceeds to test these state variables in
  42. the right places to avoid executing the code that should be skipped
  43. because you are not really supposed to be there anyway.
  44.  
  45. A very SIMPLE example:
  46.     a, b, c and d are arbitrary expressions (maybe with side effects),
  47.     *_statements are arbitrary sequences of statements.
  48.  
  49.     /* C code, _just_ 1 break, 1 continue, 16 lines */
  50.     while (a) {
  51.         if (b) {
  52.             b_true_statements;
  53.             if (c) {
  54.                 c_true_statements;
  55.                 break;
  56.             }
  57.             c_false_statements;
  58.             if (d) {
  59.                 d_true_statements;
  60.                 continue;
  61.             }
  62.             d_false_statements;
  63.         }
  64.         post_b_statements;
  65.     }
  66.  
  67.     /*
  68.      * Pascaloid code, 2 state variables, 3 tests, 2 sets, 22 lines.
  69.      * Certainly the complexity (by any count!) "outweighs" that of
  70.      * the previous code.
  71.      */
  72.  
  73.     /*
  74.      * MAINTAINER NOTES:
  75.      * Loop exited in only one place. (So what?)
  76.      * Where the heck is this "done" set that causes this loop
  77.      * to be exited here?  As far as I'm concerned the loop is
  78.      * exited also where "done" is set (humm, that might not be
  79.      * true, some more code might execute after that assignemnt
  80.      * so I better watch for that also).  Rewrite this in C.
  81.      * Who was the Pascal programmer who wrote this messy code anyway?
  82.      * Lets send him for instruction to some C programming courses.
  83.      */
  84.     done = 0;        /* judiciously introduce state variable */
  85.     while (!done && a) {    /* j. test s. v. */
  86.         skip = 0;    /* j. i. s. v. */
  87.         if (b) {
  88.             b_true_statements;
  89.             if (c) {
  90.                 c_true_statements;
  91.                 done = 1;    /* j. set. s. v. */
  92.             } else {
  93.                 c_false_statements;
  94.                 if (d) {
  95.                     d_true_statements;
  96.                     skip = 1;/* j. set. s. v. */
  97.                 } else {
  98.                     d_false_statements;
  99.                 }
  100.             }
  101.         }
  102.         /*
  103.          * CAVEAT MAINTAINER: don't just simply add code here,
  104.          * read next caveat.
  105.          */
  106.         if (!done || skip) {    /* j. test. s. v. */
  107.             post_b_statements;
  108.         }
  109.         /*
  110.          * CAVEAT MAINTAINER: review the whole function before
  111.          * adding code here, code to be added to the end of the
  112.          * loop goes in the "if" above, otherwise the cases:
  113.          *    b && c
  114.          *    b && !c && d
  115.          * would be broken.
  116.          */
  117.     }
  118.  
  119. Why do you think that most modern languages have things similar
  120. to continue, break and multiple returns?  N. Wirth omited them
  121. from Pascal to avoid programming students from going crazy
  122. with the gotos before they learnt how to program (which explains
  123. why some programmers that had early and continuous exposure to
  124. BASIC seem to have had so many side effects from it :-).
  125.  
  126. I suggest that you try rewriting some of your code using breaks,
  127. continues, and multiple returns, you might really like it!  :-)
  128. You might also want to try some of those forbiden gotos.  As you
  129. already know, there is a place for everything, and excess can hurt
  130. you, so be carefull (specially with those handy gotos)!
  131.  
  132. >Robert Martin
  133.  
  134. Nothing personal Robert, I just couldn't resist!  :-)
  135.  
  136. Ramon Pantin
  137.