Suggested change: change priority of new and ->

  101811
February 8, 2018 18:38 mcmuffinmcguffin@gmail.com (Mcmuffin Mcguffin)
Hi,

It's a common idiom in object-oriented languages to create an object and
then immediately call a method on it, such as (in C# or Java):

new DateTime ().ToString ()

However, PHP grammar does not work this way. You have to put an additional
round of parentheses around new clause, such as:

(new DateTime ())->format ('Y-m-d')

This is rather clunky for such a common scenario (you usually have to walk
all the way back to the beginning of the expression to fix it). I have a
pattern of using static factories in place of constructor just to avoid
extra parentheses. Besides, the issue is relatively easy to fix. I've done
and tested a change for grammar in this area. It's a slight adjustment to
definition of dereferencable:

dereferencable:
> variable { $$ = $1; } > | '(' expr ')' { $$ = $2; } > * | new_expr { $$ = $1; }* > | dereferencable_scalar { $$ = $1; } > ; >
There was a problem with shift/reduces though. PHP has a level of complexity in new expression which other languages don't. It's variable class instantiation, such as: new $class (arguments) Expressions in place of $class can be rather complex, though I don't think they really need to be. For example, such stuff is allowed: new $var[0]->prop (arguments) — which seems redundant and confusing. My fix to the problem was to force parentheses around complex expressions such as above: new ($var[0]->prop) (arguments) — while keeping simple cases of "new $class (arguments)" without change. Yes, this moves parentheses from one place to another (and occasionally breaks the old code) but frequency wise I think it's an improvement. What do you think? Jaroslav Wegner
  101813
February 8, 2018 22:35 hkdobrev@gmail.com (Haralan Dobrev)
I really like the proposal and it's definitely improving more common modern
use cases.

However, I understand why the precedence is like that now in PHP to begin
with and so I think this should target PHP 8.

This change would be a bit similar to other weird use cases of variables
which were changed with PHP 7.

Best,
Harry

On Thu, 8 Feb 2018 at 20:45 Mcmuffin Mcguffin <mcmuffinmcguffin@gmail.com>
wrote:

> Hi, > > It's a common idiom in object-oriented languages to create an object and > then immediately call a method on it, such as (in C# or Java): > > new DateTime ().ToString () > > However, PHP grammar does not work this way. You have to put an additional > round of parentheses around new clause, such as: > > (new DateTime ())->format ('Y-m-d') > > This is rather clunky for such a common scenario (you usually have to walk > all the way back to the beginning of the expression to fix it). I have a > pattern of using static factories in place of constructor just to avoid > extra parentheses. Besides, the issue is relatively easy to fix. I've done > and tested a change for grammar in this area. It's a slight adjustment to > definition of dereferencable: > > dereferencable: > > variable { $$ = $1; } > > | '(' expr ')' { $$ = $2; } > > * | new_expr { $$ = $1; }* > > | dereferencable_scalar { $$ = $1; } > > ; > > > > There was a problem with shift/reduces though. PHP has a level of > complexity in new expression which other languages don't. It's variable > class instantiation, such as: > > new $class (arguments) > > Expressions in place of $class can be rather complex, though I don't think > they really need to be. For example, such stuff is allowed: > > new $var[0]->prop (arguments) > > — which seems redundant and confusing. My fix to the problem was to force > parentheses around complex expressions such as above: > > new ($var[0]->prop) (arguments) > > — while keeping simple cases of "new $class (arguments)" without change. > Yes, this moves parentheses from one place to another (and occasionally > breaks the old code) but frequency wise I think it's an improvement. > > What do you think? > > Jaroslav Wegner > --
Haralan Dobrev CTO @ Clippings.com https://hkdobrev.com
  101874
February 15, 2018 07:17 php@fleshgrinder.com (Fleshgrinder)
On 2/8/2018 7:38 PM, Mcmuffin Mcguffin wrote:
> What do you think? > > Jaroslav Wegner >
Thanks for the hard work to figure out what the roots of this annoyance is. This could land in the next PHP version, considering that many other breaking changes were also allowed in the past, given the following prerequisites: * RFC with a 2/3 majority vote * Tool to convert any possibly broken code into valid code (basically putting parenthesis around any complex `new (...)()`). * Update to https://github.com/php/php-langspec/blob/master/spec/10-expressions.md#the-new-operator -- Richard "Fleshgrinder" Fussenegger
  101875
February 15, 2018 08:32 php-lists@koalephant.com (Stephen Reay)
> On 9 Feb 2018, at 01:38, Mcmuffin Mcguffin <mcmuffinmcguffin@gmail.com> wrote: > > new $var[0]
Is that creating an instance of the class name stored in the 0th index of the array $var or is it creating an instance of the class name stored in $var and accessing the 0th index using ArrayAccess? Cheers Stephen
  101876
February 15, 2018 09:21 pslacerda@gmail.com (Pedro Lacerda)
Great contribution, very sensible even if subtile.

Is the kind of change that improve a lot but cause some trouble to people
used to the old way or when upgrading legacy codebases.

2018-02-15 5:32 GMT-03:00 Stephen Reay <php-lists@koalephant.com>:

> > > On 9 Feb 2018, at 01:38, Mcmuffin Mcguffin <mcmuffinmcguffin@gmail.com> > wrote: > > > > new $var[0] > > Is that creating an instance of the class name stored in the 0th index of > the array $var or is it creating an instance of the class name stored in > $var and accessing the 0th index using ArrayAccess? > > Cheers > > Stephen > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php > >
-- Atenciosamente, Pedro Lacerda
  101881
February 17, 2018 14:04 mcmuffinmcguffin@gmail.com (Mcmuffin Mcguffin)
> > Is that creating an instance of the class name stored in the 0th index of > the array $var or is it creating an instance of the class name stored in > $var and accessing the 0th index using ArrayAccess? >
As soon as $var gets involved, it should be prioritized above the new operator. So it's equivalent of "new ($var[0])" Jaroslav
  101882
February 17, 2018 14:39 rowan.collins@gmail.com (Rowan Collins)
On 8 February 2018 18:38:36 GMT+00:00, Mcmuffin Mcguffin <mcmuffinmcguffin@gmail.com> wrote:
>Hi, > >It's a common idiom in object-oriented languages to create an object >and >then immediately call a method on it, such as (in C# or Java): > >new DateTime ().ToString () > >However, PHP grammar does not work this way.
This would definitely be nice to have, and thanks for looking into what the necessary change would look like. I think the next challenge is to work out the different ways a dynamic class construction could happen, and which ones: a) will be unaffected by the change b) are an error now and will be allowed after c) are allowed now and will be an error after d) will work in both versions but change behaviour It's anything that falls into category (d) that is particularly problematic, as it means users will see odd bugs of they don't know about the change. The clearer we can make these examples, the better. Contrary to other responses, I think this would definitely need to happen in a major version, as it is quite clearly a breaking change. There's not much that can be done to deprecate code relying on the current rules, but we can publicise how to make code that is compatible before and after. Regards, -- Rowan Collins [IMSoP]
  101887
February 18, 2018 23:47 ajf@ajf.me (Andrea Faulds)
Hi,

I'm not… quite sure if it changes anything, but it seems worth pointing 
out PHP has two syntaxes for `new`. You can do `new DateTime()`, but you 
can /also/ do `new DateTime` without the brackets.

So, while you can't do `new DateTime()->format(DATE_ATOM)`, you *can* do 
`(new DateTime)->format(DATE_ATOM)`. This is just as short. It's only 
for constructor calls requiring arguments that we get the problem.

It also makes me wonder if it's not dereferenceable because then `new 
DateTime()` would be ambiguous: is it constructing a DateTime, or is it 
invoking a newly-constructed DateTime as a function? Be aware that 
__invoke can be implemented by a class to make its objects callable.

Thanks!

-- 
Andrea Faulds
https://ajf.me/