Review request for initial lambda functions and utils
Kevin Bourrillion
kevinb at google.com
Tue Aug 9 15:54:35 PDT 2011
On Tue, Aug 9, 2011 at 3:32 PM, Rémi Forax <forax at univ-mlv.fr> wrote:
Let's take an example, Predicates.compose is declared like this:
> <A,B> Predicate<A> compose(Predicate<B> predicate, Function<A, ? extends
> B> function)
>
> Basically, your signature works in most of the cases because
> you rely on the compiler to infer of A and B but there are some known
> cases
> by example if compose is called as a parameter of another method call
> where the inference is not done by the compiler.
>
What we've tried to do is ensure that A and B can be inferred directly from
the parameters given without having to rely on the method return value being
directly assigned to a variable from which the type information could be
gleaned.
> If the compiler don't do any inference, the easy workaround
> is to provide a type argument for A and for B,
> but with your API, it will not work.
>
> void foo(Predicate<String> p) { ... }
>
You've lost me right there. That needs to be Predicate<? super String>.
> ...
> Predicate<String> p = ...
> Function<Object, String> f = ...
> foo(Predicates.compose(p, f)) // doesn't compile, Ok cf Java spec
>
Just fix foo() and this works. No explicit type parameters needed.
It would be improper for compose(p, f) to return a Predicate<String> because
a Predicate<Object> is *what it is*. It's a predicate that's capable of
handling any object. There are very rare circumstances (well, rare when
APIs are designed correctly) where you are forced to "pretend" that a
Predicate is less capable than it really is. Cast-and-suppress is a
perfectly reasonable escape valve for those situations.
> foo(Predicates.<String,String>compose(p, f)) // doesn't compile too ??
>
>
> but I can easily say that your compiler sounds like anything but a *
> typical* user project, which JDK APIs should be tailored to.
>
>
> An API should work :)
>
> Rémi
>
>
>
>
> On Tue, Aug 9, 2011 at 1:31 PM, Rémi Forax <forax at univ-mlv.fr> wrote:
>
>> On 08/09/2011 08:29 PM, Kevin Bourrillion wrote:
>> > (I have yet to look at the code because I'm new to this group and don't
>> know
>> > where to find it.)
>> >
>> >
>> > On Tue, Aug 9, 2011 at 9:55 AM, Colin Decker<cgdecker at gmail.com>
>> wrote:
>> >
>> >> I'm curious about cases such as Predicates.IS_NULL and
>> Predicates.isNull()
>> >> where there is both a public constant of type Predicate<Object> and a
>> >> public
>> >> method that returns Predicate<T>. For one thing, I find the existence
>> of
>> >> both fields and methods for these standard functions kind of awkward,
>> >> particularly when there's both a field and a method for the same thing.
>> For
>> >> another, is it really a good idea to provide a method returning a
>> >> Predicate<Object> as a Predicate<T>? I realize there are many people
>> who
>> >> don't really get wildcards, but should the standard libraries cater to
>> >> methods declared to take Predicate<T> where they should take
>> Predicate<?
>> >> super T>? Or is there some other reason for this?
>> >
>> > I strongly recommend that Predicates.isNull() NOT follow Guava's example
>> > here. Return a Predicate<Object>. Users who want it to return
>> Predicate<T>
>> > are trying to get away without using the wildcards on their method
>> > signatures that the language really dictates they *must*. They always
>> have
>> > the option to cast-and-suppress if they get into a pickle (we call that
>> a
>> > "safe contravariant cast", provided that the user is certain the
>> predicate
>> > can never be subsequently cast to any type that is *not* contravariant
>> on
>> > T).
>> >
>> > 90% of Guava's APIs use wildcards and type parameters "judiciously" --
>> only
>> > when they are needed so as to *allow a method to be invoked* in all the
>> > circumstances it should be -- but do not add extra wildcards and type
>> > parameters that *also* allow the user to "massage" the return type of
>> the
>> > method just because they want to. I have never regretted this approach
>> > (although I do sometimes regret having to explain it over and over and
>> > over).
>> >
>>
>> Hi Kevin,
>> You have to know that I've lost several Karma point because of you.
>>
>> Last year, I had to write a compiler for a DSL used to abstract some
>> graphs
>> with a runtime based on Guava.
>> It was so painful to generate Java codes that use Guava that
>> we eventually switch to another library.
>> The DSL was statically typed so it was easy to know the type of each
>> expression but
>> because Guava doesn't work if you set explicitly the type arguments,
>> I had to rely on the inference mechanism of javac
>> (in fact the one specified in the Java spec) which as you know has some
>> holes
>> At some points, the code to try to explain to Guava which types I wanted
>> was bigger than all other parts of the compiler, I just give up
>> and use a simpler API.
>>
>> The Java generics spec is already complex so why creating an API
>> which is harder to use by putting some extra fences.
>>
>> Rémi
>>
>>
>>
>
>
> --
> Kevin Bourrillion @ Google
> Java Core Libraries Team
> http://guava-libraries.googlecode.com
>
>
>
--
Kevin Bourrillion @ Google
Java Core Libraries Team
http://guava-libraries.googlecode.com
More information about the lambda-dev
mailing list