Review Request: CR#8001634 : Initial set of lambda functional interfaces

Kevin Bourrillion kevinb at google.com
Fri Nov 2 13:46:22 PDT 2012


A few Googlers, myself included, have expressed surprise that Block accepts
a value. There's nothing in the word "block" that suggests this to me -- no
semantic basis on which to distinguish 'block' from 'runnable'. We call
this type Receiver<T>. That name has a more complementary nature with
Supplier. Have we considered it?

On Fri, Nov 2, 2012 at 12:32 PM, Brian Goetz <brian.goetz at oracle.com> wrote:

> Gathering the feedback we've gotten so far:
>
> 1.  Factory.  People seem comfortable renaming Factory to Supplier; as a
> bonus (or not), IntSupplier specializations make more sense when connected
> to Supplier than Factory (how do you make new ints?)
>
> 2.  Mapper.  I agree with Doug's complaint that Mapper is too specialized,
> especially as it is probably the most useful shape of function and will be
> used in places that have nothing to do with mapping.  While I've resisted
> "Function" for a long time (and will continue to resist
> Function1..FunctionN), its not clear that there are significantly better
> alternatives.
>
> 2a.  IMO Fun or Func are *not* better alternatives.  The extra few
> characters are not an impediment, and would be inconsistent with the other
> naming conventions we're adding here.
>
> 2b.  The reason I've resisted Function* is that is kind of gives up one of
> the few benefits of nominal function types.  Structural function types are
> clearly "better", except that erased structural function types are clearly
> awful.  So nominal function types are the best we can do here.  Nominal
> function types have two advantages to offset their many disadvantages:
>  - Type names are useful and informative, especially in API signatures
>  - The libraries are already full of nominal function types like Runnable
> and Comparator, so adding more does not create a bifurcation between "old
> libraries" and "new libraries".
>
> Going full-hog to Function1..FunctionN (for an ever-increasing N)
> basically says "let's take all the disadvantages of nominal types, and none
> of the advantages."  API signatures that have nothing but Function1 and
> Function2 in them are unlikely to be very informative.
>
> Guava managed to get away with only Function and a few other SAMs, and not
> need to go much further, so it is a possible candidate for recasting
> Mapper, though I still don't like the slippery slope.  Would like something
> better, but Mapper probably isn't it.
>
>
> So if we adopt the above we'd have:
>
> {Int,Long,Double}?Predicate:      T -> boolean
> {Int,Long,Double}?Function:       T -> U
> {Int,Long,Double}?Block:          T -> void
> {Int,Long,Double}?**UnaryOperator:  T -> T
> {Int,Long,Double}?Supplier:       () -> T
> {Int,Long,Double}?{Binary,**Unary}Operator
>
>
> As to the arity modifiers (which will come in the next round), it seems
> likely we'll want the equivalent of
>
> Bi{Predicate,Function,Block}
>
> Does the Bi/Tri convention scale sufficiently?  Is the "inconsistency"
> (which I don't really think is an inconsistency) with BinaryOperator
> excessively bothersome?
>
>
>
> On 10/31/2012 4:16 PM, Mike Duigou wrote:
>
>> There's a large set of library changes that will be coming with Lambda.
>> We're getting near the end of the runway and there's lots left to do so we
>> want to start the process of getting some of the more stable pieces put
>> back to the JDK8 repositories.  We've spent a some time slicing things into
>> manageable chunks. This is the first bunch. We'd like to time-box this
>> review at one week (until Nov. 7th), since there are many more pieces to
>> follow.
>>
>> The first chunk is the basic set of functional interface types.  While
>> this set is not complete, it is enough to be able to proceed on some other
>> pieces.  This set contains no extension methods (we'll do those separately)
>> and does not contain all the specializations we may eventually need.
>>
>> Doug has also suggested we have some sort of regularized, low-level
>> naming scheme.  There's nothing in this bunch that is inconsistent with
>> that; if we had such a thing, the nominal SAMs here could easily implement
>> the horribly named low-level versions.  We're still thinking about how that
>> might fit in, so while that's not directly reflected here, it hasn't been
>> forgotten.
>>
>> The specification is limited; most of the interesting restrictions
>> (side-effect-freedom, idempotency, stability) would really be imposed not
>> by the SAM itself by by how the SAM is used in a calculation. However, some
>> common doc for "how to write good SAMs" that we can stick in the package
>> doc would be helpful. Suggestions welcome.
>>
>> Elements of this naming scheme include:
>> - Each SAM type has a unique (arity, method name) pair.  This allows SAMs
>> to implement other SAMs without collision.
>> - The argument lists are structured so that specializations act on the
>> first argument(s), so IntMapper<T> is a specialization of Mapper<R,T>, and
>> IntBinaryOperator is a specialization of BinaryOperator<T>.
>> - Multi-arg versions use prefix BiXxx, TriXxx, as suggested by Doug.
>> However, the "natural" arity varies.  No good two or three letter prefix
>> for zero or one comes to mind (e.g., UnaryFactory<T> or NilaryBlock (though
>> that's the same as Runnable.)  So that could be improved.
>>
>> Please review and comment.
>>
>> http://cr.openjdk.java.net/~**mduigou/8001634/2/webrev/<http://cr.openjdk.java.net/~mduigou/8001634/2/webrev/>
>>
>>


-- 
Kevin Bourrillion | Java Librarian | Google, Inc. | kevinb at google.com


More information about the lambda-libs-spec-observers mailing list