{"id":539,"date":"2012-08-20T15:56:44","date_gmt":"2012-08-20T19:56:44","guid":{"rendered":"http:\/\/blog.bitsofgenius.com\/?p=539"},"modified":"2012-08-20T15:57:31","modified_gmt":"2012-08-20T19:57:31","slug":"when-a-loop-is-not-a-loop","status":"publish","type":"post","link":"https:\/\/blog.bitsofgenius.com\/?p=539","title":{"rendered":"When a loop is not a loop"},"content":{"rendered":"<p>In an earlier post, I showed how to rethink the traditional MS-SQL CURSOR logic pattern, to minimize the number of maintenance points for FETCH statements (<a href=\"?p=50\" target=\"_blank\">The lost art of break and continue<\/a>). That post covered the while() { &#8230; } loop. Another equally-useful\u00a0variant is the do { &#8230; } while() loop, which also supports the break and continue statements.<\/p>\n<p>The main difference between the two loop types is the number of guaranteed times the loop will execute. The while loop evaluates the boolean case at the beginning, so its content will not run at all if the initial boolean test evaluates to false. \u00a0For the SQL CURSOR example, these is useful when the number of rows to process is zero: the row handling logic doesn&#8217;t execute at all.<\/p>\n<p>The do..while() loop is very useful for evaluating complex\u00a0business logic using extensive branching (e.g. rate\/tarff calculations). \u00a0The loop is guaranteed to always execute, and a break statement can exit the loop block at any time. \u00a0This is a great way to implement short-circuiting for evaluations (sometimes referred to as a trap-door sequence). \u00a0A trap door sequence is common in rate or tariff calculations, where a number of factors are evaluated to determine a specific rate or tariff. \u00a0Once the tariff is determined, the evaluation ends (the trap door) and the logic to further apply the calculated tariff continues.<\/p>\n<p>An example of this type of logic using if() statements would look like this:<\/p>\n<pre lang=\"c\">money Rate = -1.0;\r\n\r\nif (Rate == -1.0 && TestCase1() == false) Rate = 2.0;\r\nif (Rate == -1.0 && TestCase2())\r\n{\r\n  if (SubTest1ofTestCase2() == false)\r\n  {\r\n    if (SubTest2ofTestCase2() == true)\r\n    {\r\n      Rate = 1.754;\r\n    }\r\n    else Rate = 1.872;\r\n  }\r\n}\r\nif (Rate == -1.0)  \/\/ when true, the rate is still indeterminate\r\n{\r\n  if (TestCase3() == false) Rate = 2.715;\r\n}\r\n\r\nif (Rate == -1.0)\r\n{\r\n  Rate = 2.772;   \/\/ apply a default, throw an error... whatever\r\n}\r\n\r\n\/\/ Rate application logic follows here<\/pre>\n<p>The penalty with this method, when a large number of evaluations is done, is that often the if(Rate == -1.0) statement has to end, and another if(Rate == -1.0) statement has to wrap the next set of logic that evaluates the next case. \u00a0If the rule set is long, the number of\u00a0if(Rate == -1.0) wrappers will increase accordingly. There is no quick way out of the evaluation, just a way of stopping the next evaluation from occurring.<\/p>\n<p>Since the do..while() loop evaluates at the end of the block, the code within the do loop is guaranteed to run at least once. \u00a0Set the ending evaluation to while(false) or until (true), and the code in the do&#8230;while() loop sequence only executes once. \u00a0Add the use of the break statement, and the do loop is perfectly suited for a block of code that requires a single pass and needs a quick exit: the trap-door sequence. \u00a0Have a look at the following example, which uses break statements, to solve the same problem.<\/p>\n<pre lang=\"c\">money Rate = -1.0;\r\ndo\r\n{\r\n  if (Rate == -1.0 && TestCase1() == false) \r\n  {\r\n    Rate = 2.0;\r\n    break;\r\n  }\r\n  if (TestCase2())\r\n  {\r\n    if (SubTest1ofTestCase2() == false)\r\n    {\r\n      if (SubTest2ofTestCase2() == true)\r\n      {\r\n        Rate = 1.754;\r\n        break;\r\n    }\r\n    else\r\n    {\r\n      Rate = 1.872;\r\n      break;\r\n    }\r\n  }\r\n  if (TestCase3() == false)\r\n  {\r\n    Rate = 2.715;\r\n    break;\r\n  }\r\n  Rate = 2.772;   \/\/ apply a default, throw an error... whatever\r\n} while (false);   \/\/ or until (true)... guarantees iteration will not occur.\r\n\r\n\/\/ Rate application logic follows here\r\n\/\/ ...\r\n<\/pre>\n<p>Many people would argue that the same effect can be established with GOTO statements and a label. \u00a0Even in my days programming modular code, I never liked the goto statement. \u00a0With line numbers in archaic BASIC code it made sense, but migrating it to use labels in object-oriented code seems to be carrying forward a hack: a way for old-school developers to find a way out of their code.<\/p>\n<p>Break simply says the loop is ending, and is also a nice word choice to say the logic has a reason to &#8220;break out&#8221; of what it is doing. \u00a0The break statements, to me, are easier to follow as a developer inheriting someone else&#8217;s code base, and doesn&#8217;t break the rhythm of the logic.<\/p>\n<p>This trap-door technique with the do { &#8230; } while() loop has proven very useful. I encourage you to try it.<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In an earlier post, I showed how to rethink the traditional MS-SQL CURSOR logic pattern, to minimize the number of maintenance points for FETCH statements (The lost art of break and continue). That post covered the while() { &#8230; } loop. Another equally-useful\u00a0variant is the do { &#8230; } while() loop, which also supports the [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[13,17],"tags":[],"class_list":["post-539","post","type-post","status-publish","format-standard","hentry","category-technologythoughts","category-tips-and-tricks"],"_links":{"self":[{"href":"https:\/\/blog.bitsofgenius.com\/index.php?rest_route=\/wp\/v2\/posts\/539","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.bitsofgenius.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.bitsofgenius.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.bitsofgenius.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.bitsofgenius.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=539"}],"version-history":[{"count":0,"href":"https:\/\/blog.bitsofgenius.com\/index.php?rest_route=\/wp\/v2\/posts\/539\/revisions"}],"wp:attachment":[{"href":"https:\/\/blog.bitsofgenius.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=539"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.bitsofgenius.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=539"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.bitsofgenius.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=539"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}