Abbreviated wildcard syntax in Javadoc?

Zhong Yu zhong.j.yu at gmail.com
Sun Jul 14 19:33:31 PDT 2013


Wildcards are becoming increasingly unintelligible when Java is going
functional. If we need something like

    Function<A, Function<B, C>>

we have to spell it out as

    Function<? super A, ? extends Function<? super B, ? extends C>>

Seriously, who can read that? I can only hope that in private Java is
deeply embarrassed by it and will do something about it asap.

Meanwhile, can we display wildcards in javadoc in an unobtrusive way,
so that readers of APIs do not have their eyeballs exploding?

Zhong Yu




On Sun, Jul 14, 2013 at 9:24 PM, Zhong Yu <zhong.j.yu at gmail.com> wrote:
> X<Y<Child>> is not a subtype of X<Y<? extends Parent>>. We have to go
> wildcard all the way - X<? extends Y<? extends Parent>>.
>
> The subtyping rules don't care about final-ness of types. For example,
> X<String> is a distinct type from X<? extends String>, even though
> String has only one subtype (itself).
>
> Zhong Yu
>
> On Sun, Jul 14, 2013 at 8:04 AM, Jed Wesley-Smith <jed at wesleysmith.io> wrote:
>> (accidentally didn't post to the list)
>>
>>> You probably know that the example provided is not completed ported to
>> work with our Optional implementation,
>>
>> It should be, for the example I wrote an Optional that is final and should
>> be otherwise identical. It should certainly be fairly easy for any
>> committer to try. If you can make it work without the ? extends Optional
>> I'd love an explanation of how.
>>
>>> and fugue works around the type system with Option as abstract class.
>>
>> As I've tried to explain, this isn't about the implementation of the
>> container class, but how covariance works with a parameterised class.
>>
>> We originally had the non-, but in a discussion with Brian he alerted us to
>> the fact that the signature was wrong. We hastily fixed it:
>>
>> https://bitbucket.org/atlassian/fugue/commits/9eca663326a5baeb8f23974732ec585d5627a05c
>>
>> To further demonstrate, I give you a minimal example of a final Optional
>> implementation that does not compile for this test:
>>
>> https://gist.github.com/jedws/5993596#file-gistfile1-java-L57
>>
>> cheers,
>> jed.
>>
>>
>>
>> On 14 July 2013 15:02, Henry Jen <henry.jen at oracle.com> wrote:
>>
>>>  I think I understand what you are saying. However, unless we make
>>> Optional not final, the extends part just doesn't matter.
>>>
>>> You probably know that the example provided is not completed ported to
>>> work with our Optional implementation, and fugue works around the type
>>> system with Option as abstract class.
>>>
>>> Cheers,
>>> Henry
>>>
>>>  On Jul 13, 2013, at 4:35 PM, Jed Wesley-Smith <jed at wesleysmith.io><jed at wesleysmith.io>wrote:
>>>
>>>  I did supply a test that you can use to try it.
>>>
>>>  What we are talking about is whether type Box<Parent> is substitutable
>>> by Box<Child> in the contravariant position. Intuitively we think we only
>>> need Box<? extends Parent> because we only care about the type parameter,
>>> but the type – as you point out – is actually different. Box<Parent> is not
>>> "inherited by" Box<Child>.
>>>
>>>  Specifically, if we have a consuming Box, and we replace it with a Box
>>> of a more specific type parameter, we could attempt feed the more general
>>> type into it, ie. a Box<Child> isn't going to appreciate having Parent fed
>>> to it. This is why covariance and mutable containers don't mix well, and
>>> why Java's covariant arrays are problematic.
>>>
>>>  In this situation we have an immutable container, and we can substitute
>>> the type of our container with one of a more specific type, as it will only
>>> ever supply a value – and a value of Child will suffice as a Parent. So,
>>> for this case we need a Box that is substitutable, and therefore we need to
>>> add the covariance to our box.
>>>
>>>  <? extends Box> is simply adding covariance to our Box type.
>>>
>>>  For a much better explanation than I can give about this, see this
>>> excellent post describing generics in Scala, which – apart from have
>>> declaration-site variance and using [A] in place of <A> – generally follow
>>> the same pattern:
>>>
>>>
>>> http://termsandtruthconditions.herokuapp.com/blog/2012/12/29/covariance-and-contravariance-in-scala/
>>>
>>>  cheers,
>>> jed.
>>>
>>>
>>> On 14 July 2013 04:49, Henry Jen <henry.jen at oracle.com> wrote:
>>>
>>>> I think the type you talking about here is Optional<? extends U> instead
>>>> of ? extends Optional<U>.
>>>>
>>>>  IIRC, Optional<? extends U> is not a subtype of Optional<U>, just like
>>>> any other Collection class. List<Child> is not a List<Parent>.
>>>>
>>>>  Cheers,
>>>> Henry
>>>>
>>>>
>>>>  On Jul 13, 2013, at 3:15 AM, Jed Wesley-Smith <jed at wesleysmith.io>
>>>> wrote:
>>>>
>>>>  > The ? extends Optional is unnecessary in flatMap as Optional is final.
>>>>
>>>>  interestingly enough, it actually is.
>>>>
>>>>  try the following test:
>>>>
>>>>  class OptionalTest {
>>>>   class Parent {};
>>>>
>>>>    class Child extends Parent {};
>>>>
>>>>    @Test public void covariantReturn() {
>>>>     Optional<Parent> some = some(new Parent());
>>>>     Function<Parent, Optional<Child>> f = new Function<Parent,
>>>> Optional<Child>>() {
>>>>       @Override public Optional<Child> apply(Parent p) {
>>>>         return some(new Child());
>>>>       }
>>>>     };
>>>>     Optional<Parent> mapped = some.<Parent> flatMap(f);
>>>>     assertThat(mapped.get(), notNullValue());
>>>>   }
>>>> }
>>>>
>>>>  adapted from the fugue test suite:
>>>>
>>>>
>>>> https://bitbucket.org/atlassian/fugue/src/96a65067fb7aaf1edae1bffa07167a5865cbebec/src/test/java/com/atlassian/fugue/OptionTest.java#cl-155
>>>>
>>>>  The point to remember is that Optional<Child> is a type and as such is
>>>> actually a subtype of Optional<Parent> –  and therefore requires a
>>>> covariant return.
>>>>
>>>>  cheers,
>>>> jed.
>>>>
>>>>
>>>>
>>>>
>>>> On 13 July 2013 04:15, Mike Duigou <mike.duigou at oracle.com> wrote:
>>>>
>>>>> The ? extends Optional is unnecessary in flatMap as Optional is final.
>>>>> Otherwise this looks good.
>>>>>
>>>>> Mike
>>>>>
>>>>> On Jul 5 2013, at 14:37 , Henry Jen wrote:
>>>>>
>>>>> > Hi,
>>>>> >
>>>>> > Please review the webrev at
>>>>> >
>>>>> > http://cr.openjdk.java.net/~henryjen/ccc/8015317.0/webrev/
>>>>> >
>>>>> > Which adds following method to Optional,
>>>>> >
>>>>> > public static <T> Optional<T> ofNullable(T value) {}
>>>>> > public Optional<T> filter(Predicate<? super T> predicate) {}
>>>>> > public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {}
>>>>> > public<U> Optional<U> flatMap(Function<? super T, ? extends
>>>>> Optional<U>>
>>>>> > mapper) {}
>>>>> >
>>>>> > Also included is some cleanup on javadoc.
>>>>> >
>>>>> > Cheers,
>>>>> > Henry
>>>>>
>>>>>
>>>>>
>>>>
>>>>
>>>
>>>
>>


More information about the lambda-dev mailing list