# [CONCEPT][DISCUSSION] Allow objects to declare emptiness and by extension truthiness

- Thread: https://externals.io/message/110967
- Original archive: https://news-web.php.net/php.internals/110967
- Started by Josh Bruce on 2020-07-12T17:48:35+00:00
- Messages: 9
- RFC: Objects can be declared falsifiable (Inactive) — https://externals.io/rfc/objects-can-be-falsifiable.md
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · RFCs at https://externals.io/rfc.md · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #110967 — Josh Bruce — 2020-07-12T17:48:35+00:00

URL: https://externals.io/message/110967#110967

Latest version as we zero in on what this is really about: https://bit.ly/php-0002 <https://bit.ly/php-0002>

Other threads:

1. https://externals.io/message/110879 <https://externals.io/message/110879>
2. https://externals.io/message/110881 <https://externals.io/message/110881>

Thanks for all the feedback so far! Definitely feels like progress.

Cheers,
Josh

---

## #110969 — Larry Garfield — 2020-07-12T23:46:54+00:00

URL: https://externals.io/message/110967#110969 · In reply to: #110967

> Latest version as we zero in on what this is really about: 
> https://bit.ly/php-0002 <https://bit.ly/php-0002>
> 
> Other threads:
> 
> 1. https://externals.io/message/110879 <https://externals.io/message/110879>
> 2. https://externals.io/message/110881 <https://externals.io/message/110881>
> 
> Thanks for all the feedback so far! Definitely feels like progress.
> 
> Cheers,
> Josh

Hi Josh.  This is a big improvement, and I think focuses on the useful value-add a lot better.  Basing it off of Countable rather than Stringable is, I think, a safer overall approach, especially as it then gets us toBool as effectively a side-effect.

There's 2 additional improvements I'd suggest:

1) The 2 places that you have lists of "this thing produces true/false" could likely stand to be turned into tables to make it clearer, especially when demonstrating that isEmpty() and __toBool() are effectively opposites of each other so we get a 2-for-1 deal.

2) Include some less-random examples of real "empty" objects.

Also, please be warned that the PHP wiki doesn't use Markdown.  It uses some wonky proprietary ancient mess instead.  Now that you have Wiki access you should probably start using the PHP Wiki instead of Github so that you don't have to convert a mess of nice formatting from Markdown to PHPWiki-down.

I like this idea and wish I had the skillz to help implement it. :-)

--Larry Garfield

---

## #110970 — Nikita Popov — 2020-07-13T10:19:28+00:00

URL: https://externals.io/message/110967#110970 · In reply to: #110967

> Latest version as we zero in on what this is really about:
> https://bit.ly/php-0002 <https://bit.ly/php-0002>
>
> Other threads:
>
> 1. https://externals.io/message/110879 <
> https://externals.io/message/110879>
> 2. https://externals.io/message/110881 <
> https://externals.io/message/110881>
>
> Thanks for all the feedback so far! Definitely feels like progress.


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.

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.

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.

4. I think if ($container->isEmpty()) is much clearer than if ($container)
-- why would we want people to use the latter instead?

Regards,
Nikita

---

## #110974 — Josh Bruce — 2020-07-13T15:18:00+00:00

URL: https://externals.io/message/110967#110974 · In reply to: #110969

> > […]
> 1) The 2 places that you have lists of "this thing produces true/false" could likely stand to be turned into tables to make it clearer, especially when demonstrating that isEmpty() and __toBool() are effectively opposites of each other so we get a 2-for-1 deal.

I appreciate this idea - done.

> 
> 2) Include some less-random examples of real "empty" objects.
> 

I’m having difficulty with this, to be honest. I think there are two reasons for this:

1. I avoid null to the point of going out of my way to make it not happen - including implementing “isEmpty” - simultaneously I’m having a hard time, which could mean it’s a solution looking for a problem (was thinking about a file cabinet with drawers that would accept folders).

