rfc:loop_else
no way to compare when less than two revisions
Differences
This shows you the differences between two versions of the page.
Next revision | |||
— | rfc:loop_else [2012/05/11 03:07] – created ravazin | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ====== Request for Comments: Loop+Else control structure ====== | ||
+ | * Version: 1.0 | ||
+ | * Date: 2012-05-10 | ||
+ | * Author: Dmitri Ravazin < | ||
+ | * Status: Draft | ||
+ | * First Published at: http:// | ||
+ | * Original discussion: https:// | ||
+ | |||
+ | ===== Introduction ===== | ||
+ | |||
+ | Performing a set of actions upon *not* entering a loop is a very common programming necessity. This RFC proposes an optional " | ||
+ | |||
+ | A secondary objective of this RFC is to bring closure to a number of requests in bug tracker (hopefully they can be closed after this, whatever the resolution). | ||
+ | |||
+ | ==== Syntax ==== | ||
+ | Proposed syntax will look as follows: | ||
+ | <code php> | ||
+ | // " | ||
+ | foreach ($array as $x) { | ||
+ | echo "Name: {$x-> | ||
+ | } else { | ||
+ | echo "No records found!\n"; | ||
+ | } | ||
+ | |||
+ | // " | ||
+ | for ($i = some_very_expensive_and_ugly_looking_calculation($array); | ||
+ | unset($array[$i]); | ||
+ | } else { | ||
+ | return null; // horrific error! | ||
+ | } | ||
+ | return $array; | ||
+ | |||
+ | // " | ||
+ | while ($temp = array_search($search, | ||
+ | unset($array[$temp]); | ||
+ | } else { | ||
+ | unset($array[$search]); | ||
+ | return false; | ||
+ | } | ||
+ | return true; | ||
+ | </ | ||
+ | And for comparison purposes, the following block (it's obviously longer and less elegant) contains the same code written //without// loop+else: | ||
+ | <code php> | ||
+ | foreach ($array as $x) { | ||
+ | echo "Name: {$x-> | ||
+ | } | ||
+ | if (count($array) < 1) { | ||
+ | echo "No records found!\n"; | ||
+ | } | ||
+ | |||
+ | |||
+ | |||
+ | if (some_very_expensive_and_ugly_looking_calculation($array) < 0) { // either that or clutter our scope with temporary variable | ||
+ | return null; | ||
+ | } | ||
+ | for ($i = some_very_expensive_and_ugly_looking_calculation($array); | ||
+ | unset($array[$i]); | ||
+ | } | ||
+ | return $array; | ||
+ | |||
+ | |||
+ | |||
+ | $removed = false; // no choice... have to remember this in a variable | ||
+ | while ($temp = array_search($search, | ||
+ | unset($array[$temp]); | ||
+ | $removed = true; | ||
+ | } | ||
+ | if (!$removed) { | ||
+ | unset($array[$search]); | ||
+ | } | ||
+ | return $removed; | ||
+ | </ | ||
+ | |||
+ | ===== How does this work? ===== | ||
+ | |||
+ | ==== When is loop's " | ||
+ | Proposed " | ||
+ | For this reason do-while loop cannot have this syntax (as it is guaranteed that its body will be entered at least once). | ||
+ | |||
+ | So in general, a loop+else construct is the equivalent of the following user code: | ||
+ | <code php> | ||
+ | $loop_entered = false; | ||
+ | loop ($condition) { | ||
+ | // " | ||
+ | $loop_entered = true; | ||
+ | } | ||
+ | if (!$loop_entered) { | ||
+ | // this is our " | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== What about loops without a body? ==== | ||
+ | I suggest loops without a body should not be allowed to have an alternate " | ||
+ | <code php> | ||
+ | while($condition); | ||
+ | for ($i = 0; $i < 10; $i++); | ||
+ | foreach ($array as $x); | ||
+ | </ | ||
+ | |||
+ | ==== What is the precedence? ==== | ||
+ | In order to avoid BC breaks when single-statement blocks are not enclosed in {}'s, any ambiguity should always be resolved in favor of if's. | ||
+ | This means that in the following sample " | ||
+ | <code php> | ||
+ | if ($hungry) | ||
+ | while (more_food()) { | ||
+ | eat(); | ||
+ | else | ||
+ | watch_tv(); | ||
+ | </ | ||
+ | However, when there is no conflict between a loop and an " | ||
+ | This means that in the following sample " | ||
+ | <code php> | ||
+ | while ($condition) | ||
+ | foreach ($array as $x) | ||
+ | $x-> | ||
+ | else | ||
+ | echo "No work was done!\n"; | ||
+ | </ | ||
+ | |||
+ | ==== Alternative syntax for control structures ==== | ||
+ | This should work as expected (while respecting the precedence order described above), e.g.: | ||
+ | <code php> | ||
+ | <?php while ($x = $cursor-> | ||
+ | < | ||
+ | <?php else: ?> | ||
+ | < | ||
+ | <?php endwhile; ?> | ||
+ | </ | ||
+ | |||
+ | ==== How about elseif? ==== | ||
+ | Under this proposal, the following PHP code would be valid: | ||
+ | <code php> | ||
+ | while ($condition) { | ||
+ | ... | ||
+ | } else if ($another_condition) { | ||
+ | ... | ||
+ | } else { | ||
+ | ... | ||
+ | } | ||
+ | </ | ||
+ | Because of that, I believe it would make sense to allow loop+elseif syntax as well. | ||
+ | |||
+ | ===== Pros ===== | ||
+ | * This makes code shorter, more flat, and more readable. (this is the primary objective) | ||
+ | * Eliminates the annoyance of having to use flag variables in a lot of common use-cases | ||
+ | * Code is more structured and predictable (e.g. no more if's that can come before OR after the loop) | ||
+ | * No new keywords | ||
+ | * No BC breaks | ||
+ | * PHP would not be the first language to implement such a structure. Python has it (although it behaves differently there). | ||
+ | * This feature has almost universal support in userland (related feature requests in bug tracker are among the highest rated of all time) | ||
+ | |||
+ | ===== Cons ===== | ||
+ | * "This new syntax is excessive and can be confusing to new developers" | ||
+ | * "This violates the KISS principle" | ||
+ | * Overhead? | ||
+ | * Complicated changes to the parser? Too much work for a relatively minor syntax sugar? | ||
+ | * This syntax is not supported by any of the "big mountains" | ||
+ | |||
+ | ===== Common Misconceptions ===== | ||
+ | |||
+ | * Proposed syntax can be achieved by a simple " | ||
+ | * While true in some cases (for example in most " | ||
+ | * Even when temporary variable can be avoided, an extra " | ||
+ | |||
+ | ===== Alternative Proposals ===== | ||
+ | We could also do it the Python way, which means executing " | ||
+ | I personally see this a lot less useful than this proposal. | ||
+ | |||
+ | |||
+ | ===== References ===== | ||
+ | |||
+ | Original discussions in bug tracker: | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | ===== Changelog ===== | ||
+ | May 10, 2012 - RFC draft created |
rfc/loop_else.txt · Last modified: 2021/03/27 14:26 by ilutov