PRE-PROPOSAL: Extension methods

Reinier Zwitserloot reinier at zwitserloot.com
Wed Mar 18 12:11:55 PDT 2009


In my opinion, Extension Methods and Static Methods in Interfaces  
augment each other nicely. You can stuff your Collections.sort()  
methods in the more appropriate List interface, and then static import  
them for seamless sorting:

import java.util.List;
import static java.util.List.sort;

public void foo() {
     someList.sort();
}


However, I considered Extension Methods a bit too complicated for  
Project Coin, and therefore submitted SMI because it seemed simple  
enough. Extension Methods can always be added in java8. One could even  
argue then that extension methods in a type that extend themselves  
(such as sort(this List foo) in java.util.List) are 'auto-imported',  
or at the very least, IDEs can suggest them as normal and auto-add the  
import static java.util.List.sort() statement. We don't need to  
consider this now, just acknowledge that we have the option when its  
time to think about java8 language additions.  The big advantage to  
having both SMI and EM at that point is IDEs, which the vast majority  
of java programmers use. An IDE can quite easily suggest EMs from the  
type you're auto-completing on, and if you pick one, silently add the  
import statement to make it work.

Contrast this to just having EMs: Either:

  A) The IDE needs to scan every class file in every jar on the entire  
classpath / in every imported module just to build a list of EMs which  
can then be suggested, -or-

  B) types need an annotation to point at a class that contains EMs.  
This would be a unique move for java; An annotation that is only there  
to help IDEs; javac can't do anything with it, other than perhaps  
suggest import statics ("list.sort(); ^^^ did you mean to static  
import java.util.Collections.sort?") -or-

  C) IDEs need to make arbitrary rules, such as "I'll only search for  
EMs within the same package/module as the type".


Most of those get more complicated because any auto-complete needs to  
search multiple type (all parent types of the expression's calculated  
type).

If Extension Methods are in scope for project coin, I'd love to see a  
proposal, and I would encourage *both* SMI and EM to be accepted. The  
sum would be greater than the parts.

  --Reinier Zwitserloot



On Mar 18, 2009, at 18:23, Neal Gafter wrote:

> On Tue, Mar 17, 2009 at 11:56 PM, Kevin Krouse  
> <kevin.krouse at gmail.com> wrote:
>> I'm interested in extension methods.
>
> I'll write up a full proposal if I have any indication it's something
> Joe/Sun(/IBM) would consider for project Coin.  The basic idea would
> work like this:
>
> Within a static method, you can use "this" as an new qualifier on the
> first method parameter, which must be a reference type.  This would be
> reflected in the class file format as either a new flag, or a new
> classfile attribute ("ExtensionMethod") on the method.
>
> When an extension method has been statically imported, you can use it
> as if it is a member of the type of its first argument.  The name
> lookup rules for a method invocation
>
> o.f(...)
>
> are augmented as follows.  When identifying candidates for overload
> resolution, if no accessible candidates of the correct name are found
> as a member of the static type of the receiver (JLS 15.12.1 and
> 15.12.2), then we consider as candidates those statically imported
> methods with name f, and perform the overload resolution among them as
> if the invocation had been written
>
> f(o, ...)
>
> This is backward compatible, as it assigns meanings to expressions
> that were previously errors, and does not change the meaning of code
> that was not previously an error.
>
> There are a number of benefits to this approach.  A large number of
> static utility class members can and probably should be retrofitted to
> use extension methods, making it possible to use a much more
> convenient syntax for common operations.
>
>    import static java.util.Collections.sort;
>    List<Integer> list = ...
>    list.sort(); // uses Collections.sort extension method
>
> Similarly, it allows extension methods to operate on arrays
>
>    import static java.util.Arrays.sort;
>    String[] strings = ...
>    strings.sort(); // uses Arrays.sort extension method
>
> The syntactic convenience of this is greater (i.e. code becomes more
> readable) when multiple invocations work together in an expression.
>
> One of the more important benefits of this approach is that it enables
> future language changes to be defined by syntactic translation, while
> allowing more flexible retrofitting of those language changes onto
> existing APIs than would be possible without extension methods.  For
> example, one could define an ARM construct by translation of something
> like
>
> protected (expression) statement
>
> into
>
> {
> Type1 $t1 = expression
> Type2 $t2 = $t1.protectedStart();
> try {
>    statement
> } finally {
>    $t2.protectedEnd();
> }
> }
>
> (with appropriate inversion of suppressed exceptions, if you please).
>
> Then, to add support for this new ARM construct to some particular API
> you would either add these methods to the API or define extension
> methods.  If done using extension methods or final instance methods,
> they are likely to be inlined by HotSpot if used in frequently
> executed code, so the performance overhead is vanishingly small.
> Since extension methods can be added even to existing interfaces
> without breaking compatibility, such an ARM construct could be
> retrofitted onto many more APIs than the currently proposed construct.
> It could easily be retrofitted onto java.util.concurrent.locks.Lock,
> for example.
>
> See also http://www.javac.info/ExtensionMethods.html




More information about the coin-dev mailing list