Raising the precedence of the new operator

php.internals

André Hänsel

5 years ago
I was wondering... PHP is the only language I know of where you have to write `(new Foo())->bar()` instead of `new Foo()->bar()`. This is particularly apparent with the builder pattern: $developer->drink((new Coffee())->withCream()->withSugar()); $logger->log((new LogMessage())->withMessage('Coffee was drunk')); Since `new Foo()->bar()` cannot (and probably should not) be used to "dynamically instantiate a new thing of the class name returned by function Foo()", it seems like it would be no problem to change the precedence rules so that `new Foo()->bar()` means "instantiate a new Foo and call bar() on it". It's currently a syntax error, so allowing it would be automatically compatible. Has this ever been discussed before?

Ben Ramsey

5 years ago
> On Apr 5, 2021, at 11:40, André Hänsel <andre@webkr.de> wrote: > > I was wondering... PHP is the only language I know of where you have to > write `(new Foo())->bar()` instead of > `new Foo()->bar()`. This is particularly apparent with the builder pattern: > > $developer->drink((new Coffee())->withCream()->withSugar()); > $logger->log((new LogMessage())->withMessage('Coffee was drunk')); > > Since `new Foo()->bar()` cannot (and probably should not) be used to > "dynamically instantiate a new thing of the class > name returned by function Foo()", it seems like it would be no problem to > change the precedence rules so that > `new Foo()->bar()` means "instantiate a new Foo and call bar() on it". > > It's currently a syntax error, so allowing it would be automatically > compatible. > > Has this ever been discussed before?
Mike Schinkel and I recently discussed this off-list. Mike, now’s your time to chime in with your ideas on this. :-) My $0.02 is that this is unnecessary, but I can see how others might want it to avoid parenthesis soup. Cheers, Ben

Mike Schinkel

