apply (original) (raw)
Brian Goetz brian.goetz at oracle.com
Sun Dec 16 18:07:43 PST 2012
- Previous message: apply
- Next message: apply
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
OK, let's try to get this all in one place. Mostly a defense of the status quo but there's some possibly good news at the end for apply fans.
Functional interfaces are special interfaces, but they are interfaces. They can be implemented with lambdas, but they can also be implemented by anonymous classes or implemented by classes with other methods. Choosing sensible method names is a key part of API design; there's a reason why we called the method in Runnable "run" and not "apply". Run is a more descriptive name. One could design a library where all methods are named "Harold", but it would be hard to write and hard to use. And there are likely to be functional interfaces where "apply" is an outright terrible name for what the thing does, and the "all same" rule will feel pretty constraining.
Choosing nominal function types was a compromise -- a big one. Structural function types are better than nominal ones in almost every way. (Reminder: we went this way because erased and always-boxed structural function types would really suck.) One of the few advantages of nominal function types is that they have a name. Naming them all Harold seems like deciding that since we chose a route with disadvantages, we don't deserve any of the few remaining advantages.
Naming all SAM methods Harold slams the door on implementing many combinations of SAMs in a single class, or having certain SAMs extend each other. Again, in a pure functional world, the notion of implementing multiple function types doesn't make much sense. But, functional interfaces are interfaces, and objects may very well want to implement multiple functional interfaces. Naming them all Harold means that some combinations can be implemented this way, but some not, which is a half-here, half-there state of affairs.
An obvious example is:
interface SupplierOfBoxedIntegers { Integer apply(); }
interface DispenserOfInts { int apply(); }
(First of all, apply is a terrible name for this class.) But more importantly, no class can implement both, even though it might be entirely reasonable for a class IntFlinger to implement all manner of "give me an integer" methods, to maximize compatibility with / minimize needed adaptation for multiple libraries that use a dispenser of integers. If they are all called Harold, IntFlinger is out of luck.
In this example, the two functions that IntFlinger wants to implements are basically the same function modulo boxing. But, sometimes you may want to implement mutiple SAMs because their semantics are coupled through the semantics of your class. For example:
class MapMembershipArbiter<K,V> {
Map<K,V> m;
implements Predicate<K>, Function<K,V> {
boolean test(K k) { return m.containsKey(k); }
V apply(K k) { return m.get(k);
}
If both methods were named apply, you couldn't do this.
Now, you might say "that's a stupid example" (and you might be right!) But, the "all different" rule allows for the possibility that this might actually be reasonable in some configuration; the "all same" rule ensures that this can never happen.
That said, I am not unsympathetic (well, unless you don't use an IDE, in which case I'm completely unsympathetic.) I do find myself tripping over UnaryOperator.operate vs Function.apply since they're both just so functiony. And here's where there might be some good news for you. Since we currently have
interface UnaryOperator extends Function<T,T>
then it actually is quite reasonable for UnaryOperator to adopt the name from Function, since there is no way to implement UnaryOperator without implementing Function. In which case some of the offenders -- Unary/BinaryOperator -- can go away.
Similarly, SAMs of different arities can safely use the same name. So Function and BiFunction both use the same name.
On 12/16/2012 5:10 PM, Doug Lea wrote:
(Still in the midst of the painful setup allowing JDK8 j.u.c builds to track lambda-libs...) Could someone please explain clearly and compellingly why we are using different method names for all the functional forms in java.util.function instead of just "apply"? Does anyone think that other users won't find this very annoying? -Doug
- Previous message: apply
- Next message: apply
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
More information about the lambda-libs-spec-experts mailing list