On Mon, Jul 13, 2020 at 5:33 PM Josh Bruce <j...@joshbruce.dev> wrote:
> > >> Latest version as we zero in on what this is really about: >> https://bit.ly/php-0002 <https://bit.ly/php-0002> >> >> I have a really hard time understanding what is actually being proposed > here. You mention the introduction of the Emptiable interface, but not how > it influences empty() or (bool) casts. There's some examples in "Usage" > that are possibly intended to illustrate this -- I suspect that a "return > true" vs "return false" mixup has made them impossible to understand though. > > Some thoughts on the general domain: > > 1. I don't like the idea of decoupling empty() and (bool). empty($x) is > currently the same as !$x (modulo notices), and changing that will make > PHP's already messy implicit type conversion matrix even messier. > > > Thanks for the feedback! Not all incorporated in the latest, due to > timing: https://bit.ly/php-0002 > > Initially this started as a desire to be able to declare an object casting > to bool (__toBool or something). After a couple rounds the relationship > between empty() and bool surfaced. The question I’m volleying there is are > they different concepts (a non-answer compared to a lie) and does it matter > given the established norm. (Sounds like you’re in the established norm > camp - I tend to lean that way as well.) > > 2. Coupling boolean casts to an "emptiness" concept seems somewhat dubious > to me. That works for container structures, but what about something like > new Bigint(0)? It would be quite odd to declare an integer "empty" to make > it evaluate to false. > > > This seems counter to the first bullet point. They already are coupled. > The result of empty() tends to be the opposite of casting bool - unless > there’s an example I’m unaware of. > Yes, they are coupled. The problem here is more that empty() is a misnomer, because it does not check emptiness, it checks falsyness. The big example is that empty("0") returns true, even though "0" is very clearly not an empty string. > > 3. I'm generally not a fan of overloadable bool casts. We have exactly one > object with an overloaded bool cast in PHP, and that's SimpleXMLElement. As > far as I know, this has only caused issues. A big reason for that is that > using "if ($foo->bar)" is a common idiom for checking "if ($foo->bar !== > null)" -- one that works very reliably, with the exception of > SimpleXMLElement. > > > I wasn’t aware of this. Thank you! I will take a look and see what > problems people are running into and how it’s implemented - at least from a > developer perspective. > > 4. I think if ($container->isEmpty()) is much clearer than if ($container) > -- why would we want people to use the latter instead? > > > Fair question. This made me raise the question in the draft and I’ll raise > it here…under what circumstances would PHP return null from new. > > $instance = new MyClass(); > > If ($instance->isEmpty()) {} > > $inner = $instance->innerObject(); > > If ($innnerObject->isEmpty()) {} > > If I implement the innerObject() method to return null - and it does - > then that call fails, because it’s null, which brings up your earlier > point, I think. > > If ($innerObject) { > // not null > > If ($innerObject->isEmpty()) { > // two-step process with null-check > > } > } > > // with the language feature > If ($innerObject) { > // I know it can give and receive messages, and is not empty > > } else { > // I know it can give and receive messages, but is empty > > } > The nullsafe operator proposal will allow you to write this as if ($innerObject?->isEmpty()) { } That is both concise, and very explicit. Just If ($innerObject) is not -- it could be intended as just a null check, or as a null or empty check, or only an empty check, under your proposal. Nikita