On Fri, Apr 29, 2016 at 4:55 AM, Jesse Schalken <m...@jesseschalken.com>
wrote:

>
>
> On Wed, Apr 27, 2016 at 6:50 AM, guilhermebla...@gmail.com <
> guilhermebla...@gmail.com> wrote:
>
>> Hi all,
>>
>> Yesterday I spent a considerable 2h talking about Generics in Doctrine
>> channel.
>> We discussed the specifics of each boundary that PHP's implementation
>> could
>> take advantage. Here are our findings, which I'll illustrate using Java
>> equivalents:
>>
>> 1- Upper bounds (T extends A)
>>
>> We all understood they're required. Whenever you mention class Foo<T is A>
>> {}, we're talking that T can be A or any of its subtypes.
>> Also, we debated over intersection types. It's an edge case, and its
>> support could be done as a subsequent RFC once union and intersection
>> types
>> gets resolved.
>>
>> 2- Lower bounds (T super A)
>>
>> It was just not possible to come up with a single use case or possibility.
>> It not only violates Liskov, but it also doesn't make any sense in the
>> context of PHP.
>> When we debate about Java, it does make sense because of polymorphism and
>> the requirement removal of implementing multiple methods.
>>
>> 3- Unbounded wildcards (?)
>>
>> It wouldn't be necessary in the context of PHP. Why?
>> Once we introduce Generics, the difference between process(List $list) and
>> process(List<?> $list) would be none, as due to PHP's nature.
>>
>> 4- Upper bounded wildcard (? extends A)
>>
>> Again, invalid in the context of PHP. Let me explain why...
>> In Java context, whenever you declare something as List<A>, you can only
>> add As to the list, but no subtypes. When you declare List<? extends A>,
>> you can add A and also any of its subtypes.
>> PHP is loose in this restriction, so there's no way of strict-ing to only
>> A
>> but not subtypes. Defining as List<A> would be enough, and PHP wouldn't
>> support adding A and A only.
>>
>
>
> You can add subtypes of A to a List<A> in Java. What List<? extends A>
> means is that the list itself may be a list of any type, provided that type
> is compatible with A. So if B extends A, List<B> is compatible with List<?
> extends A>, and when reading items you can assume they will be compatible
> with A (since B extends A) but you can't add an A (because it's actually a
> list of Bs).
>
>
Wrong. This is documented here
https://docs.oracle.com/javase/tutorial/java/generics/upperBounded.html and
specifically states:

To write the method that works on lists of Number and the subtypes of Number,
> such as Integer, Double, and Float, you would specify List<? extends
> Number>. The term List<Number> is more restrictive than List<? extends
> Number> because the former matches a list of type Number only, whereas
> the latter matches a list of type Number or any of its subclasses.




> Similarly, List<? super A> means it may be a list of A or some super type
> of A. So if A extends C, List<C> is compatible with List<? super A>, and
> you can add an A (because A is compatible with C) but when reading items
> you can't assume they're going to be As (because it's actually a list of
> Cs).
>
>
Again wrong. The lower bound also respect the rules of upper bound
wildcard. If you return a List<C>, you cannot add an A instance.


