[RFC] Loop... or...

php.internals

Leigh

11 years ago
Hello list! This is an item that has been repeatedly requested in various forms, with no solid implementation to back it up, yet remaining quite desirable to the developer community at large. Loops with a default block, executed in the event that the loop is never entered. https://wiki.php.net/rfc/loop_or Traditionally this is requested as a loop {} else {} structure, however due to the choice of keyword this causes significant BC problems. I have written an RFC presenting this feature as loop {} or {} along with how I intend to implement it. I have consulted with several core contributors as well as normal developers, and this seems to be the most BC-complete option. A poll of local developers indicates a strong positive response supporting this feature, so please take the time to consider and discuss what is laid out in the RFC, as many of us would like this to become a permanent fixture of the language. I especially need input regarding Opcache concerns, as this is not an area of expertise for me. I will be developing the patch myself, and hope to have a full proof of concept completed by the end of this weekend. (for and while are both working, foreach currently segfaults, I am working on it) Thanks for reading. Leigh.

Rowan Collins

11 years ago
On 19/09/2014 22:56, Leigh wrote:
> Hello list! > > This is an item that has been repeatedly requested in various forms, > with no solid implementation to back it up, yet remaining quite > desirable to the developer community at large. > > Loops with a default block, executed in the event that the loop is > never entered. > > https://wiki.php.net/rfc/loop_or
Interesting! Not sure I've ever felt the need for it, but it seems like it could be quite handy to have in the toolbox, as it were. It's worth noting that both Smarty and Twig implement a similar mechanism in their respective foreach loop syntax. Smarty spells it {foreachelse} http://www.smarty.net/docs/en/language.function.foreach.tpl Twig spells it {% else %} http://twig.sensiolabs.org/doc/tags/for.html#the-else-clause
-- Rowan Collins [IMSoP]

Leigh

11 years ago
On 19 September 2014 23:08, Rowan Collins <rowan.collins@gmail.com> wrote:
> It's worth noting that both Smarty and Twig implement a similar mechanism in > their respective foreach loop syntax. > > Smarty spells it {foreachelse} > http://www.smarty.net/docs/en/language.function.foreach.tpl > > Twig spells it {% else %} > http://twig.sensiolabs.org/doc/tags/for.html#the-else-clause > > -- > Rowan Collins
Yep, I thought I included a paragraph about templating engines emulating this, but I probably did a copy/edit/paste fail --> on the todo list for next edit.

Andrew Faulds

11 years ago
On 19 Sep 2014, at 22:56, Leigh <leight@gmail.com> wrote:
> Loops with a default block, executed in the event that the loop is > never entered. > > https://wiki.php.net/rfc/loop_or
While this might be useful, I’d prefer we copy Python’s else behaviour, where a block of code is executed when break is never used. This feature makes code that does, for example, a linear search nicer to read.
-- Andrea Faulds http://ajf.me/

Leigh

11 years ago
On 19 September 2014 23:47, Andrea Faulds <ajf@ajf.me> wrote:
> > While this might be useful, I’d prefer we copy Python’s else behaviour, where a block of code is executed when break is never used. This feature makes code that does, for example, a linear search nicer to read. > > -- > Andrea Faulds > http://ajf.me/ >
Hey Andrea, The RFC describes in particular why the else keyword is a bad choice, and opens up the possibility of Python-style "else" in a future RFC. Please consider this feature request as independent of any python-related functionality. I understand the desire for something python-like, however it certainly doesn't fall under the "or" keyword. If anything we could probably get away with it under "and", or introduce a new keyword of "then", but really, that is a subject for a different thread altogether. This thread is about the "loop not entered" syntax. Lets stick to that for now, and I'm more than happy to create a thread for the other scenario later on, and we can discuss the python style there instead. Cheers, Leigh.

Andrew Faulds

11 years ago
On 20 Sep 2014, at 00:10, Leigh <leight@gmail.com> wrote:
> I understand the desire for something python-like, however it > certainly doesn't fall under the "or" keyword.
Why not? Python uses “else”, and before creating this RFC you initially wanted to use “else”.
> If anything we could > probably get away with it under "and", or introduce a new keyword of > "then", but really, that is a subject for a different thread > altogether. This thread is about the "loop not entered" syntax. Lets > stick to that for now, and I'm more than happy to create a thread for > the other scenario later on, and we can discuss the python style there > instead.
I’m bringing it up because I think we’re only going to end up with one feature or the other, and I think Python’s behaviour is more useful.
-- Andrea Faulds http://ajf.me/

Leigh

