RFR: 8015317: Optional.filter, map, and flatMap
Jed Wesley-Smith
jed at wesleysmith.io
Mon Jul 15 00:17:08 PDT 2013
ignore me, you do actually need both ? extends on the type constructor and
the inner type – dunno what I was thinking.
On 15 July 2013 13:02, Jed Wesley-Smith <jed at wesleysmith.io> wrote:
> I'm not entirely sure that is a problem, have a look at the following:
>
> https://gist.github.com/jedws/5993596#file-variancetest-java
>
> it is only the one with a covariance annotation on the parameter that
> fails…
>
>
> On 15 July 2013 12:52, Zhong Yu <zhong.j.yu at gmail.com> wrote:
>
>> Another example of possible missing a wildcard
>>
>>
>> http://gee.cs.oswego.edu/dl/jsr166/dist/docs/java/util/concurrent/CompletionStage.html#thenCompose%28java.util.function.Function%29
>>
>> thenCompose(Function<? super T,? extends CompletionStage<U>> fn)
>>
>> should be
>>
>> thenCompose(Function<? super T,? extends CompletionStage<? extends U>>
>> fn)
>>
>> The problem is probably wide spread, and we need a tool to find these
>> mistakes.
>>
>> 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