rfc:loop_or
Differences
This shows you the differences between two versions of the page.
rfc:loop_or [2014/09/20 16:48] leigh |
rfc:loop_or [2017/09/22 13:28] |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== loop + or control structure ====== | ||
- | * Version: 1.0 | ||
- | * Date: 2014-09-19 | ||
- | * Author: Leigh, leight -> gmail | ||
- | * Status: Under Discussion | ||
- | * First Published at: http:// | ||
- | |||
- | ===== Introduction ===== | ||
- | |||
- | It is often desirable to perform a set of actions if the conditions to enter a loop are //not// met. This can require a significant amount of boilerplate code if the conditions are complex. | ||
- | |||
- | This RFC proposes an optional default control block for loops, that is executed in the event that the loop is not entered. | ||
- | |||
- | ===== Proposal ===== | ||
- | |||
- | Pre-condition loops (for, foreach and while) will be allowed to have an optional default block (using the existing '' | ||
- | |||
- | Usage: | ||
- | |||
- | <code php> | ||
- | while ($cond) { | ||
- | // loop body | ||
- | } | ||
- | or{ | ||
- | // did not enter while loop | ||
- | } | ||
- | |||
- | for ($i = 0, $j = $k; $i < 4 && $j < 65536; $i++, $j <<= 1) { | ||
- | // loop body | ||
- | } | ||
- | or { | ||
- | // did not enter for loop | ||
- | } | ||
- | |||
- | foreach (generator() as $k => $v) { | ||
- | // loop body | ||
- | } | ||
- | or { | ||
- | // did not enter foreach loop | ||
- | } | ||
- | </ | ||
- | |||
- | In the case of '' | ||
- | |||
- | '' | ||
- | |||
- | Alternate syntax loops also gain this functionality with a '' | ||
- | |||
- | This type of behaviour has been suggested before typically using the '' | ||
- | |||
- | The originally conceived alternative was to use the '' | ||
- | |||
- | * Not backwards compatible by default due to dangling '' | ||
- | <code php> | ||
- | if ($something) | ||
- | while ($cond) | ||
- | // loop body | ||
- | else | ||
- | // this now belongs to the while loop | ||
- | </ | ||
- | |||
- | * Making it backwards compatible leads to inconsistent behaviour | ||
- | <code php> | ||
- | if ($something) | ||
- | while ($cond) | ||
- | // loop body | ||
- | else | ||
- | // this still belongs to the if statement | ||
- | </ | ||
- | |||
- | * It breaks familiarity with similar behaviour in other languages | ||
- | <code php> | ||
- | while ($cond) { | ||
- | // loop body | ||
- | } | ||
- | else { | ||
- | // In Python this will always execute unless break; is used in the loop body | ||
- | } | ||
- | </ | ||
- | |||
- | Using '' | ||
- | <code php> | ||
- | switch ($x) { | ||
- | case 1: | ||
- | while ($y) | ||
- | // stuff | ||
- | default; | ||
- | // stuff | ||
- | } | ||
- | </ | ||
- | |||
- | These scenarios could be solved by introducing a new keyword, however to maintain backward compatibility as far as possible it is more sane to borrow an existing keyword with a similar semantic meaning, in this case '' | ||
- | |||
- | The intention is to implement this by duplicating loop prologues to avoid the requirement for tracking variables, and keep performance on-par with pre-patch looping. | ||
- | |||
- | As an example here is the opcode dump of a pre-patch basic while loop. | ||
- | < | ||
- | $i = 3; | ||
- | while ($i--) { | ||
- | print ' | ||
- | } | ||
- | |||
- | line # * op | ||
- | --------------------------------------------------------------------------------- | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | </ | ||
- | |||
- | And a post-patch basic while loop with default block (labels added to help visualise flow) | ||
- | < | ||
- | $i = 0; | ||
- | while ($i--) { | ||
- | print ' | ||
- | } | ||
- | or { | ||
- | print ' | ||
- | } | ||
- | |||
- | # * op | ||
- | --------------------------------------------------------------------------------- | ||
- | | ||
- | cond_1: | ||
- | | ||
- | cond_2: | ||
- | | ||
- | loop: 5 > | ||
- | | ||
- | | ||
- | or: 8 > | ||
- | | ||
- | nxt_op: 10 > > RETURN | ||
- | </ | ||
- | |||
- | The key here is that '' | ||
- | |||
- | ===== Backward Incompatible Changes ===== | ||
- | Nothing forseen. | ||
- | |||
- | ===== Proposed PHP Version(s) ===== | ||
- | PHP 7 | ||
- | |||
- | ===== RFC Impact ===== | ||
- | ==== To SAPIs ==== | ||
- | All SAPIs gain the same functionality | ||
- | |||
- | ==== To Existing Extensions ==== | ||
- | No standard extensions should be affected, only the parser and compiler are modified. | ||
- | |||
- | ==== To Opcache ==== | ||
- | TODO - There may be an impact here, but any patch will review Opcache. This section needs commentary from internals. | ||
- | |||
- | ===== Open Issues ===== | ||
- | None | ||
- | |||
- | ===== Unaffected PHP Functionality ===== | ||
- | '' | ||
- | |||
- | Both require the loop to be entered to have an effect, which means the default block cannot be executed at the point these constructs are used. | ||
- | |||
- | Loops without bodies also get to have default blocks | ||
- | |||
- | ===== Future Scope ===== | ||
- | There may be an opporunity to support the python style loop+else, but this will require a new keyword to preserve dangling else backward compatibility | ||
- | |||
- | ===== Proposed Voting Choices ===== | ||
- | This is a language change and requires a 2/3 majority in favour of the feature. | ||
- | |||
- | ===== Patches and Tests ===== | ||
- | A proof of concept is being worked on by Leigh - '' | ||
- | |||
- | ===== Implementation ===== | ||
- | TODO | ||
- | |||
- | ===== References ===== | ||
- | |||
- | Original RFC: | ||
- | |||
- | [[http:// | ||
- | |||
- | Original discussions in bug tracker: | ||
- | |||
- | [[https:// | ||
- | |||
- | [[https:// | ||
- | |||
- | [[https:// | ||
- | |||
- | ===== Changelog ===== | ||
- | 2014-09-20 - Changed target version to PHP 7 | ||
- | |||
- | 2014-09-20 - Added details that templating engines emulate this behaviour | ||
- | |||
- | 2014-09-19 - v1.0 - RFC created | ||
rfc/loop_or.txt · Last modified: 2017/09/22 13:28 (external edit)