Function type naming conventions
Brian Goetz
brian.goetz at oracle.com
Wed Jan 23 13:20:05 PST 2013
Will do the first part tomorrow unless someone strongly objects.
Open issues:
- Where multiple rules apply, do we prefer XY or XToY?
- Do we like the "drop the arity prefix in case all are specialized"
rule tweak?
On 1/23/2013 3:19 PM, Sam Pullara wrote:
> Awesome, this is where I hoped we would end up on this.
>
> Thanks,
> Sam
>
> On Jan 23, 2013, at 12:11 PM, Brian Goetz <brian.goetz at oracle.com
> <mailto:brian.goetz at oracle.com>> wrote:
>
>> Returning to this....
>>
>> Recall that the primary goal in choosing SAM names is user ergonomics.
>> Not only do we want to make things clear, but we want to assign the
>> simple names to the most commonly used configurations. Hence
>> "Function<T,U>" instead of "ObjectToObjectFunction". A secondary goal
>> is for the names to be mechanically derivable from a reasonably small
>> set of rules.
>>
>> To recap where we are:
>>
>> Base types, each with their own natural arity:
>>
>> 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>
>>
>> Plus arity prefixes to modify the natural arity of these:
>>
>> BiFunction<T,U,R> // (T,U) -> R
>> BiPredicate<T,U> // (T,U) -> boolean
>>
>> We have a primitive specialization convention that lets you prefix
>> {Int,Long,Double,Boolean,Obj} on front of one of these (possibly
>> multiple times). In accordance with our ergonomics goal, we want
>> simple specializations for those that specalize return type, since
>> that has been the most common specialization. (Obj is used when you
>> want to specialize later type params.)
>>
>> We first tried ordering the type parameters return-type-first, so that
>> partial specialization could proceed left-to-right. This went over
>> like a lead balloon. So we then adopted the rule that we specialize
>> return type first when the return type is generic, and otherwise
>> left-to-right. This means that
>>
>> IntFunction<T>
>>
>> is a function T -> int. This seemed attractive as T -> int was far,
>> far more common than int -> T.
>>
>> But this special treatment introduces anomalies. For example, this
>> rule would (probably) assign
>>
>> IntDoubleFunction
>>
>> for double -> int, whereas users will probably expect IntDouble
>> function to correspond to int -> double based on left-to-right. There
>> are ways to further complicate the mapping to avoid this but that just
>> moves the anomalies into darker corners.
>>
>> Based on offline discussions with Kevin and Joe, we concluded that
>> backing off slightly from our desire to have the shortest possible
>> name for the most common specialization can yield a more consistent
>> naming scheme while still being acceptably ergonomic.
>>
>> So, new proposal:
>>
>> - When specializing return type, prefix "ToXxx"
>> - Otherwise specializations gobble type arguments left-to-right.
>>
>> So:
>>
>> Function<T,U> // T -> U
>> DoubleFunction<T> // double -> T
>> ToIntFunction<T> // T -> int
>> DoubleToIntFunction // double -> int
>>
>> This also means there is more than one way to represent the same thing
>> in some cases. For example, also consistent with these rules are:
>> DoubleIntFunction // double -> int
>> since this covers all the type arguments.
>>
>> Only Function and Supplier are generic in return, so specializations
>> of Block and Predicate would not be affected by the new "To" rule.
>>
>> This scheme is simpler and has fewer anomalies. The casualty is that
>> IntFunction becomes ToIntFunction -- arguably clearer, and only
>> slightly more verbose -- overall seems a win.
>>
>> Here's how the current SAMs would be affected:
>>
>> IntFunction<T>
>> ToIntFunction<T>
>> IntBiFunction<T,U>
>> ToIntBiFunction<T,U>
>> IntBlock
>> not affected
>> IntBinaryOperator
>> not affected
>> IntPredicate
>> not affected
>> IntSupplier
>> ToIntSupplier
>> alternately, not affected
>> IntUnaryOperator
>> not affected
>> ObjIntBiBlock
>> not affected
>> ObjIntFunction
>> IntToObjFunction
>> alternately, IntObjFunction
>>
>>
>> A possible (orthogonal) tweak to this system would be:
>> - When there are enough specializations to cover all arguments, omit
>> the arity prefix
>>
>> This would turn ObjIntBiBlock into ObjIntBlock. Some more
>> investigation would be required to ensure there are no collisions here.
>
More information about the lambda-libs-spec-observers
mailing list