11 years ago
On 20 September 2014 00:15, Andrea Faulds <ajf@ajf.me> wrote:
> > Why not? Python uses “else”, and before creating this RFC you initially wanted to use “else”.
Then I realised it was folly. Documented in the RFC why "else" is a bad choice.
> I’m bringing it up because I think we’re only going to end up with one feature or the other, and I think Python’s behaviour is more useful. >
We can absolutely have both, but it's not for this RFC.

Rowan Collins

11 years ago
On 19/09/2014 23:47, Andrea Faulds wrote:
> On 19 Sep 2014, at 22:56, Leigh <leight@gmail.com> wrote: > >> Loops with a default block, executed in the event that the loop is >> never entered. >> >> https://wiki.php.net/rfc/loop_or > While this might be useful, I’d prefer we copy Python’s else behaviour, where a block of code is executed when break is never used. This feature makes code that does, for example, a linear search nicer to read.
I saw that discussed in the RFC, and couldn't understand why it would work that way. I think it's just the word "else" that's throwing me - I can see that a block distinguishing between "got to the end" and "hit a break statement" would be useful, but tend to think of "break" as being the exceptional case, so having that *skip* an "else" block feels really backwards to me. It seems like there are actually quite a number of special blocks you *could* define, such as: a) When the body is executed zero times (proposed "or" block) b) When the body is executed exactly once (in a do...while loop, as mentioned in the RFC) c) After every iteration of the loop, even if the iteration was ended early (Perl's "continue" block [1], where "next" is equivalent to PHP's "continue") d) After every iteration of the loop, *only* if the iteration was ended early (would have a similar relationship to (c) as "catch" does to "finally") e) After the end of the loop, if "break" was not used (Python's "else" block [2]) f) After the end of the loop, if "break" WAS used Most of these can be reduced to conditional jumps: (c) can be implemented by replacing "continue" with "goto continue_block" [3], and (d) by skipping that block during normal loop execution [4]; (e) can be done using a goto which jumps over the relevant block [5], and (f) by jumping into a skipped block [6] (a) and (b), on the other hand, I can't think of a way of implementing in existing PHP code without a state variable to track whether (or how often) the loop body was reached. I certainly don't see (a) and (f) as being at all mutually exclusive. Now I'm going to go to bed before the raptors catch up with me from all those gotos... [1] http://perldoc.perl.org/functions/continue.html [2] https://docs.python.org/2/tutorial/controlflow.html#break-and-continue-statements-and-else-clauses-on-loops [3] http://3v4l.org/TnW12 [4] http://3v4l.org/HbSei [5] http://3v4l.org/T4Boh [6] http://3v4l.org/CmO9C
-- Rowan Collins [IMSoP]

Rowan Collins

11 years ago
On 20/09/2014 01:02, Rowan Collins wrote:
> I certainly don't see (a) and (f) as being at all mutually exclusive.
Sorry, that was meant to say (a) and (e). Or, in plain English, I don't see why we couldn't have both Smarty-style "if the loop executed zero times" and Python-style "if the break keyword wasn't used to end the loop early", as long as we can think of keywords for them.
-- Rowan Collins [IMSoP]

Leigh

11 years ago
On 20 September 2014 01:02, Rowan Collins <rowan.collins@gmail.com> wrote:
> > It seems like there are actually quite a number of special blocks you > *could* define, such as: > > a) When the body is executed zero times (proposed "or" block) > b) When the body is executed exactly once (in a do...while loop, as > mentioned in the RFC) > c) After every iteration of the loop, even if the iteration was ended early > (Perl's "continue" block [1], where "next" is equivalent to PHP's > "continue") > d) After every iteration of the loop, *only* if the iteration was ended > early (would have a similar relationship to (c) as "catch" does to > "finally") > e) After the end of the loop, if "break" was not used (Python's "else" block > [2]) > f) After the end of the loop, if "break" WAS used >
Some or all of these can be implemented (in other RFCs). However in order to avoid specifying every permutation in the grammar it would require converting loop structures that currently have a defined number of children, into list structures ("if" behaves like this, with multiple optional "elseifs" and an optional "else"). Obviously the complexity increases with each new type of block but I think the type being addressed in this RFC, and the python-style type can live side-by-side pretty happily. So, lets deal with this one first, and then I will work on a python-style one afterwards (promise)

Rowan Collins

11 years ago
On 20 September 2014 15:43:46 GMT+01:00, Leigh <leight@gmail.com> wrote:
>On 20 September 2014 01:02, Rowan Collins <rowan.collins@gmail.com> >wrote: >> >> It seems like there are actually quite a number of special blocks you >> *could* define > >Some or all of these can be implemented (in other RFCs). > >However in order to avoid specifying every permutation in the grammar >it would require converting loop structures that currently have a >defined number of children, into list structures ("if" behaves like >this, with multiple optional "elseifs" and an optional "else").
Yeah, I absolutely didn't mean that all of these were equally essential, I was just brainstorming some of the possible permutations. I guess the only way to avoid running out of keywords would be to have a generic clause like "on(x)", but that's probably just asking for trouble... foreach ( $x as $y ) { ... } on ( break ) { ... } on ( nobreak ) { ... } on ( continue ) { ... } on ( nocontinue ) { ... } on ( noloop ) { ... } on ( loopcount == 1 ) { ... } Yeah, let's not do that! :p
-- Rowan Collins [IMSoP]

Leigh

11 years ago
Updated RFC to include information about templating engines often emulating this behaviour for ease-of-use. Changed target version to be specifically PHP 7, so that it's clear that changes target the AST based compiler. (If there's ever a 5.next, we can consider that at the time)