> This is my understanding of variance behaviour and notation in the three
> languages I'm most familiar with:
>
> Covariance (Foo<Sub> is a subtype of Foo<Super>)
>
> Java  Foo<? extends T> at usage  Methods accepting T as parameter cannot
> be called
> Hack  Foo<+T> at declaration     Methods accepting T as parameter cannot
> be defined
> C#    Foo<out T> at declaration  Methods accepting T as parameter cannot
> be defined
>
>
> Contravariance (Foo<Super> is a subtype of Foo<Sub>)
>
> Java  Foo<? super T> at usage   Methods returning T can be called but
> return Object
> Hack  Foo<-T> at declaration    Methods returning T cannot be defined
> C#    Foo<in T> at declaration  Methods returning T cannot be defined
>
>
> Invariance (no relationship between Foo<Super> and Foo<Sub>)
>
> Java  Foo<T> at usage           Methods accepting T and returning T can
> both be called
> Hack  Foo<T> at declaration     Methods accepting T and returning T can
> both be defined
> C#    Foo<T> at declaration     Methods accepting T and returning T can
> both be defined
>
>
> (There are more general rules for method signatures when T is used as the
> parameter for another generic type, but I can't remember what they are.)
>
> I can't see variance mentioned in the RFC, but when I asked about it when
> the RFC was posted on Reddit, Rasmus said the type parameters would always
> be covariant, so Foo<A> in PHP as an annotation would be equivalent to
> Foo<? extends A> in Java, even though this has the opposite of the
> intended effect if Foo has methods which accept a parameter of the generic
> type, such as something like List<T>::add(T $element), Callback<T>::run(T
> $data) or Box<T>::setContents(T $contents).
>
>
Rasmus is purely following already defined PHP covariance definition that
currently exists for type hinting into generic types.
Java differs from that and accept covariance for type definitions, but
restricts for generic types.


> My view is that PHP's generics should be invariant to start with (generic
> arrays can still be covariant of course, since they are passed by value),
> maintaining type safety and matching the behaviour of Java, Hack and C# for
> type parameters without variance annotations, and variance syntax should be
> added later as another RFC as demand arises.
>
>
>
> 5- Lower bounded wildcard (? super A)
>>
>> Applies the same concept of #2. PHP doesn't need it as it doesn't fully
>> support polymorphism.
>>
>> 6- Reflection
>>
>> We discussed over an example I extracted from a piece of code I currently
>> work on. We came with several ideas, but couldn't wrap up (but we're 80%)
>> a
>> valid approach. The example we debated was this one:
>> https://gist.github.com/guilhermeblanco/56ec0e11e7b029c2cfdcaf6fe2323742
>>
>>
>>
>>
>> So I'll have to say sorry for poking around of "missing implementation"
>> while in reality most of them cannot be applied in the context of PHP.
>> I've reviewed the RFC again and it mostly makes sense surrounding
>> boundaries. I still have to talk about diamond operator and constructor
>> generic type.
>>
>>
>> []s,
>>
>>
>> On Tue, Apr 26, 2016 at 4:15 PM, Robert Stoll <p...@tutteli.ch> wrote:
>>
>> >
>> >
>> > > -----Ursprüngliche Nachricht-----
>> > > Von: Rasmus Schultz [mailto:ras...@mindplay.dk]
>> > > Gesendet: Montag, 25. April 2016 18:09
>> > > An: Josh Di Fabio
>> > > Cc: Dominic Grostate; Guilherme Blanco; Mathieu Rochette; Ben Scholzen
>> > 'DASPRiD'; Sara Golemon; PHP internals; Mathieu
>> > > Rochette
>> > > Betreff: Re: [PHP-DEV] [RFC:generics]
>> > >
>> > > > I really don't like 'as' in this context, even if Hack uses it, as
>> it
>> > > > doesn't reflect in English terms what the code is doing. As others
>> > > > have already said, it reads as if 'T' is being aliased to 'Bar'.
>> > >
>> > > I second that.
>> > >
>> > > I hear the concerns about adding another reserved word "is" though, so
>> > I'd like to suggest simply using a ":" ... as in:
>> > >
>> > >     class A<T : T1> { ... }
>> >
>> > In this case I would suggest to use class A<T <: T1> which leaves room
>> > open to define lower bounds later on (either with <: as well or with :>
>> as
>> > in scala)
>> >
>> > >
>> > > Consistent with return type-hints, it should feel like home?
>> > >
>> > > For sure nobody wants to type out "instanceof", and (as pointed out in
>> > the RFC) the instanceof operator checks the type of
>> > > an object, which is *not* what this is doing - a type argument is not
>> an
>> > "instance of" anything. The ":" is more neutral in that
>> > > regard maybe?
>> > >
>> > >
>> > > On Thu, Apr 21, 2016 at 10:32 AM, Josh Di Fabio <
>> joshdifa...@gmail.com>
>> > wrote:
>> > > > On Wed, Apr 20, 2016 at 8:17 PM, Dominic Grostate
>> > > > <codekest...@googlemail.com> wrote:
>> > > >> Thanks for you're input everyone.
>> > > >>
>> > > >> So far, we have read some ideas for handling upper bounds, or
>> > > >> multiple there of.
>> > > >> The preferred keywords appear to be either "as" or "instanceof".
>> > > >>
>> > > >> class Foo<T as Bar> {}
>> > > >> class Foo<T instanceof Bar> {}
>> > > >>
>> > > >> We would like to know for sure then if everyone is largely against
>> > > >> the addition of an "is" keyword, in favour of one of the other two.
>> > > >>
>> > > >
>> > > > I really don't like 'as' in this context, even if Hack uses it, as
>> it
>> > > > doesn't reflect in English terms what the code is doing. As others
>> > > > have already said, it reads as if 'T' is being aliased to 'Bar'.
>> > > >
>> > > > On Wed, Apr 20, 2016 at 8:17 PM, Dominic Grostate
>> > > > <codekest...@googlemail.com> wrote:
>> > > >> Thanks for you're input everyone.
>> > > >>
>> > > >> So far, we have read some ideas for handling upper bounds, or
>> > > >> multiple there of.
>> > > >> The preferred keywords appear to be either "as" or "instanceof".
>> > > >>
>> > > >> class Foo<T as Bar> {}
>> > > >> class Foo<T instanceof Bar> {}
>> > > >>
>> > > >> We would like to know for sure then if everyone is largely against
>> > > >> the addition of an "is" keyword, in favour of one of the other two.
>> > > >>
>> > > >> ----------------
>> > > >>
>> > > >> There is also a desire to include unions and intersections.
>> > > >> Presently though, this feature feels tied in with
>> > > >> https://wiki.php.net/rfc/union_types meaning if union types are
>> > > >> approved, then generics would have to support them as well.
>> Likewise
>> > > >> if this feature becomes approved in generics, it would make sense
>> to
>> > > >> support them in regular type hints as well.
>> > > >>
>> > > >> ----------------
>> > > >>
>> > > >> The RFC makes a reference to generic closures, which may look
>> > > >> something like
>> > > >> this:
>> > > >>
>> > > >> function my_function(callable<Foo, Bar> $func) {
>> > > >>
>> > > >> }
>> > > >>
>> > > >> However, an RFC already exists which is very similar to this
>> feature
>> > > >> at https://wiki.php.net/rfc/callable-types
>> > > >> As it currently standards these RFCs appear incompatible with each
>> > > >> other (please correct me if I am wrong).
>> > > >>
>> > > >> My question about this is would you prefer the generics RFC exclude
>> > > >> this part in favour of a separate or later RFC.
>> > > >> Initially the proposal included generic arrays "array<string>".
>> > > >> However to ease the implementation it was decided that should be a
>> > separate feature.
>> > > >> So we'd like to find out if everyone else feels the same way about
>> > > >> callable types.
>> > > >>
>> > > >> ----------------
>> > > >>
>> > > >> This RFC currently doesn't specify in detail how reflection would
>> > > >> work.  We have attempted a few API designs, but due to generic
>> > classes being ...
>> > > >> generic, it is difficult to find a suitable way to glean
>> information
>> > > >> about a class in a backwards compatible manner.  So we will need
>> some
>> > > >> help on this one.
>> > > >>
>> > > >> -----------------
>> > > >>
>> > > >> Aside from these top issues on our own list, however does everyone
>> > > >> feel about the proposal in general?
>> > > >> As the RFC is still in draft, we will continue to make changes to
>> it
>> > > >> as more popular idea pop up, so please continue.
>> > > >>
>> > > >> Thanks.
>> > > >>
>> > > >> PS: I wasn't properly subscribed to the mailing list, so I missed a
>> > > >> few important messages that were mailed directly to internals, but
>> > > >> hopefully I've managed to fix that now.
>> > >
>> > > --
>> > > PHP Internals - PHP Runtime Development Mailing List To unsubscribe,
>> > visit: http://www.php.net/unsub.php
>> >
>> >
>> >
>>
>>
>> --
>> Guilherme Blanco
>> Lead Architect at E-Block
>>
>
>


-- 
Guilherme Blanco
Lead Architect at E-Block

Reply via email to