# [RFC][Discussion] Objects can be declared falsifiable

- Thread: https://externals.io/message/118971
- Original archive: https://news-web.php.net/php.internals/118971
- Started by Josh Bruce on 2022-11-04T23:05:06+00:00
- Messages: 11
- 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

---

## #118930 — Josh Bruce — 2022-10-31T19:38:05+00:00

URL: https://externals.io/message/118971#118930

Hello Interntals,

Someone reached out to me outside of internals regarding the RFC I submitted on being able to declare objects falsifiable, so, I decided to update and re-enter the fray.

I’ve updated the references section as many of the RFCs that were under discussion at the time have since been implemented.

I still find myself in situations where having the capability would be beneficial. Specifically, I’m noticing with API responses where I want to pass the body received from a ResponseInterface the object can check itself. I currently use methods such as:

->isValid()
->isInvalid()
->toBool()

And similar - the isValid and isInvalid() methods are just aliases of toBool(), which speaks to the ability for adopters to make their interfaces compatible without breaking changes in their code.

In the case of a conditional - looks like this:

$obj = Object::init($response);
If ($obj->isValid()) {
    // do something with $obj
}

Or:

If (
    $obj = Object::init($response) and
    $obj->isValid()
) {
    // do something with $obj
}

Would like to be able to do something like:

If ($obj = Object::init($response)) {
    // do something with $obj
}

As of today, the last example is always true. You wouldn’t be able to create a guard clause for the negation:

If (
    $obj = Object::init($response) and
    $obj === false
) {
    // handle invalid object, which could include something like $obj->failed()
}

Cheers,
Josh

> 
> 
> Hey Internals,
> 
> So, I received a message that said of the mail I should have received from internals bounced; so, this is part test and part update.
> 
> I’ve started mapping out call paths in the project that brought this concept to light.
> 
> The project, Shoop, never uses `is_bool()` - instead it always uses empty, then reverses that for:
> 
> 1. Booleans
> 2. Numbers
> 3. Arrays
> 4. Strings
> 5. stdClass or data-only classes
> 6. Json strings, which it treats as #5
> 
> I essentially get standard SPL behavior when I do this.
> 
> For the object definition I can define two interfaces:
> 
> 1. Falsifiable
> 2. Emptiable
> 
> The checks go like this:
> 
> 1. if the object implements Falsifiable: the __toBool method would be called and would return the result. (This check would be inside `is_bool()` and could use the empty() implementation)
> 2. if the object implements Emptiable: the __isempty method would be called and return the result. (This check would be inside empty())
> 3. else: standard output from `is_bool()` or empty() would be used when passing an instance to either of those SPL functions, depending on which the user is using.
> 
> Because the concepts of emptiness and falsiness are so tightly coupled, I’m wondering if it would be better to implement both with this RFC??
> 
> Otherwise, Emptiable would be a future enhancement consideration.
> 
> I’d like to hear what the rest of Internals thinks.
> 
> Next for me: I’m going to finish solidifying the Shoop project and make sure my other projects can use latest and then continue going through the tutorials from Nikita and others on doing development Internals.
> 
> Cheers,
> Josh
> 
> > […]

---

## #118934 — Marco Pivetta — 2022-10-31T21:52:20+00:00

URL: https://externals.io/message/118971#118934 · In reply to: #118930

Since this topic fits like a glove, just dropping the "why I don't use
`__toString()`" argument here:
https://github.com/ShittySoft/symfony-live-berlin-2018-doctrine-tutorial/pull/3#issuecomment-460085493

A falsifiable object is worse than `__toString()` in this context, IMO.

Marco Pivetta

https://twitter.com/Ocramius

https://ocramius.github.io/