Sara Golemon

11 years ago
> On Sep 19, 2014, at 14:56, Leigh <leight@gmail.com> wrote: > https://wiki.php.net/rfc/loop_or >
I like the general idea, but rather than explicitly focusing on the 'or' keyword, how about just giving all loop constructs (do/while/for/foreach) a return value? I'd suggest an integer return value indicating the number of times the loop executed. This accomodates your use case since foreach(...) {} or { defaultblock } still works, while also allowing for others: e.g.: $ranTwice = foreach(...) {} == 2; It does introduce a temp var, but OpCache+ can trivially optimize that out when it isn't used. -Sara

Leigh

11 years ago
On 20 September 2014 20:47, Sara Golemon <php@golemon.com> wrote:
> > I like the general idea, but rather than explicitly focusing on the 'or' keyword, how about just giving all loop constructs (do/while/for/foreach) a return value? I'd suggest an integer return value indicating the number of times the loop executed. > > This accomodates your use case since foreach(...) {} or { defaultblock } still works, while also allowing for others: > > e.g.: > $ranTwice = foreach(...) {} == 2; > > It does introduce a temp var, but OpCache+ can trivially optimize that out when it isn't used. > > -Sara
Sorry @Sara - didn't reply to all the first time. ---- mind === blown This would open up a huge amount of other functionality I'd never dreamed of (some of which is quite scary!) for($i = for(...) {}; $i < ...) {} I'm really not sure I understand the full implication of this though. This would mean changing loop constructs from statements to expressions. I wonder how difficult that will actually be, and what other problems it would cause (I obviously haven't played with this idea yet). It would also mean having to make { default block } into an expression... with a return value (to be allowed on either side of the boolean or) Lots to think about here, if it's at all viable this will need it's own separate RFC, it's a much more invasive change, but definitely a great idea.

Leigh

11 years ago
On 20 September 2014 23:06, Leigh <leight@gmail.com> wrote:
> > Lots to think about here, if it's at all viable this will need it's > own separate RFC, it's a much more invasive change, but definitely a > great idea.
NikiC and Bob have convinced me to carry on with the original proposal, and bring up Saras ideas as another RFC afterwards, so the full impact of converting loops to expressions can be judged on its own merits. It is BC with this RFC, so no problem there.

Sara Golemon

11 years ago
On Sat, Sep 20, 2014 at 5:16 PM, Leigh <leight@gmail.com> wrote:
> On 20 September 2014 23:06, Leigh <leight@gmail.com> wrote: >> >> Lots to think about here, if it's at all viable this will need it's >> own separate RFC, it's a much more invasive change, but definitely a >> great idea. > > NikiC and Bob have convinced me to carry on with the original > proposal, and bring up Saras ideas as another RFC afterwards, so the > full impact of converting loops to expressions can be judged on its > own merits. It is BC with this RFC, so no problem there. >
Agreed. If we do find a nice way to make loops into expressions and make default blocks work with that, then the explicit LOOP/OR syntax can vanish and work implicitly with the expression approach. -Sara

Leigh

11 years ago
Completed my proof of concept patch: https://github.com/lt/php-src/compare/loop-or This gives for, foreach, and while loops an additional "or {}" block

Christian Stoller

11 years ago
From: Leigh [mailto:leight@gmail.com] Sent: Friday, September 19, 2014 11:57 PM
> > Traditionally this is requested as a loop {} else {} structure, > however due to the choice of keyword this causes significant BC > problems. > > I have written an RFC presenting this feature as loop {} or {} along > with how I intend to implement it. I have consulted with several core > contributors as well as normal developers, and this seems to be the > most BC-complete option.
I like this proposal as I am using this feature in Twig very often. But I would really prefer using "else" instead of "or", because it is already common in the mentioned projects. Maybe you could reconsider if it is really not possible to use "else". What about making the brackets for the loop block obligatory for using this feature? Christian

