> On Aug 19, 2024, at 1:08 PM, Derick Rethans <[email protected]> wrote:
>
> Hi!
>
> Arnaud, Larry, and I have been working on an article describing the
> state of generics and collections, and related "experiments".
>
> You can find this article on the PHP Foundation's Blog:
> https://thephp.foundation/blog/2024/08/19/state-of-generics-and-collections/
>
> cheers,
> Derick
Great job on providing so much detail in your blog post.
JMTCW, but I am less of a fan of boil-the-ocean generics and more of a fan of focused pragmatic
solutions like you proposed with the Collection types. The former can result in really complex to
read and understand code whereas the latter — when done well — results in easier to read and
understand code.
It seems Java-style Generics are viewed as the proper archetype for Generics in PHP? I would
challenge the wisdom of taking that road considering how different the compilers and runtimes are
between the Java and PHP. PHP should seek out solutions that are a perfect fit for its nature and
not pursue parity with Java.
As PHP is primarily a web development language — vs. a systems language like C or Rust, or an
enterprise application language like Java or C# — reducing code complexity for reading and
understanding is a very important attribute of the language.
PHP is also a unique language and novel solutions benefit a unique language. PHP should pursue
solutions that result in less complex code even if not found in other languages. Your collections
idea is novel — which is great — but there are probably even more novel solutions to address
other needs vs. going full-on with Java-style generics.
Consider if adding type aliases; or augmenting, enhancing, or even merging classes, interfaces,
and/or traits to address the needs Java-style generics would otherwise provide. I would work on some
examples but I think you are more likely to adopt the features you come up with on your own.
--------
As for type-erasure, I am on the fence, but I find the proposed "how" problematic. I can
see wanting some code to be type-checked and other code not, but I think more often developers would
want code type-checked during development and testing but not for staging or production. And if the
switch for that behavior is in every file that means modifying every file during deployment. IMO
that is just a non-starter.
If you are going to pursue type-erasure I recommend introducing a file in the root — call it
.php.config
or similar — that contains a wildcard enabled tree-map of code with
attributes settable for each file, directory, group of files and/or group of directories where one
attribute is type-checked or other attributes are reserved for future use. This config file should
also be able to delegate the .php.config
files found elsewhere, such as config files
for each package in the vendor directory. It would be much better and easier to swap out a few
.php.config
files during CI/CD than to update all files.
Additionally PHP could use an environment variable as prescribed by 12 Factor apps to identify the
root config file. That way a hosting company could allow someone to configure their production
server to point to .php.production.config
instead of
`.php.development.config
.
-Mike
P.S. Also consider offering the ability for a function or class method to "type" a
parameter or variable based on an interface and then allow values that satisfy that interface
structurally[1] but not necessarily require the class to explicitly implement the interface.
This is much like how Stringable
is just automatically implemented by any class that
has a __ToString()
method, but making this automatic implementation available to
userland. Then these automatically-declared interfaces can cover some of the use-cases for generics
without the complexity of generics.
For example — to allow you to visualize — consider a Printable
interface that
defines a print()void
method. If some PHP library has a class Foo
and it
has a method with signature print()void
then we could write a function to use it, maybe
like so:
---------
interface Printable {
print($x any)void
}
// The prefix ?
on Printable
means $printer
just has to match
the Printable
interface's signature
function doSomething($printer ?Printable) {
$printer->print()
}
$foo = new Foo();
doSomething($foo);
---------
Something to consider?
[1] https://en.wikipedia.org/wiki/Structural_type_system