Closures prototype equivalence between closures and methodrefs

Alex Buckley Alex.Buckley at Sun.COM
Wed Aug 13 10:45:08 PDT 2008


I recall you distinguished "function type" from "closure type" many 
moons ago. For my own understanding, here are some notes.

"Ideally" there would be no difference and one could say:
- A closure literal is a value and has a function type.
- A variable can store such a value and has a function type.
- Closure conversion is from a function type to an interface type
   with a single compatible method.

which would allow:

interface Foo { void m(int i, String s) throws IOException; }

doN(1, "hi", new Foo() {
   void m(int i, String s) {if (i==3) throw ...; System.out.println(s);}
});

void doN(int n, String x,
          {int, String => void throws IOException} b) {...}

Conversion from an arbitary interface type (Foo) to an arbitrary 
function type ({int, String => void throws IOException}) is hard.
VM-level interface injection could make it less hard.

Conversion from the synthetic and canonical JVM type of a closure 
literal to an arbitrary function type is not hard, since the synthetic 
type ("closure type") can be made a subtype of the target function type.

Therefore, BGGA 0.5 stratifies closure literal terms and variable terms:
- A closure literal is a value and has a closure type.
- A variable can store such a value and has a function type.
- Closure conversion is from a closure type to an interface type
   with a single compatible method.

Alex

Neal Gafter wrote:
> Subtype relationships among reference types must require no conversion 
> code. For example, converting a List<? extends Number> to a List<? 
> extends Object> requires no code.  If we support more general 
> conversions among function types I believe it ought to be implemented by 
> putting the underlying interfaces in some kind of normal form - for 
> example, using Void for the result type in the interface when the user 
> wrote void in the function type.  All that is possible, but I'm 
> reluctant to take on major changes to the spec at this stage.
> 
> Regards,
> Neal
> 
> On Wed, Aug 13, 2008 at 3:29 AM, Mark Mahieu 
> <mark at twistedbanana.demon.co.uk <mailto:mark at twistedbanana.demon.co.uk>> 
> wrote:
> 
>     I must admit that I've come close to reporting similar non-bugs,
>     because even though I *know* - having read the spec far too many
>     times - that the conversion is only applicable to closures, I've
>     found it's very easy to slip into thinking that assignment
>     compatibility works the same way for function types.  At least for
>     the subtler aspects like boxing or void vs Void.
> 
>     So I'll ask the question: why is the conversion applicable to
>     closures only, and not to function types as well?
> 
>     Presumably if it were allowed for function types then it would be
>     trivial to write a program which appears to have stable performance
>     and memory usage but which actually degrades in performance and
>     eventually blows up with an OutOfMemoryError or StackOverflowError,
>     but I'm curious to know what the real reasons are.
> 
>     Regards,
> 
>     Mark
> 
> 
>     On 13 Aug 2008, at 04:44, Neal Gafter wrote:
> 
>>     Alex-
>>
>>     In your code, doN requires its third parameter of type
>>
>>     {int, T => U throws X}
>>
>>     but you've supplied something of type
>>
>>     {int, String => void throws IOException}
>>
>>     In fact, the value you supplied is NOT a closure, it is a variable
>>     of function type.  The closure conversion is not involved at all.
>>
>>     These two function types are unrelated.  There is no conversion
>>     between them.  So the call is illegal.
>>
>>     In the first call, you did supply a closure (a method reference is
>>     a kind of closure), so the closure conversion was applied.
>>
>>     The fact that the diagnostic prints the "required" line in terms
>>     of javax.lang.function.OIO instead of using the function type
>>     syntax is a bug.
>>
>>     Regards,
>>     Neal
>>
>>     On Tue, Aug 12, 2008 at 2:34 PM, Alex Buckley
>>     <Alex.Buckley at sun.com <mailto:Alex.Buckley at sun.com>> wrote:
>>
>>         Trying to stress the equivalence, I get this interesting error
>>         on the first line of main but not the second:
>>
>>         A.java:13: method doN in class A cannot be applied to given types
>>         required: int,T,javax.lang.function.OIO<? extends U,? super
>>         T,? extends X>
>>         found: int,java.lang.String,{int,java.lang.String => void
>>         throws java.io.IOException}
>>            doN(1, "hi" , closure);
>>            ^
>>         1 error
>>
>>         Seems like the wrong proto-function is being selected.
>>
>>         --
>>         import java.io.*;
>>
>>         public class A {
>>          static {int, String => void throws IOException} closure = {
>>            int i, String s =>
>>              if (i==3) throw new IOException(); System.out.println(s);
>>          };
>>
>>          static void method(int i, String s) throws IOException {
>>            if (i==3) throw new IOException(); System.out.println(s);
>>          }
>>
>>          public static void main(String[] a) {
>>            doN(1, "hi" , closure);
>>            doN(2, "bye", A#method(int,String));
>>          }
>>
>>          static <T extends String, U, throws X extends IOException>
>>          void doN(int n, T x, {int, T => U throws X} b) {
>>            for (int i = 0; i < n; i++) {
>>              try {
>>                b.invoke(i, x);
>>              } catch (IOException e) { System.out.println("o no!"); }
>>            }
>>          }
>>         }
>>         --
>>
>>
> 
> 



More information about the closures-dev mailing list