> Hello Interntals,
>
> Someone reached out to me outside of internals regarding the RFC I
> submitted on being able to declare objects falsifiable, so, I decided to
> update and re-enter the fray.
>
> I’ve updated the references section as many of the RFCs that were under
> discussion at the time have since been implemented.
>
> I still find myself in situations where having the capability would be
> beneficial. Specifically, I’m noticing with API responses where I want to
> pass the body received from a ResponseInterface the object can check
> itself. I currently use methods such as:
>
> ->isValid()
> ->isInvalid()
> ->toBool()
>
> And similar - the isValid and isInvalid() methods are just aliases of
> toBool(), which speaks to the ability for adopters to make their interfaces
> compatible without breaking changes in their code.
>
> In the case of a conditional - looks like this:
>
> $obj = Object::init($response);
> If ($obj->isValid()) {
>     // do something with $obj
> }
>
> Or:
>
> If (
>     $obj = Object::init($response) and
>     $obj->isValid()
> ) {
>     // do something with $obj
> }
>
> Would like to be able to do something like:
>
> If ($obj = Object::init($response)) {
>     // do something with $obj
> }
>
> As of today, the last example is always true. You wouldn’t be able to
> create a guard clause for the negation:
>
> If (
>     $obj = Object::init($response) and
>     $obj === false
> ) {
>     // handle invalid object, which could include something like
> $obj->failed()
> }
>
> Cheers,
> Josh
>
> > […]
> from internals bounced; so, this is part test and part update.
> > […]
> concept to light.
> > […]
> then reverses that for:
> > […]
> called and would return the result. (This check would be inside `is_bool()`
> and could use the empty() implementation)
> > […]
> called and return the result. (This check would be inside empty())
> > […]
> passing an instance to either of those SPL functions, depending on which
> the user is using.
> > […]
> I’m wondering if it would be better to implement both with this RFC??
> > […]
> sure my other projects can use latest and then continue going through the
> tutorials from Nikita and others on doing development Internals.
> > […]
> josh@joshbruce.dev>> wrote:
> > […]
> few minutes here and there; definitely on the list.
> > […]
> across Pipeline from the PHP League and saw their interruptible processor
> and was wondering if something like this would be helpful there - for
> pipeline patterns in general:
> https://github.com/thephpleague/pipeline/blob/master/src/InterruptibleProcessor.php
> > […]
> array_filter docs:
> > […]
> (see converting to boolean) will be removed."
> > […]
> wanted to put a working (non-internals) implementation out there (note this
> covers emptiness and falseness for the purposes of the project):
> > […]
> https://github.com/8fold/php-shoop/blob/master/tests/RfcObjectCanBeDeclaredFalsifiableTest.php
> > […]
> https://github.com/8fold/php-shoop/blob/master/src/FilterContracts/Interfaces/Falsifiable.php
> - for our purposes the efToBool would be __toBool
> > […]
> https://github.com/8fold/php-shoop/blob/master/src/Shooped.php#L216
> > […]
> https://github.com/8fold/php-shoop/blob/master/src/Filter/TypeAsBoolean.php
> > […]
> <mailto:tysonandre775@hotmail.com>> wrote:
> > […]
> (linked to in your RFC's reference) when implementing this PR.
> > […]
> class which is falsifiable - SimpleXMLElement.
> > […]
> int type)
> > […]
> zend_function *fptr_count)
> > […]
> to fall back to the original handlers for types other than bool.
> > […]
> class entry's zend_object_handlers,
> > […]
> behaviors from SimpleXMLElement and other classes continuing to work.
> > […]
> bother handling the possibility that `object` can be false even after it
> was checked for falsiness.
> > […]
> adding the special casing and performance overhead checking for FFI objects
> and SimpleXMLElement, subclasses of those is currently low priority
> compared to those things.
> > […]
> in practice.
> > […]
> classes, though, and the priority would increase if the RFC passed.
> > […]
> probably wouldn't get changed in any php release
> > […]
> of the data structures treat emptiness as false and half don't.
> > […]
> convenient but turns out prone to accidental bugs and later is deprecated
> and removed.
> > […]
> https://stackoverflow.com/questions/25031236/if-elem-vs-elem-is-not-none
> was seen in python
> > […]
> slow_db_operation(); }`
> > […]
> objects (executed repeatedly instead of once))
> > […]
> thought this might be a valid use case:
> > […]

---

## #118938 — michal.brzuchalski@gmail.com — 2022-11-02T08:12:19+00:00

URL: https://externals.io/message/118971#118938 · In reply to: #118930

Hi Josh,

pon., 31 paź 2022 o 20:38 Josh Bruce <josh@joshbruce.dev> napisał(a):

> Hello Interntals,
>
> Someone reached out to me outside of internals regarding the RFC I
> submitted on being able to declare objects falsifiable, so, I decided to
> update and re-enter the fray.
>
> I’ve updated the references section as many of the RFCs that were under
> discussion at the time have since been implemented.
>
> I still find myself in situations where having the capability would be
> beneficial. Specifically, I’m noticing with API responses where I want to
> pass the body received from a ResponseInterface the object can check
> itself. I currently use methods such as:
>
> ->isValid()
> ->isInvalid()
> ->toBool()
>
> And similar - the isValid and isInvalid() methods are just aliases of
> toBool(), which speaks to the ability for adopters to make their interfaces
> compatible without breaking changes in their code.
>
> In the case of a conditional - looks like this:
>
> $obj = Object::init($response);
> If ($obj->isValid()) {
>     // do something with $obj
> }
>
> Or:
>
> If (
>     $obj = Object::init($response) and
>     $obj->isValid()
> ) {
>     // do something with $obj
> }
>
> Would like to be able to do something like:
>
> If ($obj = Object::init($response)) {
>     // do something with $obj
> }
>
> As of today, the last example is always true. You wouldn’t be able to
> create a guard clause for the negation:
>
> If (
>     $obj = Object::init($response) and
>     $obj === false
> ) {
>     // handle invalid object, which could include something like
> $obj->failed()
> }
>

Have you tried not initializing invalid objects? This could help you.
Also that sounds more logical to me as I don't see any reasons to
initialize invalid objects if it's a matter of simple validation instead.

P.S. I don't see it feasible to have objects that evaluate false in
logical expressions.

Cheers,
Michał Marcin Brzuchalski

---

## #118940 — Claude Pache — 2022-11-02T17:51:50+00:00

URL: https://externals.io/message/118971#118940 · In reply to: #118938

> Le 2 nov. 2022 à 09:12, Michał Marcin Brzuchalski <michal.brzuchalski@gmail.com> a écrit :
> 
> P.S. I don't see it feasible to have objects that evaluate false in
> logical expressions.

For better or for worse (IMHO, for worse), `SimpleXMLElement` instances representing attributeless empty elements are already falsy, so yes, it is absolutely feasible.

—Claude

---

## #118941 — Marco Pivetta — 2022-11-02T18:09:35+00:00

URL: https://externals.io/message/118971#118941 · In reply to: #118940

>
>
> > […]
> michal.brzuchalski@gmail.com> a écrit :
> > […]
>
> For better or for worse (IMHO, for worse), `SimpleXMLElement` instances
> representing attributeless empty elements are already falsy, so yes, it is
> absolutely feasible.
>
> —Claude


This is absolutely terrifying.

Marco Pivetta

https://twitter.com/Ocramius

https://ocramius.github.io/

---

## #118944 — Jordan LeDoux — 2022-11-02T21:08:50+00:00

URL: https://externals.io/message/118971#118944 · In reply to: #118938

On Wed, Nov 2, 2022 at 1:12 AM Michał Marcin Brzuchalski <
michal.brzuchalski@gmail.com> wrote:

> Hi Josh,
>
> Have you tried not initializing invalid objects? This could help you.
> Also that sounds more logical to me as I don't see any reasons to
> initialize invalid objects if it's a matter of simple validation instead.
>
> P.S. I don't see it feasible to have objects that evaluate false in
> logical expressions.
>
> Cheers,
> Michał Marcin Brzuchalski
>

The one situation in which I can think of where an object might
legitimately have a falsey bool casting is if it represents a single value
(that may have multiple properties associated with it, like units of
measurement), and `if ($obj)` is really asking something like `if
($obj->castSingleValuePropertyToBool())`.

For most of *these* situations, either `if ($obj->isEqual(0))` is
equivalent, or `if ($obj == 0)` is equivalent if operator overloading was
accepted.

Jordan

---

## #118947 — Josh Bruce — 2022-11-03T01:51:16+00:00

URL: https://externals.io/message/118971#118947 · In reply to: #118941

Thank you all for the engagement so far.

(Note: All scalar types and one compound type can be cast as true or false natively - of the scalar and compound types, callable and object are the only two with no, native false representation.)

> Have you tried not initializing invalid objects? This could help you. Also that sounds more logical to me as I don't see any reasons to initialize invalid objects if it's a matter of simple validation instead.


I've tried valid objects (multiple approaches) - and I’m using the term valid loosely because the instances are not, technically, invalid in the strictest sense. I’m using “valid” and “invalid” as method names in the implementation because I don’t have a better word to describe the concept; still looking. If you'd like to hear more, please let me know and I can detail out other approaches, which are pretty standard. 

I only used it as an example of what would be possible and trying to illustrate using a real world example of the problem-space.

With that said, the RFC isn’t meant to directly solve an implementation issue that can’t be solved any other way; it’s more syntax, style, and consistency (see note above). 

Similar to:

function x(?SomeType $arg): ?SomeOtherType

Instead of:

function x(SomeType|null $arg): SomeType|null

Both are the same thing under the hood.

In that same spirit, totally opt-in - not required to use or you can get there some other way - similar to Marco’s comment around __toString. 

For example, I actively avoid null and don’t use most null-related things available in PHP and tend to wrap objects, methods, and functions that might return null…but, if you’re into null, don’t let me stop you. :)

(I also tend to wrap objects, methods, and functions that return bool and some other type to put them in a context where I get one or the other, but not either-or - file_put_contents, for example…big fan of single return types.)

> The one situation in which I can think of where an object might legitimately have a falsey bool casting is if it represents a single value


I see that, though I don’t necessarily agree.

To use similar language, the object could represent a single, complex concept (especially through composition) - not just a single value. 

A car without a blinker is still a car and usable for most things it was designed for - and there could be a fallback for the missing blinker; valid instance with a non-blocking deficiency: https://www.dmv.org/how-to-guides/hand-signals-guide.php

> > […]


I’m interested in more detail on this. 

Feasible as in not possible to do easily? Not possible in general? Or, something else? 

> For better or for worse (IMHO, for worse), `SimpleXMLElement` instances representing attributeless empty elements are already falsy, so yes, it is absolutely feasible.

Interesting use case. Haven’t used SimpleXMLElement enough to comment.

Interested to hear more.

> This is absolutely terrifying.

Not sure if this is referring to the SimpleXMLElement reference or beyond it. :)

Cheers,
Josh

> 
> 
> 
> 
> > […]
> 
> 
> This is absolutely terrifying.
> 
> Marco Pivetta
> 
> https://twitter.com/Ocramius
> 
> https://ocramius.github.io/

---

## #118948 — Claude Pache — 2022-11-03T08:30:23+00:00

URL: https://externals.io/message/118971#118948 · In reply to: #118947

> Le 3 nov. 2022 à 02:51, Josh Bruce <josh@joshbruce.dev> a écrit :
> 
> Similar to:
> 
> function x(?SomeType $arg): ?SomeOtherType
> 
> Instead of:
> 
> function x(SomeType|null $arg): SomeType|null
> 
> Both are the same thing under the hood.

The big difference between `?SomeType` shortcut and falsifiable object feature, is that using `?SomeType` does not change the semantics of `SomeType|null`, while declaring an object falsifiable changes the semantics of `if ($obj)`.

> 
> In that same spirit, totally opt-in - not required to use or you can get there some other way - similar to Marco’s comment around __toString. 



It is opt-in for the implementer of the library, not for the user of it, as they are not necessarily the same person.

Today, in a common situation where I know that a variable contains either an object of some type or null, I routinely write `if ($a)` to mean `if ($a !== null)`. Now, with magic `__toBool()` possibly implemented by  the library’s author, I don’t know what `if ($a)` means, unless I have carefully read the docs in order to know whether they have opt into that misfeature, and, if so, what exactly “falsy” means for them (invalid?, empty?, zero?). Ironically, that will incite me to not use anymore the implicit casting to bool for objects, and to write systematically `if ($a !== null)`, so that both myself and the reader of my code won’t have to look at the docs in order to understand such simple code.

—Claude

---

## #118957 — Josh Bruce — 2022-11-04T00:01:35+00:00

URL: https://externals.io/message/118971#118957 · In reply to: #118948

>  while declaring an object falsifiable changes the semantics of `if ($obj)`.

Got me thinking, appreciate that. 

In PHP: 

false == empty == null 

(Originally the RFC was geared toward data objects being able to natively express emptiness when passed to empty() - might be beneficial for the SimpleXMLElement topic - conversation revealed false and empty are tightly coupled in PHP and the preference was to declare false instead of empty to cover more use cases, including empty().)

I’m not sure how much if ($obj) actually changes what we do at a fundamental level - due to the true/false (null) caveat:

> Today, in a common situation where I know that a variable contains either an object of some type or null […]
> unless I have carefully read the docs in order to know whether they have opt into that misfeature, and, if so, what exactly “falsy” means for them (invalid?, empty?, zero?).

Do you still find yourself reading the docs or debugging to figure out why the thing became null instead of another, expected type (I do)?

Asked in a different way, with or without the RFC, I still need to know if the implementer has opted in to using null (or empty or false), and under what circumstances I would receive null (or empty or false), yeah?

Default behavior is:

if (new MyType($config)) {
  // do something with not null - true - can’t use object because unassigned

}
// code is unreachable because instances always resolve to true unless an exception occurs during initialization; the guard is somewhat unnecessary.

Given the default behavior, would we consider a static initializer returning MyType|null or ?MyType to be an anti-pattern (“misfeature”), because __construct can’t return null (or false or anything else really)?

We could also throw during initialization; see Stripe: https://github.com/stripe/stripe-php/blob/9c7e27ab7e30a50853aa23139d581ceab3b5e619/lib/BaseStripeClient.php#L254

try {
  $obj = new MyType($config);

  // handle true - able to use $obj

} catch ($e) {
  // handle false - object type we interact with is the error - not null and not $obj, but still represents false because the unintended occurred

}

Or we could opt in to returning the instance of the error directly, without throwing: MyType|MyError - user would still need to guard in some way - using `is_a()` possibly - see null objects: https://en.wikipedia.org/wiki/Null_object_pattern

Shifting gears.

Consider a situation where there’s a range of true and false within the object definition; PSR-7 responses due to HTTP status codes: https://www.php-fig.org/psr/psr-7/ and https://developer.mozilla.org/en-US/docs/Web/HTTP/Status

if ($response->getStatusCode() > 199 and $response->getStatusCode() < 300) {
  // do something with “true” - which has a range of 100 possibilities at a granular level, which we could respond to differently - possible to interact with $response

}
// do something with “false” - which has a range of more than 100 possibilities at a granular level, which we could respond to differently - possible to interact with $response

We might wrap response to create an isOk() method to move the conditional logic somewhere within the object itself and make the call site more readable.

If ($response->isOk()) {
  // do something with “true” - still able to interact with $response

}
// do something with “false” - still able to interact with $response

With the RFC:

if (new MyType($config)) {
  // do something with “true” - can’t use MyType because not assigned

}
// reachable because possible to resolve to false - if implements Falsifiable and __toBool can resolve to false - can’t use MyType because not assigned

if ($response = new MyType($config)) {
  // do something with “true” - with the option of using $response

}
// reachable - can’t use MyType because may not be assigned

$response = new MyType($config);
If ($response) {
  // do something with “true” - with the option of using $response

}
// do something with “false” - with the option of using $response

Or a host of other possibilities for the conditional guard.

They’re all shorthands for the same, high-level concept - does this thing resolve to true *or* false (null), yeah?

Cheers,
Josh

ps. 

Added open issue of what to do with callable: https://wiki.php.net/rfc/objects-can-be-falsifiable - specifically in the context of __invoke()

Added invokable RFC to RFC list.

> 
> 
> 
> 
> > […]
> 
> The big difference between `?SomeType` shortcut and falsifiable object feature, is that using `?SomeType` does not change the semantics of `SomeType|null`, while declaring an object falsifiable changes the semantics of `if ($obj)`.
> 
> > […]
> 
> 
> 
> It is opt-in for the implementer of the library, not for the user of it, as they are not necessarily the same person.
> 
> Today, in a common situation where I know that a variable contains either an object of some type or null, I routinely write `if ($a)` to mean `if ($a !== null)`. Now, with magic `__toBool()` possibly implemented by  the library’s author, I don’t know what `if ($a)` means, unless I have carefully read the docs in order to know whether they have opt into that misfeature, and, if so, what exactly “falsy” means for them (invalid?, empty?, zero?). Ironically, that will incite me to not use anymore the implicit casting to bool for objects, and to write systematically `if ($a !== null)`, so that both myself and the reader of my code won’t have to look at the docs in order to understand such simple code.
> 
> —Claude

---

## #118958 — michal.brzuchalski@gmail.com — 2022-11-04T05:37:40+00:00

URL: https://externals.io/message/118971#118958 · In reply to: #118957

>
> if ($response->getStatusCode() > 199 and $response->getStatusCode() < 300)
> {
>   // do something with “true” - which has a range of 100 possibilities at
> a granular level, which we could respond to differently - possible to
> interact with $response
>
> }
> // do something with “false” - which has a range of more than 100
> possibilities at a granular level, which we could respond to differently -
> possible to interact with $response
>
> We might wrap response to create an isOk() method to move the conditional
> logic somewhere within the object itself and make the call site more
> readable.
>
> If ($response->isOk()) {
>   // do something with “true” - still able to interact with $response
>
> }
> // do something with “false” - still able to interact with $response
>

This looks way much cleaner and is easy to read and understand.
While I understand the proposed feature is opt-int it introduces more magic
that can be solved using more verbose and IMO cleaner solutions.


> With the RFC:
>
> if (new MyType($config)) {
>   // do something with “true” - can’t use MyType because not assigned
>
> }
> // reachable because possible to resolve to false - if implements
> Falsifiable and __toBool can resolve to false - can’t use MyType because
> not assigned
>
> if ($response = new MyType($config)) {
>   // do something with “true” - with the option of using $response
>
> }
> // reachable - can’t use MyType because may not be assigned
>
> $response = new MyType($config);
> If ($response) {
>   // do something with “true” - with the option of using $response
>
> }
> // do something with “false” - with the option of using $response
>

This is somehow confusing, why is the $response storing object ref is ok
while inclining the new object creation is not?
This requires more attention while reading and debugging.

Cheers,
Michał Marcin Brzuchalski

---

## #118971 — Josh Bruce — 2022-11-04T23:05:06+00:00

URL: https://externals.io/message/118971#118971 · In reply to: #118958

> While I understand the proposed feature is opt-int it introduces more magic
> that can be solved using more verbose and IMO cleaner solutions.

Understood and appreciate the position.

> This is somehow confusing, why is the $response storing object ref is ok
> while inclining the new object creation is not?

Not quite following, apologies.

Adding a different use case.

Allow for fully-specified custom collections; array being the compound type that can resolve to false/empty based on count.

$array = [];

(bool) $array; // false

empty($array); // true

if ($array) { 
  // handle not empty 
} 
// handle empty

$array = [1, 2, 3];

(bool) $array; // true

empty($array); // false

if ($array) { 
  // handle not empty 
} 
// handle empty

Current state of PHP re custom collections (exclamation marks - ! - represent difference compared to native array):

class MyCollection implements ArrayAccess, Iterator, Countable {}

$collection = new MyCollection([]);

(bool) $collection; // true - ! - because instance exists, regardless of collection content

empty($collection); // false - ! - same reason as previous

if ($collection) { 
  // ! - handle empty and not empty 
} 
// ! - unreachable

$collection = new MyCollection([1, 2, 3]);

(bool) $collection; // true - because instance exists, regardless of collection content

empty($collection); // false - same as previous

if ($collection) { 
  // ! - handle empty and not empty 
} 
// ! - unreachable

With RFC:

class MyCollection implements ArrayAccess, Iterator, Countable, Falsifiable 
{
  public function __toBool(): bool
  {
    return $this->count() > 0;
  }  
}

$collection = new MyCollection([]);

(bool) $collection; // false - because collection count === 0 - close to the previous comment re single value under inspection

empty($colleciton); // true - same as previous

if ($collection) { 
  // handle not empty 
} 
// handle empty

$collection = new MyCollection([1, 2, 3]);

(bool) $collection; // true - because collection count > 0

empty($colleciton); // false - same as previous

if ($collection) { 
  // handle not empty 
} 
// handle empty

Alternative approaches for custom collection use case: 

1. Modify Countable (most likely, if using alternative) to include empty() and bool() methods. 

Might feel more palatable despite not strictly limiting scope to the custom collection use case. 

Any class with Countable, for example, would also be able to resolve to false or empty using SPL functions - including use in IF.

Allows for explicit (“verbose"), direct call of both methods by user should they choose:

$collection->empty()

$collection->bool()

Instead of $collection->__toBool() OR something like $collection->__isEmpty()

Known drawback to using Countable would be in a possible future where there is a separation between 0, false, and empty when it comes to type juggling in PHP. 

Whereas using a Falsifiable interface leaves a simpler path of an Emptiness interface; again, should the three be separated in the future.

2. Or, modify ArrayAccess to include the empty() and bool() methods.

This would restrict the behavior more toward the custom collection concept.

However, would lean more toward Countable due to the equivalence in PHP type juggling and Countable using an integer: 0 == false == empty

Otherwise, similar to alternative #1.

3. Or, modify Iterator to include the empty() and bool() methods (or possibly leverage the valid() method that already exists?); otherwise, similar to alternative #2.

Cheers,
Josh

> 
> 
> > […]
> 
> This looks way much cleaner and is easy to read and understand.
> While I understand the proposed feature is opt-int it introduces more magic
> that can be solved using more verbose and IMO cleaner solutions.
> 
> 
> > […]
> 
> This is somehow confusing, why is the $response storing object ref is ok
> while inclining the new object creation is not?
> This requires more attention while reading and debugging.
> 
> Cheers,
> Michał Marcin Brzuchalski