5 years ago
> On Apr 5, 2021, at 12:47 PM, Ben Ramsey <ben@benramsey.com> wrote: > >> On Apr 5, 2021, at 11:40, André Hänsel <andre@webkr.de> wrote: >> >> I was wondering... PHP is the only language I know of where you have to >> write `(new Foo())->bar()` instead of >> `new Foo()->bar()`. This is particularly apparent with the builder pattern: >> >> $developer->drink((new Coffee())->withCream()->withSugar()); >> $logger->log((new LogMessage())->withMessage('Coffee was drunk')); >> >> Since `new Foo()->bar()` cannot (and probably should not) be used to >> "dynamically instantiate a new thing of the class >> name returned by function Foo()", it seems like it would be no problem to >> change the precedence rules so that >> `new Foo()->bar()` means "instantiate a new Foo and call bar() on it". >> >> It's currently a syntax error, so allowing it would be automatically >> compatible. >> >> Has this ever been discussed before? > > > Mike Schinkel and I recently discussed this off-list. Mike, now’s your > time to chime in with your ideas on this. :-)
Thanks for the invite. I had asked Ben what he thought about allowing the following syntax as a synonym for `new Foo()`: Foo::new() That would be backward compatible because you currently cannot have a method named `new()`.
> My $0.02 is that this is unnecessary, but I can see how others might > want it to avoid parenthesis soup.
Yes, off list Ben said he did not see the need for it, so I did not bring it up on the list. But now since he has invited me to... :-) If we had such syntax then that would also Andre and others to use (and reduce the necessity of needing so many parens: Foo::new()->bar() Thoughts? -Mike

Claude Pache

5 years ago
> Le 5 avr. 2021 à 19:42, Mike Schinkel <mike@newclarity.net> a écrit : > > Foo::new() > > That would be backward compatible because you currently cannot have a method named `new()`.
Really? The following compiles without hiccup for me: https://3v4l.org/Vb5Sj —Claude

Mike Schinkel

5 years ago
> On Apr 5, 2021, at 1:51 PM, Claude Pache <claude.pache@gmail.com> wrote: > >> Le 5 avr. 2021 à 19:42, Mike Schinkel <mike@newclarity.net> a écrit : >> >> Foo::new() >> >> That would be backward compatible because you currently cannot have a method named `new()`. > > Really? The following compiles without hiccup for me: https://3v4l.org/Vb5Sj <https://3v4l.org/Vb5Sj>
Ah. I must have been remembering the failures from the 5.x days and not tried it since. Well in that case, the solution to André request could be handled in userland. -Mike P.S. Too bad it works in 7.x and 8.x as that means it can never be added into PHP w/o BC breaks. :-(

André Hänsel

5 years ago
Mike Schinkel wrote:
> I had asked Ben what he thought about allowing the following syntax as a synonym for `new Foo()`: > > Foo::new()
This can already be done in application code, having the language add a synonym is IMO unnecessary magic and breaks the principle of the least surprise. The solution proposed in https://bugs.php.net/bug.php?id=70549 however is very similar to what I'm asking. Note that in that bug entry the solution was based on the premise that `$obj = new $foo->bar();` was valid code, which it isn't. (https://3v4l.org/lpN1T)

Rowan Collins

5 years ago
On 05/04/2021 20:51, André Hänsel wrote:
> Note that in that bug entry the solution was based on the premise that `$obj = new $foo->bar();` was valid code, which > it isn't. (https://3v4l.org/lpN1T)
Looking at the error message, that code parsed as valid, but failed at run-time, because it was looking for a property $bar, not a method bar(). Working version: https://3v4l.org/S9gLf It's equivalent to: $className = $foo->bar; $obj = new $className(); I think this means that just changing the operator precedence would be a compatibility break, and we would need to allow a more restricted version, as discussed on that feature request. Regards,
-- Rowan Tommins [IMSoP]

André Hänsel

5 years ago
Rowan Tommins wrote:
> it was looking for a property $bar, not a method bar(). Working version: https://3v4l.org/S9gLf
Oh, right.
> we would need to allow a more restricted version, as discussed on that feature request.
Yeah, that would be great. I think it would already cover the by far most common use case.

Marco Pivetta

5 years ago
On Mon, Apr 5, 2021, 19:42 Mike Schinkel <mike@newclarity.net> wrote:
> > > On Apr 5, 2021, at 12:47 PM, Ben Ramsey <ben@benramsey.com> wrote: > > > >> On Apr 5, 2021, at 11:40, André Hänsel <andre@webkr.de> wrote: > >> > >> I was wondering... PHP is the only language I know of where you have to > >> write `(new Foo())->bar()` instead of > >> `new Foo()->bar()`. This is particularly apparent with the builder > pattern: > >> > >> $developer->drink((new Coffee())->withCream()->withSugar()); > >> $logger->log((new LogMessage())->withMessage('Coffee was drunk')); > >> > >> Since `new Foo()->bar()` cannot (and probably should not) be used to > >> "dynamically instantiate a new thing of the class > >> name returned by function Foo()", it seems like it would be no problem > to > >> change the precedence rules so that > >> `new Foo()->bar()` means "instantiate a new Foo and call bar() on it". > >> > >> It's currently a syntax error, so allowing it would be automatically > >> compatible. > >> > >> Has this ever been discussed before? > > > > > > Mike Schinkel and I recently discussed this off-list. Mike, now’s your > > time to chime in with your ideas on this. :-) > > Thanks for the invite. > > I had asked Ben what he thought about allowing the following syntax as a > synonym for `new Foo()`: > > Foo::new() > > That would be backward compatible because you currently cannot have a > method named `new()`. >
I have static ctors named `new` in multiple codebases: https://3v4l.org/FudWpk

Marco Pivetta

5 years ago
On Mon, Apr 5, 2021, 22:51 Marco Pivetta <ocramius@gmail.com> wrote:
> > > On Mon, Apr 5, 2021, 19:42 Mike Schinkel <mike@newclarity.net> wrote: > >> >> > On Apr 5, 2021, at 12:47 PM, Ben Ramsey <ben@benramsey.com> wrote: >> > >> >> On Apr 5, 2021, at 11:40, André Hänsel <andre@webkr.de> wrote: >> >> >> >> I was wondering... PHP is the only language I know of where you have to >> >> write `(new Foo())->bar()` instead of >> >> `new Foo()->bar()`. This is particularly apparent with the builder >> pattern: >> >> >> >> $developer->drink((new Coffee())->withCream()->withSugar()); >> >> $logger->log((new LogMessage())->withMessage('Coffee was drunk')); >> >> >> >> Since `new Foo()->bar()` cannot (and probably should not) be used to >> >> "dynamically instantiate a new thing of the class >> >> name returned by function Foo()", it seems like it would be no problem >> to >> >> change the precedence rules so that >> >> `new Foo()->bar()` means "instantiate a new Foo and call bar() on it". >> >> >> >> It's currently a syntax error, so allowing it would be automatically >> >> compatible. >> >> >> >> Has this ever been discussed before? >> > >> > >> > Mike Schinkel and I recently discussed this off-list. Mike, now’s your >> > time to chime in with your ideas on this. :-) >> >> Thanks for the invite. >> >> I had asked Ben what he thought about allowing the following syntax as a >> synonym for `new Foo()`: >> >> Foo::new() >> >> That would be backward compatible because you currently cannot have a >> method named `new()`. >> > > I have static ctors named `new` in multiple codebases: > https://3v4l.org/FudWpk >
> Sorry, mails synchronized now, and I did not realize that you already had
a waterfall of responses related to this :|

Christoph Becker

5 years ago
On 05.04.2021 at 18:40, André Hänsel wrote:
> I was wondering... PHP is the only language I know of where you have to > write `(new Foo())->bar()` instead of > `new Foo()->bar()`. This is particularly apparent with the builder pattern: > > $developer->drink((new Coffee())->withCream()->withSugar()); > $logger->log((new LogMessage())->withMessage('Coffee was drunk')); > > Since `new Foo()->bar()` cannot (and probably should not) be used to > "dynamically instantiate a new thing of the class > name returned by function Foo()", it seems like it would be no problem to > change the precedence rules so that > `new Foo()->bar()` means "instantiate a new Foo and call bar() on it". > > It's currently a syntax error, so allowing it would be automatically > compatible. > > Has this ever been discussed before?
See <https://bugs.php.net/bug.php?id=70549>.
-- Christoph M. Becker

Ben Ramsey

5 years ago
> On Apr 5, 2021, at 12:12, Christoph M. Becker <cmbecker69@gmx.de> wrote: > > On 05.04.2021 at 18:40, André Hänsel wrote: > >> I was wondering... PHP is the only language I know of where you have to >> write `(new Foo())->bar()` instead of >> `new Foo()->bar()`. This is particularly apparent with the builder pattern: >> >> $developer->drink((new Coffee())->withCream()->withSugar()); >> $logger->log((new LogMessage())->withMessage('Coffee was drunk')); >> >> Since `new Foo()->bar()` cannot (and probably should not) be used to >> "dynamically instantiate a new thing of the class >> name returned by function Foo()", it seems like it would be no problem to >> change the precedence rules so that >> `new Foo()->bar()` means "instantiate a new Foo and call bar() on it". >> >> It's currently a syntax error, so allowing it would be automatically >> compatible. >> >> Has this ever been discussed before? > > See <https://bugs.php.net/bug.php?id=70549>.
The last comment on that issue reads:
> @Nikic > Good news. I'll prepare RFC for 7.1.
Was there an RFC for it? I can’t find one. Cheers, Ben

Christoph Becker

5 years ago
On 05.04.2021 at 19:19, Ben Ramsey wrote:
>> On Apr 5, 2021, at 12:12, Christoph M. Becker <cmbecker69@gmx.de> wrote: >> >> On 05.04.2021 at 18:40, André Hänsel wrote: >> >>> I was wondering... PHP is the only language I know of where you have to >>> write `(new Foo())->bar()` instead of >>> `new Foo()->bar()`. This is particularly apparent with the builder pattern: >>> >>> $developer->drink((new Coffee())->withCream()->withSugar()); >>> $logger->log((new LogMessage())->withMessage('Coffee was drunk')); >>> >>> Since `new Foo()->bar()` cannot (and probably should not) be used to >>> "dynamically instantiate a new thing of the class >>> name returned by function Foo()", it seems like it would be no problem to >>> change the precedence rules so that >>> `new Foo()->bar()` means "instantiate a new Foo and call bar() on it". >>> >>> It's currently a syntax error, so allowing it would be automatically >>> compatible. >>> >>> Has this ever been discussed before? >> >> See <https://bugs.php.net/bug.php?id=70549>. > > The last comment on that issue reads: > >> @Nikic >> Good news. I'll prepare RFC for 7.1. > > Was there an RFC for it? I can’t find one.
I don't think there ever was an RFC for this.
-- Christoph M. Becker

Stas Malyshev

5 years ago
Hi! On 4/5/21 9:40 AM, André Hänsel wrote:
> I was wondering... PHP is the only language I know of where you have to > write `(new Foo())->bar()` instead of > `new Foo()->bar()`. This is particularly apparent with the builder pattern:
Enabling something that is syntax error now sounds pretty innocent, but I wonder if messing with precedence would cause some deeper consequences in different expressions. We need to be careful here given how much code (and how much weird code) there exists in PHP. If we can guarantee that we can enable this construct without causing any side effects, then it's fine I think.
-- Stas Malyshev smalyshev@gmail.com