Function type naming conventions

Ali Ebrahimi ali.ebrahimi1781 at gmail.com
Thu Jan 3 14:13:08 PST 2013


Hi,

  FunctionInt<T>         T -> int
  IntFunction<R>         int -> R
  SupplierInt            () -> int
  BiFunctionInt<T,U>     (T,U) -> int
  IntTBiFunctionInt<T>     (int,T) -> int
  TIntBiFunctionInt<T>     (T,int) -> int
  IntBinaryOperatorInt(IntIntFunctionInt)      (int,int) -> int
  IntBlock               int -> void

just as OptionalInt. This is just general convention that is
consistent and predictable and readable.

But other option:

  Function.OfT2Int<T>         T -> int
  Function.OfInt2R<R>         int -> R
  Supplier.Of2Int            () -> int
  BiFunction.OfTU2Int<T,U>     (T,U) -> int
  BiFunction.OfIntT2Int<T>     (int,T) -> int
  BiFunction.OfTInt2Int<T>     (T,int) -> int
  BinaryOperator.OfInt2Int     (int,int) -> int
  Block.OfInt               int -> void

Regards,
Ali

On 1/2/13, Brian Goetz <brian.goetz at oracle.com> wrote:
> Just to recap where we are in function type naming, we've got a few base
> types:
>
>    Block<T>               T -> void
>    Function<T,R>          T -> R
>    Predicate<T>           T -> boolean
>    Supplier<T>            () -> T
>
> Plus some derived convenience types:
>
>    UnaryOperator<T>       extends Function<T,T>
>    BinaryOperator<T>      extends BiFunction<T,T,T>
>
> We have arity prefixes to modify the natural arity of these:
>
>    BiFunction<T,U,R>      (T,U) -> R
>    BiPredicate<T,U>       (T,U) -> boolean
>
> Presumably we'll be forced into TriXxx and worse at some point, but so
> far we've been able to avoid that.
>
> We have a primitive specialization convention that lets you prefix
> {Int,Long,Double,Boolean} on front of one of these (possibly multiple
> times), and this gobbles the type argument that appears in the return
> position, or, if the return is not generic, the first type argument:
>
>    IntFunction<T>         T -> int
>    IntSupplier            () -> int
>    IntBiFunction<T,U>     (T,U) -> int
>    IntBinaryOperator      (int,int) -> int
>    IntBlock               int -> void
>
> So far we've got about 30 defined SAMs, and this has been mostly enough
> to implement our libraries, including primitive specializations.
>
> This convention is an uneasy compromise that is part and parcel of the
> compromise/commitment we made to nominal function types.  Its a bit
> annoying in places, but the rules above are consistent, and the names
> read mostly reasonably in APIs, and better than most of the alternatives
> proposed, especially the fully general Function$FromIntAndDouble$ToDouble.
>
> In fact, the only type we've come across repeatedly that wants a "nice"
> name that doesn't fit into the above scheme is:
>
>    int -> T
>
> which shows up in quite a few places.  There are probably a few others
> but this is the biggest.  (We also came across a desire for (T,int)->T
> in the reducer work, but that shows up in only one place.)
>
> We could treat int -> R as a specialization of Function<T,R>, and extend
> the naming convention to handle it, or we could try to come up with a
> new top-level name for it.
>
> In the latter category, IndexedSupplier<T> would work for some of the
> use cases (Arrays.fill, array suppliers) but not terribly well for
> IntStream.map(int -> T).
>
> Other ideas?
>


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