[RFC][DISCUSSION] Collection Inspection
| From: | Michael Morris | Date: | Thu, 25 Jan 2018 01:39:14 +0000 |
| Subject: | [RFC][DISCUSSION] Collection Inspection | ||
| Groups: | php.internals | ||
| Request: | Send a blank email to internals+get-101662@lists.php.net to get a copy of this message | ||
Ok, here's another idea I've been mulling over. This I know is possible
because I've done it using user land code, specifically Drupal 8's
Assertion\Inspector class.
https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Component%21Assertion%21Inspector.php/class/Inspector/8.5.x
These methods provide a means to inspect collections - arrays usually but
also Traversables. They fill a hole in the PHP library - the ability to
check collection integrity.
To answer the question "Why in core?" - well, Drupal needing to do this
using a library referenced only by assert() statements creates an
undocumented dependency for any class that wants to run these checks. From
a pragmatic standpoint it just feels wrong. Most other languages have some
means of doing these checks.
IMPLEMENTATION STYLE #1: collectionof operator
The style of implementation I like the most is a collectionof operator in
parallel to the instance_of operator. It would be instanceof's plural
brother, so
$arg collectionof \SomeClass
To pass the check $arg must be of the iterable psuedotype with all its
values being a \SomeClass object.
This is all well and good, but collection integrity checks are usually
going to be looking to see if all the members are the same scalar.
$arg collectionof string
For language consistency we would need to allow instance_of to do the same,
which it currently does not.
$arg instanceof string
This does create duplication with the is_* family of functions, but
instanceof already overlaps is_a heavily.
IMPLEMENTATION STYLE #2: all_*
This style takes the is_* family and creates plural cousins for them.
Example:
all_string($arg);
This is most similar to the user land solution. Following the current is_*
family this gives us all_array(), all_bool(), all_callable(), all_double(),
all_float(), all_int(), all_integer(), all_iterable(), all_long(),
all_null(), all_numeric(), all_object(), all_real(), all_scalar(), and
all_string(). One other function, all_are(), would be necessary for class
and interface inspection.
That's a lot of new functions, and the chance of BC breaking with someone's
code is very high, so I don't personally like this approach. I'm putting it
out there as alternate because despite that shortcoming it is a sensible
alternative.