Review request for initial lambda functions and utils

Kevin Bourrillion kevinb at
Tue Aug 9 15:54:35 PDT 2011

On Tue, Aug 9, 2011 at 3:32 PM, Rémi Forax <forax at> 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

> 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> 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>
>>  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

Kevin Bourrillion @ Google
Java Core Libraries Team

More information about the lambda-dev mailing list