Re: Re: Generic classes and methods RFC
| From: | Stephen Coakley | Date: | Thu, 10 Sep 2015 01:50:41 +0000 |
| Subject: | Re: Re: Generic classes and methods RFC | ||
| References: | 1 2 3 4 5 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-88131@lists.php.net to get a copy of this message | ||
On 09/07/2015 02:02 PM, George Bond wrote:
On 7 September 2015 at 11:37, Ben Scholzen <mail@dasprids.de> wrote:You could also just use the dollar sign for type variables. As inHello, Hi Ben!Generics are a feature I'd love to see in PHP. I think this RFC could do with a little elaboration, though. Something that's particularly important to me is if it be possible to have default values for type parameters? For example, could I make a class like this?I'm not sure if we would need any other default than "mixed". Personally I think that you should be able to instantiate any generic class which does not enforce specific types on the hints without any types, which automatically turns it into a mixed-type generic. That should cover this use-case pretty easily. On a different note, I'm not sure I like the<?php // note the =, a default value (like function parameters) class List<T=mixed> { private $array = [];// ...public function append(T $value) { $this->array[] = $value; } }$integerList = new List<int>; // only accepts integers $list = new List; // accepts any valueHere, 'mixed' means any type, like in the PHP manual or in Hack. We don't currently have a 'mixed' typehint since we don't need it (you can simply omit a typehint for a parameter or return type), but it would be useful here. I'd like it if this was possible, because then you could make existing classes use generics without breaking compatibility. It's also more beginner-friendly: people who don't know about generics don't have to use them, if the class author has made this possible. This is in keeping with the "PHP way" where we don't require people to use type hints if they don't want them.class Baz<Foo : \Bar>syntax. For functions parameters, we put the type name before the variable name, e.g.As written in an earlier mail, the colon came up from another email, I'm happy to change it if there's a better suggestion. Though that looks a little strange to me. It's two bare identifiers nextfunction foo(int $bar). So, could we do the same here, i.e.class <\Bar Foo>, for consistency?to eachother (I like that idea, as it makes the code easier to understand. I'm wondering what other people's thoughts about that is.\Bar Foo), unlike function parameters where the second one has a dollar prefix (\Bar $foo). Perhaps type variables, like regular variables, should have some sort of sigil in PHP? This would make it more obvious that something is a type variable and not a class name. To take an example from your RFC, consider the following code snippet:class Entry<KeyType, ValueType> { // ...public function __construct(KeyType $key, ValueType $value) { // ... }// ... }If we hadn't seen the class declaration at the top which makesKeyTypeandValueTypebe type parameters, we might not realise they weren't ordinary classes or interfaces when we looked at__construct. The -Type suffix you've used helps a little, but that's a convention, and isn't guaranteed to be used. Also, in some existing projects, there might be classes with that suffix. What if we use some sort of sigil here to make it clear? Say we used %: class Entry<%KeyType, %ValueType> {// ...public function __construct(%KeyType $key, %ValueType $value) { // ... }// ...} Now, without having to look at the class declaration, we can tell thatKeyTypeisn't a class name, because it has % in front of it.
class Entry<$KeyType, $ValueType>
{
// ...
public function __construct($KeyType $key, $ValueType $value)
{
// ...
}
// ...
}
Not sure if that would be *more* confusing or *less* confusing. If there was such a thing as a "type" type, then, depending on how generics were implemented, the type variables could *literaly* be "type" variables. If that makes any sense at all.
You could also have the type variables resolve to type strings somehow. For example, the output of:
class Box<$T>
{
public function __construct($T $value)
{
// ...
}
public function printType()
{
print "$T\n";
}
}
$box = new Box<\My\Object>(new \My\Object());
$box->printType();
would be "My\Object". Just another idea; one that feels very "PHP-like" to me anyway. Other opinions?
I like the "where" syntax as well. Most of PHP's "type operators" are words instead of glyphs, so it makes sense to keep the tradition for consistency. See the various syntaxes and keywords for using traits for comparison. I think adding a comma between "where" expressions is a little redundant; I'd leave it out like in C#. -- StephenAnyway, all that being said: the big challenge with generics is reallyI'm a fan of the C# syntax for generics ("where" keyword). I think the natural translation of that syntax to PHP would be: class ListOfLoggers<T> extends Enumerable<T> implements ArrayAccessgetting someone to do the nitty-gritty of implementing it. It's great that you've got an RFC written for this, but unless someone is willing to implement it, I fear it may go to waste. But you writing an RFC might inspire someone. There is hope!I hope so as well! Hope my thoughts are somewhat helpful.-- Andrea Faulds http://ajf.me/-- Ben Scholzen http://www.dasprids.dewhere T implements LoggerInterface{...} Ie you have "where <class>" and then a block in the same syntax as a normal class extends/implements declaration. The full structure would be: class Foo<TFirst, TSecond> extends BaseClass<TFirst, AnotherClass> implements IGenericInterface<TSecond>, IOtherInterfacewhere TFirst extends OtherBaseClass implements IAnotherInterface where TSecond extends YetAnotherBaseClass implementsIYetAnotherInterface, IEvenMoreInterfaces {....} C# doesn't put a comma between where blocks, which usually catches me out. It's open to bikeshedding whether it would be sensible to require one here (after "implements IAnotherInterface"), and if so whether to allow a trailing comma (after "IEvenMoreInterfaces"). Thoughts? --G