<html><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; ">
<div>Motivation for all this is not entirely clear to me at the moment, probably because there's obviously a lack of existing APIs which use function types, so there's a heavy bias to the kind of conversions needed right now.</div><div><br></div><div>Still, I'm getting horribly tempted to do some 'investigative research' :/</div><div><br></div><div>I'll probably talk myself out of it, but let's see if I understand this so far.  Sticking my notes together with the points made in this thread, what I think we're talking about is, from an end-user's perspective:</div><div><br></div><div>1) implicit conversion from one function type to another compatible function type,</div><div>2) implicit conversion from a single-abstract-method interface type to a compatible function type,</div><div><br></div><div>where 'compatible' implies the full cunningness of the current BGGA closure conversion.</div><div><br></div><div>Such bi-directional conversions are already possible under BGGA, by explicitly wrapping the expression in a closure, or more simply by creating a method reference.  Each such explicit conversion introduces accumulative runtime overhead, in terms of memory usage and method invocation, so cannot be done implicitly by the compiler.</div><div><br></div><div>Closure conversion as currently defined incurs no such runtime overhead, since the closure literal is realised as an instance of (some subtype of) the target type, and cannot be performed again on the resulting value.</div><div><br></div><div>Normalising the function type interfaces might allow conversion between function types without incurring that overhead, but if the normalisation extends to using the boxed versions of the primitive types, such that it supports the following:</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>{Integer=>void} fn1 = ...;</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>{int=>void} fn2 = fn1;</div><div>then it would incur a different overhead at the point of method invocation - this would be undesirable for motivational frameworks like fork/join.</div><div><br></div><div>Interface injection alone may eliminate the overhead for certain conversions, but not all.  For example, it wouldn't cater for a conversion from {Integer=>void} to {int=>void} without injecting a 'bridge' method.  (What would be the effect of repeated conversion of a value between the two types?)</div><div><br></div><div>BGGA's current approach doesn't appear to stand in the way of future versions of the compiler from taking advantage of new VM features, nor a future iteration of the language spec from using those features to allow implicit conversions of the above forms.  In which case, since the 'closure type' is a compile-time only concept, it should be possible to replace it with the "ideal" model Alex described.</div><div><br></div><div>That sound reasonably accurate?</div><div><br></div><div>Regards,</div><div><br></div><div>Mark</div><div><br></div><div><br></div><div><div>On 13 Aug 2008, at 23:33, Neal Gafter wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div dir="ltr">Alex-<br><br>BGGA's goal was to introduce closures and the function type syntax without changing the underlying type system, and without requiring changes in the VM's type system.  Opening up the scope to the possibility of such changes might affect the shape of the ideal solution.<br> <br>Regards,<br>Neal<br><br><div class="gmail_quote">On Wed, Aug 13, 2008 at 10:45 AM, Alex Buckley <span dir="ltr">&lt;<a href="mailto:Alex.Buckley@sun.com">Alex.Buckley@sun.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"> I recall you distinguished "function type" from "closure type" many moons ago. For my own understanding, here are some notes.<br> <br> "Ideally" there would be no difference and one could say:<br> - A closure literal is a value and has a function type.<br> - A variable can store such a value and has a function type.<br> - Closure conversion is from a function type to an interface type<br>  with a single compatible method.<br> <br> which would allow:<br> <br> interface Foo { void m(int i, String s) throws IOException; }<br> <br> doN(1, "hi", new Foo() {<br>  void m(int i, String s) {if (i==3) throw ...; System.out.println(s);}<br> });<br> <br> void doN(int n, String x,<br>         {int, String => void throws IOException} b) {...}<br> <br> Conversion from an arbitary interface type (Foo) to an arbitrary function type ({int, String => void throws IOException}) is hard.<br> VM-level interface injection could make it less hard.<br> <br> 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.<br> <br> Therefore, BGGA 0.5 stratifies closure literal terms and variable terms:<br> - A closure literal is a value and has a closure type.<br> - A variable can store such a value and has a function type.<br> - Closure conversion is from a closure type to an interface type<br>  with a single compatible method.<br> <br> Alex<br> <br> Neal Gafter wrote:<br> <blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"><div class="Ih2E3d"> Subtype relationships among reference types must require no conversion code. For example, converting a List&lt;? extends Number> to a List&lt;? 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.<br> <br> Regards,<br> Neal<br> <br></div><div><div></div><div class="Wj3C7c"> On Wed, Aug 13, 2008 at 3:29 AM, Mark Mahieu &lt;<a href="mailto:mark@twistedbanana.demon.co.uk" target="_blank">mark@twistedbanana.demon.co.uk</a> &lt;mailto:<a href="mailto:mark@twistedbanana.demon.co.uk" target="_blank">mark@twistedbanana.demon.co.uk</a>>> wrote:<br> <br>    I must admit that I've come close to reporting similar non-bugs,<br>    because even though I *know* - having read the spec far too many<br>    times - that the conversion is only applicable to closures, I've<br>    found it's very easy to slip into thinking that assignment<br>    compatibility works the same way for function types.  At least for<br>    the subtler aspects like boxing or void vs Void.<br> <br>    So I'll ask the question: why is the conversion applicable to<br>    closures only, and not to function types as well?<br> <br>    Presumably if it were allowed for function types then it would be<br>    trivial to write a program which appears to have stable performance<br>    and memory usage but which actually degrades in performance and<br>    eventually blows up with an OutOfMemoryError or StackOverflowError,<br>    but I'm curious to know what the real reasons are.<br> <br>    Regards,<br> <br>    Mark<br> <br> <br>    On 13 Aug 2008, at 04:44, Neal Gafter wrote:<br> <br> </div></div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"><div><div></div><div class="Wj3C7c">    Alex-<br> <br>    In your code, doN requires its third parameter of type<br> <br>    {int, T => U throws X}<br> <br>    but you've supplied something of type<br> <br>    {int, String => void throws IOException}<br> <br>    In fact, the value you supplied is NOT a closure, it is a variable<br>    of function type.  The closure conversion is not involved at all.<br> <br>    These two function types are unrelated.  There is no conversion<br>    between them.  So the call is illegal.<br> <br>    In the first call, you did supply a closure (a method reference is<br>    a kind of closure), so the closure conversion was applied.<br> <br>    The fact that the diagnostic prints the "required" line in terms<br>    of javax.lang.function.OIO instead of using the function type<br>    syntax is a bug.<br> <br>    Regards,<br>    Neal<br> <br>    On Tue, Aug 12, 2008 at 2:34 PM, Alex Buckley<br></div></div><div><div></div><div class="Wj3C7c">    &lt;<a href="mailto:Alex.Buckley@sun.com" target="_blank">Alex.Buckley@sun.com</a> &lt;mailto:<a href="mailto:Alex.Buckley@sun.com" target="_blank">Alex.Buckley@sun.com</a>>> wrote:<br> <br>        Trying to stress the equivalence, I get this interesting error<br>        on the first line of main but not the second:<br> <br>        A.java:13: method doN in class A cannot be applied to given types<br>        required: int,T,javax.lang.function.OIO&lt;? extends U,? super<br>        T,? extends X><br>        found: int,java.lang.String,{int,java.lang.String => void<br>        throws java.io.IOException}<br>           doN(1, "hi" , closure);<br>           ^<br>        1 error<br> <br>        Seems like the wrong proto-function is being selected.<br> <br>        --<br>        import java.io.*;<br> <br>        public class A {<br>         static {int, String => void throws IOException} closure = {<br>           int i, String s =><br>             if (i==3) throw new IOException(); System.out.println(s);<br>         };<br> <br>         static void method(int i, String s) throws IOException {<br>           if (i==3) throw new IOException(); System.out.println(s);<br>         }<br> <br>         public static void main(String[] a) {<br>           doN(1, "hi" , closure);<br>           doN(2, "bye", A#method(int,String));<br>         }<br> <br>         static &lt;T extends String, U, throws X extends IOException><br>         void doN(int n, T x, {int, T => U throws X} b) {<br>           for (int i = 0; i &lt; n; i++) {<br>             try {<br>               b.invoke(i, x);<br>             } catch (IOException e) { System.out.println("o no!"); }<br>           }<br>         }<br>        }<br>        --<br> <br> <br> </div></div></blockquote> <br> <br> </blockquote> </blockquote></div><br></div></blockquote></div><br></body></html>