Review Request: CR#8001634 : Initial set of lambda functional interfaces
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:
- 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/
>
More information about the lambda-libs-spec-observers
mailing list