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