2. I have a very specific use case where this would solve a problem for me. It mainly revolves around the ability in PHP to make an object in such a way that it “feels” like an array - and “feels” like a string - and can become an integer - but there’s no way to make the object feel like and be interacted with like a bool. I don’t want my use case to be the only reason a change like this is introduced to PHP - I want to make sure “it’s not just me” - you know??

Re the wiki: I can edit pages now, it doesn’t look like I can create them. There’s another thread I’ve been watching and I think I need more karma to make that a thing. I will continue working on this and if it generates enough pull then maybe I’ll be let in - I’ll also contribute where I can to start earning karma.

Updated: https://bit.ly/php-0002 <https://bit.ly/php-0002>

Cheers,
Josh

---

## #110975 — Josh Bruce — 2020-07-13T15:33:39+00:00

URL: https://externals.io/message/110967#110975 · In reply to: #110970

> 
> Latest version as we zero in on what this is really about: https://bit.ly/php-0002 <https://bit.ly/php-0002> <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.

> 
> 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

}

I remember hearing what sounds like hyperbole but it said something like 40% of code written is guarding against null. I can totally see that being real so didn’t look much further into it. If we can guarantee that an object is that type of object - just happens to be empty, maybe we reduce or remove the need null-checks??

Cheers,
Josh

---

## #110976 — Nikita Popov — 2020-07-13T16:50:30+00:00

URL: https://externals.io/message/110967#110976 · In reply to: #110975

>
>
> > […]
> 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

---

## #110977 — Christoph M. Becker — 2020-07-13T17:14:16+00:00

URL: https://externals.io/message/110967#110977 · In reply to: #110974

> Re the wiki: I can edit pages now, it doesn’t look like I can create them. There’s another thread I’ve been watching and I think I need more karma to make that a thing. I will continue working on this and if it generates enough pull then maybe I’ll be let in - I’ll also contribute where I can to start earning karma.

You have RFC karma now.

--
Christoph M. Becker

---

## #111004 — Josh Bruce — 2020-07-14T18:24:20+00:00

URL: https://externals.io/message/110967#111004 · In reply to: #110977

> 
> 
> 
> 
> > […]
> 
> You have RFC karma now.

Christoph: Wow, okay. Thank you!

All: I’ve decided to go ahead and do one more round using GitHub (big changes - kind of a synthesis of directions so far based on feedback).

Then I’ll spend time transferring it to a draft (or discussion??) and making sure I understand the process more than I do at present.

Nikita:

Re falsiness: Switching back to being more about truthiness and falsiness. Thanks for the feedback.

Re nullsafe: I agree that nullsafe handles the issue of null being returned and it’s a welcomed workaround, but it doesn’t address the problem of null being returned instead of a false (empty) object of the desired type that can be acted upon - even if limited.

Brings up the new question again: Under what circumstances would PHP return null without a developer explicitly asking it to (somewhere in the call chain) or without PHP error?

Cheers,
Josh

---

## #111005 — Josh Bruce — 2020-07-14T18:24:46+00:00

URL: https://externals.io/message/110967#111005 · In reply to: #111004

> 
> 
> 
> > […]
> 
> Christoph: Wow, okay. Thank you!
> 
> All: I’ve decided to go ahead and do one more round using GitHub (big changes - kind of a synthesis of directions so far based on feedback).
> 
> Then I’ll spend time transferring it to a draft (or discussion??) and making sure I understand the process more than I do at present.
> 
> Nikita:
> 
> Re falsiness: Switching back to being more about truthiness and falsiness. Thanks for the feedback.
> 
> Re nullsafe: I agree that nullsafe handles the issue of null being returned and it’s a welcomed workaround, but it doesn’t address the problem of null being returned instead of a false (empty) object of the desired type that can be acted upon - even if limited.
> 
> Brings up the new question again: Under what circumstances would PHP return null without a developer explicitly asking it to (somewhere in the call chain) or without PHP error?
> 
> Cheers,
> Josh
> 

ps. Link: https://bit.ly/php-0002 <https://bit.ly/php-0002> - sorry
