> 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