Re: [RFC] Nullsafe calls

From: Date: Wed, 10 Dec 2014 17:19:56 +0000
Subject: Re: [RFC] Nullsafe calls
References: 1  Groups: php.internals 
Request: Send a blank email to internals+get-79529@lists.php.net to get a copy of this message
> On 9 Dec 2014, at 23:07, Josh Watzman <jwatzman@fb.com> wrote: > > Hey internals! A useful feature that Hack picked up in the last few months are "nullsafe > calls", a way of propagating failure forward in a series of chained method calls to the end of > the whole computation, getting rid of a lot of the boilerplate in the middle. I think the feature > would be a good one for PHP as well, so I'm submitting this RFC to add it -- you can see the > RFC itself for a full discussion of the motivation for the feature, as well as the feature itself: > > https://wiki.php.net/rfc/nullsafe_calls Hi again, I was in favour of this, but upon further thought, I’m not sure I am. I remember I also initially liked it in Hack and then lost interest. First, how is this substantially different from catching an exception? With Nikita’s Exceptions in the Engine RFC (https://wiki.php.net/rfc/engine_exceptions_for_php7), something like this would be possible: try { return $foo->bar()->qux()->elePHPant()->dance(); } catch (EngineException $e) { return NULL; } That would essentially do the same as what you’re proposing: return $foo?->bar()?->qux()?->elePHPant()?->dance(); Are there many instances where there’d be a substantial benefit to using ?-> versus catching an exception? Second, not short-circuiting is rather unintuitive. I think most people would expect it to short-circuit. Note that ?? and isset() short-circuit, so this would be inconsistent with existing NULL-checking operators. So why, then, are you proposing that it should not short-circuit? Is there some obscure case that this makes easier? If anything, I’d expect that short-circuiting is the more useful behaviour. For example, take the following hypothetical line of code: $elePHPantParty->danceClub?->addToDanceFloor($elePHPantPool->remove()); If we have the short-circuiting behaviour, then if $elePHPantParty->danceClub is NULL, ->addToDanceFloor isn’t called and an ElePHPant isn’t removed from $elePHPantPool. On the other hand, if ->danceClub isn’t NULL, ->addToDanceFloor is called and an ElePHPant will be removed from $elePHPantPool. With the non-short-circuiting behaviour, this code would have to be longer, and you couldn’t use ?-> here. Instead, you’d have to write this: if ($elePHPantParty->danceClub !== NULL) { $elePHPantParty->danceClub->addToDanceFloor($elePHPantPool->remove()); } It is, admittedly, a hypothetical scenario, but it does demonstrate why having it not short-circuit is less useful. Are there any examples where short-circuiting is a problem? Third, as has already been mentioned, this doesn’t support ?-> for properties, which is both unintuitive (people will reasonably expect it to work) and makes it a lot less useful, because you won’t always be dealing with method calls. While $foo?->bar()?->foobar() might work, what about something like $foo?->bar?->foobar(), where one of the links in the chain is a property? This is not at all an unlikely scenario. Finally, this may encourage bad code. As someone helpfully pointed out in the reddit discussion (http://redd.it/2ot15u), this encourages breaking the Law of Demeter, i.e. that objects should only talk to their immediate friends. Usually, long chains of method calls across multiple objects are not a good idea, yet the main benefit of this RFC is to reduce the boilerplate needed for that scenario. I am only one voice in this discussion, but I personally don’t really like this RFC. Thanks! -- Andrea Faulds http://ajf.me/

« previous php.internals (#79529) next »