Review Request: CR#8001634 : Initial set of lambda functional interfaces (original) (raw)

Brian Goetz brian.goetz at oracle.com
Fri Nov 2 12:32:29 PDT 2012


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:

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 is a specialization of Mapper<R,T>, and IntBinaryOperator is a specialization of BinaryOperator. - 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 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/



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