Leigh

11 years ago
On 22 September 2014 08:17, Christian Stoller <stoller@leonex.de> wrote:
> > I like this proposal as I am using this feature in Twig very often. > But I would really prefer using "else" instead of "or", because it > is already common in the mentioned projects. > Maybe you could reconsider if it is really not possible to use "else".
It's _really_ not possible to use "else" without a huge BC break in one form or another, something I'm trying to avoid at all costs.
> What about making the brackets for the loop block obligatory for > using this feature?
Unfortunately that wouldn't help, we'd have to enforce braces on everything (if/else/elseif/while/for/etc) to make it possible to hang an "else" on the bottom of a loop, again a pretty big BC break. I have actually discussed "braces everywhere" with several internals devs, and the response has been pretty much unanimous: We'd like it, but it will never pass the vote. It would be trivial to provide a migration script though. Feel free to test the water with this idea ;)

Laruence

11 years ago
Hey: On Sat, Sep 20, 2014 at 5:56 AM, Leigh <leight@gmail.com> wrote:
> Hello list! > > This is an item that has been repeatedly requested in various forms, > with no solid implementation to back it up, yet remaining quite > desirable to the developer community at large. > > Loops with a default block, executed in the event that the loop is > never entered. > > https://wiki.php.net/rfc/loop_or > > Traditionally this is requested as a loop {} else {} structure, > however due to the choice of keyword this causes significant BC > problems. > > I have written an RFC presenting this feature as loop {} or {} along > with how I intend to implement it. I have consulted with several core > contributors as well as normal developers, and this seems to be the > most BC-complete option. > > A poll of local developers indicates a strong positive response > supporting this feature, so please take the time to consider and > discuss what is laid out in the RFC, as many of us would like this to > become a permanent fixture of the language. > > I especially need input regarding Opcache concerns, as this is not an > area of expertise for me. > > I will be developing the patch myself, and hope to have a full proof > of concept completed by the end of this weekend. (for and while are > both working, foreach currently segfaults, I am working on it) > > Thanks for reading. > > Leigh.
Maybe I am too conservative. I don't like this idea......... :< And I DO THINK, we should try to stop brings lots of new things into PHP7. I am worring whether it can be release in the next year.... thanks
> > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php >
-- Xinchen Hui @Laruence http://www.laruence.com/

Leigh

11 years ago
On 22 September 2014 08:49, Xinchen Hui <laruence@php.net> wrote:
> > Maybe I am too conservative. I don't like this idea......... :< > > And I DO THINK, we should try to stop brings lots of new things into PHP7. > > I am worring whether it can be release in the next year....
Can you give some more details on why you don't like the idea? Is there anything I can do to the proposal to make it more acceptable? I don't think you should worry this postponing the release. I plan to do all of the work for this, it shouldn't cost you any time at all except a few lines about your opinion. I'm not comfortable deep diving into the core, so it's not like I can help make the release go faster if I stop work on this.

Leigh

11 years ago
If there are no outstanding issues raised by tonight (UTC), I will open this RFC up to a vote. I'd like to remind everyone that we're discussing and voting on the concept here rather than the implementation. I'm personally not happy with "or", but if there is enough support during voting then I am happy to actively work on finding the best solution (and maybe a second round of voting when we have all of the possibilities lined up), if there is no support then I wont spend time on it. Thanks, Leigh.

Andrew Faulds

11 years ago
On 3 Oct 2014, at 08:39, Leigh <leight@gmail.com> wrote:
> If there are no outstanding issues raised by tonight (UTC), I will > open this RFC up to a vote. > > I'd like to remind everyone that we're discussing and voting on the > concept here rather than the implementation. I'm personally not happy > with "or", but if there is enough support during voting then I am > happy to actively work on finding the best solution (and maybe a > second round of voting when we have all of the possibilities lined > up), if there is no support then I wont spend time on it.
Huh, why is the keyword choice not part of the vote? So, if people vote for it with ‘or’, you could change it to something completely different? I don’t think that’s normal procedure.
-- Andrea Faulds http://ajf.me/

Leigh

11 years ago
On 3 October 2014 20:04, Andrea Faulds <ajf@ajf.me> wrote:
> > Huh, why is the keyword choice not part of the vote? So, if people vote for it with ‘or’, you could change it to something completely different? > > I don’t think that’s normal procedure.
Because there currently isn't a choice.