From mr at sun.com Thu Dec 10 13:54:19 2009 From: mr at sun.com (Mark Reinhold) Date: Thu, 10 Dec 2009 13:54:19 -0800 Subject: Project Lambda: The Straw-Man Proposal Message-ID: <20091210215419.4BD4E68F@eggemoggin.niobe.net> Welcome to Project Lambda! I've posted an initial straw-man proposal here: http://cr.openjdk.java.net/~mr/lambda/straw-man - Mark From scolebourne at joda.org Thu Dec 10 14:13:41 2009 From: scolebourne at joda.org (Stephen Colebourne) Date: Thu, 10 Dec 2009 22:13:41 +0000 Subject: Versioning the proposal Message-ID: <4B217295.4080909@joda.org> Could I ask that as the proposal is developed and refined, that each version is given a clear version number and new web page. Having the history of the proposal will be of vital value in the future when we need to point questioners as to 'why' and 'when' a certain issue was decided. thanks, Stephen From pdoubleya at gmail.com Thu Dec 10 14:20:51 2009 From: pdoubleya at gmail.com (Patrick Wright) Date: Thu, 10 Dec 2009 23:20:51 +0100 Subject: Serialization Message-ID: <64efa1ba0912101420h6c3cb2b3mf9ff4afc0d7b1a24@mail.gmail.com> Hi May we assume that there will be nothing about how closures are implemented that would prevent fields of function types in serializable classes? Thanks Patrick From alex.blewitt at gmail.com Thu Dec 10 14:38:03 2009 From: alex.blewitt at gmail.com (Alex Blewitt) Date: Thu, 10 Dec 2009 22:38:03 +0000 Subject: SAM types and functions Message-ID: > Many existing Java libraries de?ne interfaces which declare just one method > or abstract classes which declare just one abstract method (so- called ?SAM? types). > A function of appropriate type is converted to an anonymous instance ... I'm not sure this is needed in the general case; where it could be used is in (say) Comparators. However, having a Collections static method (say, Comparable c = Collections.comparable(#int(Object a, Object b)) would be sufficient to convert a lambda into a Comparable. I think the addition of the SAM conversion adds unnecessary complexity and shouldn't necessarily be implemented if it causes the detriment of the addition of lambdas to the language; after all, many of the problems of existing proposals have been due to increased complexity. That's not to say I don't see the benefit of doing this; but what happens if additional abstract methods are added to a class? That sounds like something to generate a lot of headaches in the edge cases. Alex From pdoubleya at gmail.com Thu Dec 10 14:39:30 2009 From: pdoubleya at gmail.com (Patrick Wright) Date: Thu, 10 Dec 2009 23:39:30 +0100 Subject: Function types as classes Message-ID: <64efa1ba0912101439s2f28bef2s24a01604e89b3dc@mail.gmail.com> Hi Should I assume in reading the Staw Man Proposal (SMP) that when I read "function type" I should understand that to be some Class, and we assign instances of that function type? If so: #int() fortyTwo = #()(42); #int() fortyTwoTwo = #()(42); assert !(fortyTwo == fortyTwoTwo) but what about assert (fortyTwo.equals(fortyTwoTwo)) which maybe is a way of asking, is any #int() equal to any other #int()? What about hashCode()? Thanks (for your patience!) Patrick From jason.height at gmail.com Thu Dec 10 14:46:06 2009 From: jason.height at gmail.com (JmH) Date: Fri, 11 Dec 2009 09:16:06 +1030 Subject: Implicit return syntax error Message-ID: Hello, Firstly my name is Jason Height and aside from using java for many years i have no formal experience in writing of extending programming languages. However, this does not prevent me from having an opinion! I just started reading the strawman proposal and i would like to discuss the benefit/reasons of having an implict return statement for the simple expressions. I actually believe for a person with little or no experience in closures that the statement "#()(return 42;)" rather than "#()(42)" is far more readable and natural when compared to the existing jls. A syntax error is be generated if one omits the "return" keyword for a function ie: public int getFortyTwo() { 42; } As such i propose that the straw man proposal should be changed to so implicit returns are syntax errors. Thanks for reading. Jason From forax at univ-mlv.fr Thu Dec 10 15:15:31 2009 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Fri, 11 Dec 2009 00:15:31 +0100 Subject: Implicit return syntax error In-Reply-To: References: Message-ID: <4B218113.5010804@univ-mlv.fr> Le 10/12/2009 23:46, JmH a ?crit : > Hello, > > Firstly my name is Jason Height and aside from using java for many years i > have no formal experience in writing of extending programming languages. > > However, this does not prevent me from having an opinion! > > I just started reading the strawman proposal and i would like to discuss the > benefit/reasons of having an implict return statement for the simple > expressions. I actually believe for a person with little or no experience in > closures that the statement "#()(return 42;)" rather than "#()(42)" is far > more readable and natural when compared to the existing jls. A syntax error > is be generated if one omits the "return" keyword for a function ie: > > public int getFortyTwo() { > 42; > } > > As such i propose that the straw man proposal should be changed to so > implicit returns are syntax errors. > > Thanks for reading. > > Jason > > Hi Jason, Java syntax does a clear difference between expression and statement. return is a statement not an expression. The strawman proposal proposes two syntax: - one for expression: #() (42) - one for statement: #() { return 42; } I don't think it's a good idea to try to blur this difference. R?mi From mr at sun.com Thu Dec 10 21:26:36 2009 From: mr at sun.com (Mark Reinhold) Date: Thu, 10 Dec 2009 21:26:36 -0800 Subject: Versioning the proposal In-Reply-To: scolebourne@joda.org; Thu, 10 Dec 2009 22:13:41 GMT; <4B217295.4080909@joda.org> Message-ID: <20091211052636.3F2DD684@eggemoggin.niobe.net> > Date: Thu, 10 Dec 2009 22:13:41 +0000 > From: Stephen Colebourne > Could I ask that as the proposal is developed and refined, that each > version is given a clear version number and new web page. Having the > history of the proposal will be of vital value in the future when we > need to point questioners as to 'why' and 'when' a certain issue was > decided. Agreed; I was already planning to do that. - Mark From mr at sun.com Thu Dec 10 21:31:23 2009 From: mr at sun.com (Mark Reinhold) Date: Thu, 10 Dec 2009 21:31:23 -0800 Subject: Serialization In-Reply-To: pdoubleya@gmail.com; Thu, 10 Dec 2009 23:20:51 +0100; <64efa1ba0912101420h6c3cb2b3mf9ff4afc0d7b1a24@mail.gmail.com> Message-ID: <20091211053123.08EC7684@eggemoggin.niobe.net> > Date: Thu, 10 Dec 2009 23:20:51 +0100 > From: Patrick Wright > May we assume that there will be nothing about how closures are > implemented that would prevent fields of function types in > serializable classes? Good question; I hadn't yet thought about this issue. For a closure to be serializable would require all the values it references to be serializable, including "this" if it captures its enclosing instance. If that's true then offhand I don't see any other problems and it should "just work". (Serialization is tricky though, so I may well be missing something.) - Mark From pbenedict at apache.org Thu Dec 10 21:45:29 2009 From: pbenedict at apache.org (Paul Benedict) Date: Thu, 10 Dec 2009 23:45:29 -0600 Subject: Extension Methods Message-ID: Mark, First, thank you and very nice job writing up the proposal. It is a great document to read! I suppose you could version control it in Mercurial; then people can perform hi-tech diffs too. With regard to extension methods, I think the "declaration-site" extensions are mostly worthless. Interfaces shouldn't be used this way since they are suppose to define a contract to implement. I dare to say this is an abuse of the interface mechanism. The straw man says such methods are "hidden in a class implementing that interface", but I think it's a hack; it unnaturally bolts the feature to an abstraction. Java has gone 6 full releases and 15 years with the simple understanding what interfaces do. If extension methods are really going to make an appearance in Java 7, I hope it can be done without this unwieldy extension (pun) to interfaces. If this is all that declaration-site extensions have to offer, it's simply not worth it. I rather just use the static methods directly. I'll quote Joshua Bloch from Peter Ah?'s blog [1]: They "must be regarded as a fundamental change to the nature of interfaces in Java. I believe that interfaces are the heart and soul of the language, hence am reluctant to mess with them." I opt for this feature to be dropped. [1] http://digital-sushi.org/entry/declaration-site-extension-methods/ Paul From mr at sun.com Thu Dec 10 21:54:32 2009 From: mr at sun.com (Mark Reinhold) Date: Thu, 10 Dec 2009 21:54:32 -0800 Subject: Function types as classes In-Reply-To: pdoubleya@gmail.com; Thu, 10 Dec 2009 23:39:30 +0100; <64efa1ba0912101439s2f28bef2s24a01604e89b3dc@mail.gmail.com> Message-ID: <20091211055432.D417975B@eggemoggin.niobe.net> > Date: Thu, 10 Dec 2009 23:39:30 +0100 > From: Patrick Wright > Should I assume in reading the Staw Man Proposal (SMP) that when I > read "function type" I should understand that to be some Class, and we > assign instances of that function type? Whether a function type is actually a Class is an open question, I think, although I suspect that's where we'll end up. Whatever they are, it must be possible to declare variables of function type, and assign functions to them. > If so: > > #int() fortyTwo = #()(42); > #int() fortyTwoTwo = #()(42); > > assert !(fortyTwo == fortyTwoTwo) Right. > but what about > assert (fortyTwo.equals(fortyTwoTwo)) > > which maybe is a way of asking, is any #int() equal to any other > #int()? What about hashCode()? Closure equality should be object identity, and closure hash codes should be identity hash codes. (Well, I suppose we could consider two closures to be equal if they refer to the same bytecode and if their saved lexical bindings are all .equals, but I don't really see the point. This is never something that any Lisp has done, so far as I know.) - Mark From mr at sun.com Thu Dec 10 22:23:43 2009 From: mr at sun.com (Mark Reinhold) Date: Thu, 10 Dec 2009 22:23:43 -0800 Subject: SAM types and functions In-Reply-To: alex.blewitt@gmail.com; Thu, 10 Dec 2009 22:38:03 GMT; Message-ID: <20091211062343.8516E75B@eggemoggin.niobe.net> > Date: Thu, 10 Dec 2009 22:38:03 +0000 > From: alex.blewitt at gmail.com >> Many existing Java libraries de?ne interfaces which declare just one >> method or abstract classes which declare just one abstract method (so- >> called "SAM" types). A function of appropriate type is converted to >> an anonymous instance ... > > I'm not sure this is needed in the general case; where it could be > used is in (say) Comparators. However, having a Collections static > method (say, Comparable c = Collections.comparable(#int(Object a, > Object b)) would be sufficient to convert a lambda into a Comparable. (I suspect you really mean Collections.comparable(#int(T,T)) but that's beside the point.) > I think the addition of the SAM conversion adds unnecessary complexity > and shouldn't necessarily be implemented if it causes the detriment of > the addition of lambdas to the language; after all, many of the > problems of existing proposals have been due to increased complexity. I agree that if SAM conversion proves problematic then we should drop it, at least for now. I do, however, think we should try to figure out a way to support it. > That's not to say I don't see the benefit of doing this; but what > happens if additional abstract methods are added to a class? That > sounds like something to generate a lot of headaches in the edge cases. How often does that happen? Adding a new abstract method to a class is pretty much the same thing as adding a new method to an interface. You're asking for trouble. Don't do it. (Unless you control every class that extends that abstract class, which is rarely the case.) Such a modification is "binary compatible" per the JLS [1], but any code compiled against the new class will fail miserably if it attempts to invoke the new method upon an instance of a subclass that was compiled against the old version of the abstract class. (For that reason we don't do this in the platform, with a (very) small number of exceptions (e.g., JDBC) where the number of implementors of the interfaces/abstract classes is manageably small.) If the author of an abstract class decides to add a new abstract method to that class then any existing class files defining functions that are converted to instances of that class will continue to work just fine. It's only newly-compiled clients of the class that may fail, if and when they attempt to invoke the new method. In short, I don't think this is any different from the situation we already have today. If the author of an abstract class or interface decides to add a new abstract method then the consequences are their burden to bear. - Mark [1] http://java.sun.com/docs/books/jls/third_edition/html/binaryComp.html From pdoubleya at gmail.com Thu Dec 10 23:46:05 2009 From: pdoubleya at gmail.com (Patrick Wright) Date: Fri, 11 Dec 2009 08:46:05 +0100 Subject: Reflective operations Message-ID: <64efa1ba0912102346g72191d83q42f6a2f04e6748c5@mail.gmail.com> Hi More basic questions. I thought I would start a thread related to reflective operations on function types. - what will be returned for a method whose return type or parameter types are function types or for a field type which is of a function type? - can function types be instantiated via reflection? I assume if they are a type of Class they must be... - can function types be invoked via reflection? etc. Regards Patrick From daniel.latremoliere at gmail.com Fri Dec 11 01:45:19 2009 From: daniel.latremoliere at gmail.com (=?ISO-8859-1?Q?Daniel_Latr=E9moli=E8re?=) Date: Fri, 11 Dec 2009 10:45:19 +0100 Subject: Extension methods vs. Traits Message-ID: <4B2214AF.4080106@gmail.com> I would like to understand the final paragraph of the proposal where you are saying that the traits are much more significant change than extension methods to the language and VM. The VM doesn't need to implements traits. The compiler can transform one trait in one interface with abstract methods and declaration-sites for non-abstract methods and one anonymous class with the non-abstract methods coming from the trait and referenced in the interface by declaration-sites. Then I don't think traits are a bigger change in VM than extension methods, because this can be only a language feature implemented by compiler using your declaration-site in bytecode. For the language, I think traits are much more readable, because code is local, and doesn't not ask to follow the delegate to the static method in another class file. I think traits are reusing much more current Java language (method syntax) and doesn't introduce a new construct like declaration-site extension methods. But, I have not studied all possible effects in Java language. Thanks for the explanations, Daniel Latr?moli?re. From alex.blewitt at gmail.com Fri Dec 11 01:55:43 2009 From: alex.blewitt at gmail.com (Alex Blewitt) Date: Fri, 11 Dec 2009 09:55:43 +0000 Subject: Extension methods vs. Traits In-Reply-To: <4B2214AF.4080106@gmail.com> References: <4B2214AF.4080106@gmail.com> Message-ID: Traits also suffer in Scala, because when the implementation of a trait changes (such as bugfixing a method), the compiler has to be re- run over all sources that use that trait. It's one of Scala's biggest weaknesses that it is essentially a source-only compiled language. Please don't lets follow the route of other lambda proposals and make this more than it should be - but leave traits to a separate implementation. Alex On 11 Dec 2009, at 09:45, Daniel Latr?moli?re wrote: > I would like to understand the final paragraph of the proposal where > you are saying that the traits are much more significant change than > extension methods to the language and VM. > > The VM doesn't need to implements traits. The compiler can transform > one trait in one interface with abstract methods and declaration- > sites for non-abstract methods and one anonymous class with the non- > abstract methods coming from the trait and referenced in the > interface by declaration-sites. > Then I don't think traits are a bigger change in VM than extension > methods, because this can be only a language feature implemented by > compiler using your declaration-site in bytecode. > > For the language, I think traits are much more readable, because > code is local, and doesn't not ask to follow the delegate to the > static method in another class file. I think traits are reusing much > more current Java language (method syntax) and doesn't introduce a > new construct like declaration-site extension methods. But, I have > not studied all possible effects in Java language. > > Thanks for the explanations, > Daniel Latr?moli?re. > > From mthornton at optrak.co.uk Fri Dec 11 02:16:17 2009 From: mthornton at optrak.co.uk (Mark Thornton) Date: Fri, 11 Dec 2009 10:16:17 +0000 Subject: Revising interfaces Message-ID: <4B221BF1.9090700@optrak.co.uk> There are some interfaces (e.g. java.sql.ResultSet) that have been changed many times. Presumably the theory is that not too many implement those interfaces and thus not too many will be annoyed by the changes. Could we consider annotating interface methods (@since("1.1") perhaps) and providing a default implementation for those methods. Then require the JVM to insert the default implementation when loading implementations of the interface (and where the method is not already implemented). This would preserve all the existing character of interfaces. The down side is potential collision with existing methods having the same signature, but that is something of a hazard with extension methods as well. Mark Thornton From daniel.latremoliere at gmail.com Fri Dec 11 02:33:48 2009 From: daniel.latremoliere at gmail.com (=?ISO-8859-1?Q?Daniel_Latr=E9moli=E8re?=) Date: Fri, 11 Dec 2009 11:33:48 +0100 Subject: Extension methods vs. Traits In-Reply-To: References: <4B2214AF.4080106@gmail.com> Message-ID: <4B22200C.3030504@gmail.com> Please can you explain how Scala has this problem. I don't know precisely Scala internals, but given web documentation, its implementation seems to transform a trait in one interface with all methods (even non-abstract) and one class for implementation. Then, the compiler need to modify each class extending the trait for adding methods delegating to the implementation of the trait (for implementing these abstract methods previously added by compiler). http://hestia.typepad.com/flatlander/2009/01/scala-for-c-programmers-part-1a-mixins-and-traits-behind-the-scenes.html In my suggest, I am reusing current proposal of declaration-site method but only in bytecode not in source. Then non-abstract methods of the trait becomes declaration-site extensions methods in interface and are not abstract methods to be implemented. Compiler doesn't modify each class extending the trait. The bytecode compatibility is the same than declaration-site because reusing it at bytecode level. Thanks for details on Scala problem. Daniel. Alex Blewitt a ?crit : > Traits also suffer in Scala, because when the implementation of a > trait changes (such as bugfixing a method), the compiler has to be > re-run over all sources that use that trait. It's one of Scala's > biggest weaknesses that it is essentially a source-only compiled > language. > > Please don't lets follow the route of other lambda proposals and make > this more than it should be - but leave traits to a separate > implementation. > > Alex > > On 11 Dec 2009, at 09:45, Daniel Latr?moli?re wrote: > >> I would like to understand the final paragraph of the proposal where >> you are saying that the traits are much more significant change than >> extension methods to the language and VM. >> >> The VM doesn't need to implements traits. The compiler can transform >> one trait in one interface with abstract methods and >> declaration-sites for non-abstract methods and one anonymous class >> with the non-abstract methods coming from the trait and referenced in >> the interface by declaration-sites. >> Then I don't think traits are a bigger change in VM than extension >> methods, because this can be only a language feature implemented by >> compiler using your declaration-site in bytecode. >> >> For the language, I think traits are much more readable, because code >> is local, and doesn't not ask to follow the delegate to the static >> method in another class file. I think traits are reusing much more >> current Java language (method syntax) and doesn't introduce a new >> construct like declaration-site extension methods. But, I have not >> studied all possible effects in Java language. >> >> Thanks for the explanations, >> Daniel Latr?moli?re. >> >> > > From pdoubleya at gmail.com Fri Dec 11 03:02:50 2009 From: pdoubleya at gmail.com (Patrick Wright) Date: Fri, 11 Dec 2009 12:02:50 +0100 Subject: Extension methods and API evolution Message-ID: <64efa1ba0912110302g2aa55447mcd4256618492d2f2@mail.gmail.com> Hi I'd like to restate a comment regarding declaration-site extension methods that I posted to Peter Ah?'s blog when he suggested them a couple of years ago (http://digital-sushi.org/entry/declaration-site-extension-methods/). Use-site extension methods have the advantage that the extension methods are not necessarily part of the JDK. In the SMP as I read it, the java.util.Set interface must be updated, then closed for further updates until the next JDK release. With use-site extension methods, I can attach any method to Set that I want, for any project that I work on. Obviously there will be some methods that the core-libs dev team decides will be generally useful, though as the discussion around ?humane? APIs some time back showed, it will be hard to agree on what the limited set should comprise (see http://martinfowler.com/bliki/HumaneInterface.html). And no one else will be able to add extension methods to the core API, and they will remain unchanged (as they are part of the JDK API set) until the next rev of the JDK. That seems overly constraining. What I like about use-site extension methods is that we can package different utility classes with extension methods for lists (or strings-does this need to be limited to extending interfaces? what about final classes?), to make them more convenient/friendly to use, in particular in cases where we run up against the limitations of the class API?for example, if doing a lot of String manipulation in one section of our code, we may want to add some convenience methods to simplify and clarify things (like the recent request for rtrim and ltrim in String), and in those cases we pick the extensions library that we think fits the best in that particular situation. I understand the risk of creating "dialects" of code by allowing use-site extension methods, but I think the alternative is simply too restrictive. Regards Patrick From howard.lovatt at iee.org Fri Dec 11 04:45:51 2009 From: howard.lovatt at iee.org (Howard Lovatt) Date: Fri, 11 Dec 2009 13:45:51 +0100 Subject: Extension methods vs. Traits Message-ID: <3dd3f56a0912110445n69393163p947b861005c687eb@mail.gmail.com> Hi All, Traits as proposed, http://www.artima.com/weblogs/viewpost.jsp?thread=220916, are slightly different than Scala Traits: 1. In Scala if you add a new method to a Trait then you need to recompile classes that use that Trait for the new method to become available, in the proposal the linker adds the new method automatically (hence no need to recompile). Note if you just change an existing method in Scala, or for that matter with the Trait proposal, you don't need to recompile (this is not quite what Alex said - but I think this is what he meant - Alex please confirm). 2. In Scala you can only access your immediate super Trait, in the proposal you can access any super Trait (this was one of the original motivations behind Traits as opposed to mixins - http://www.iam.unibe.ch/~scg/Archive/Papers/Scha03aTraits.pdf) 3. In Scala the traits are like mixins with complicated rules for what gets called if the same trait appears multiple times in a hierarchy (diamond problem), in the proposal you have to override any method that is ambiguous (thus much simplifying both the implementation and use of Traits). 4. Like Scala: the proposal is mainly a modification to the compiler, I would suggest that the compiler work would be similar to adding extension methods. Unlike Scala: in addition to the compiler the linker needs to be changed, so probably on balance slightly more work than extension methods. I think Traits, as proposed in the blog referenced, would be superior to any of the extension methods (thats why I made the suggestion!) and I would be happy to work on their implementation if people thought it worthwhile. On the other hand, if for all intents and purpose the decision has been made to implement extension methods then there is no point working on Traits. What do people think? -- Howard. From fatih at coskuns-castle.de Fri Dec 11 05:44:14 2009 From: fatih at coskuns-castle.de (Fatih Coskun) Date: Fri, 11 Dec 2009 14:44:14 +0100 Subject: declaration-site extension methods possibly dangerous Message-ID: <4B224CAE.6060209@coskuns-castle.de> declaration-site extension methods can be easily confused with abstract methods of an interface. I can imagine many developers trying to override extension methods in their subclasses in order to provide different implementations. But this will not work. declaration-site extension methods cannot be overriden, they are hidden instead. This means, that the extension method will always be invoked, if the static type of a variable is the interface type, although the dynamic object type may have hidden the extension method with an own implementation. This will lead to much confusion. Note, that use-site extension method do not have this problem. From gesser at gmail.com Fri Dec 11 05:50:27 2009 From: gesser at gmail.com (Carlos Eduardo Gesser) Date: Fri, 11 Dec 2009 11:50:27 -0200 Subject: Grouping extention methods Message-ID: Hello everybody What about creating a new kind of extension class, with the pourpose of grouping extension methods to a single class/interface. E.g.: super class ListOps implements List { void sort() { Collections.sort(this); } E first() { return get(0); } } super class MyStringOps extends String { String reverse() { ... } String presuffix(String p, String s) { return p + this + s; } } ..... import ListOps; import MyStringOps; ... List list = .... list.sort(); String s = "abc".reverse(); String str = s.presuffix("[", "]") This "super class" could extend/implement a single class/interface, and can not have constructors/fields/abstract methods. This way we can clarify witch class/interface we are giving new methods, and minimize the namespace pollution that would occur if we let any static method be used as extension method. "super class" is only a sugestion, it dispenses a new keyword. Internally it can be implemented as the original extension method proposal: a class with static methods taking the extended class/interface as first parameter, with a jvm level annotation to distinguish it. -- Carlos Eduardo Gesser From forax at univ-mlv.fr Fri Dec 11 06:12:47 2009 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Fri, 11 Dec 2009 15:12:47 +0100 Subject: declaration-site extension methods possibly dangerous In-Reply-To: <4B224CAE.6060209@coskuns-castle.de> References: <4B224CAE.6060209@coskuns-castle.de> Message-ID: <4B22535F.3050608@univ-mlv.fr> Fatih Coskun a ?crit : > declaration-site extension methods can be easily confused with abstract > methods of an interface. I can imagine many developers trying to > override extension methods in their subclasses in order to provide > different implementations. But this will not work. Right > declaration-site > extension methods cannot be overriden, they are hidden instead. Why ?, The proposal doesn't say anything about that. > This > means, that the extension method will always be invoked, if the static > type of a variable is the interface type, although the dynamic object > type may have hidden the extension method with an own implementation. > This will lead to much confusion. Note, that use-site extension method > do not have this problem. > I don't understand why use-site extension don't suffer from the same disease. R?mi From daniel.latremoliere at gmail.com Fri Dec 11 06:40:19 2009 From: daniel.latremoliere at gmail.com (=?ISO-8859-1?Q?Daniel_Latr=E9moli=E8re?=) Date: Fri, 11 Dec 2009 15:40:19 +0100 Subject: Extension methods vs. Traits In-Reply-To: <3dd3f56a0912110445n69393163p947b861005c687eb@mail.gmail.com> References: <3dd3f56a0912110445n69393163p947b861005c687eb@mail.gmail.com> Message-ID: <4B2259D3.1050308@gmail.com> I suppose implementation of the extension method need to add bytecode describing a new slot type forwarding calls of the extension method of this slot on a non-abstract method of another class (modification of the linker). Others methods can possibly cause problems like those of Scala traits. Given that, I think the modification needed to the linker for supporting traits, can not be bigger than the modification to the linker for supporting extension method, because I think a trait can be implemented with an interface using this forwarding slot and an anonymous class for non-abstract methods. Then, I would like to understand the comment of the proposal on significant change in the VM needed for supporting traits. Daniel. > Hi All, > > Traits as > proposed, http://www.artima.com/weblogs/viewpost.jsp?thread=220916, > are slightly different than Scala Traits: > > 1. In Scala if you add a new method to a Trait then you need to > recompile classes that use that Trait for the new method to become > available, in the proposal the linker adds the new method > automatically (hence no need to recompile). Note if you just change an > existing method in Scala, or for that matter with the Trait proposal, > you don't need to recompile (this is not quite what Alex said - but I > think this is what he meant - Alex please confirm). > > 2. In Scala you can only access your immediate super Trait, in > the proposal you can access any super Trait (this was one of the > original motivations behind Traits as opposed to mixins - > http://www.iam.unibe.ch/~scg/Archive/Papers/Scha03aTraits.pdf > ) > > 3. In Scala the traits are like mixins with complicated rules for what > gets called if the same trait appears multiple times in a hierarchy > (diamond problem), in the proposal you have to override any method > that is ambiguous (thus much simplifying both the implementation and > use of Traits). > > 4. Like Scala: the proposal is mainly a modification to the compiler, > I would suggest that the compiler work would be similar to adding > extension methods. Unlike Scala: in addition to the compiler the > linker needs to be changed, so probably on balance slightly more work > than extension methods. > > I think Traits, as proposed in the blog referenced, would be superior > to any of the extension methods (thats why I made the suggestion!) and > I would be happy to work on their implementation if people thought it > worthwhile. On the other hand, if for all intents and purpose the > decision has been made to implement extension methods then there is no > point working on Traits. > > What do people think? > > -- Howard. From neal at gafter.com Fri Dec 11 11:17:51 2009 From: neal at gafter.com (Neal Gafter) Date: Fri, 11 Dec 2009 11:17:51 -0800 Subject: Comments on the straw man... Message-ID: <15e8b9d20912111117i3850004dne0b391c5669e216a@mail.gmail.com> These are thoughts that occur to me on first reading of Mark's strawman. 1. Lambda expressions. It appears there are two forms (which I call expression lambdas and statement lambdas). I think that's a good idea. It isn't clear if the parens in the expression lambdas are a required part of the syntax, or just happen to appear in all the examples. A grammar to accompany the proposal would clarify this. I don't have strong feelings either way, but I believe we would come to regret requiring the parens. The strawman doesn't say anything about it, but I believe it would be an error to require that each evaluation of a lambda expression creates a distinct object, as Mark suggested in a previous email. I can explain in detail if it isn't clear why, but for a hint note that many of the examples of lambdas in the strawman could be statically allocated (when the lambda isn't technically a closure). The compiler should be free to do that, rather than requiring the programmer to reorganize the code to place each such lambda where it is evaluated only once. There is too little detail to see how things fit together here. I don't know what the type of a lambda expression is or what the type (and definite assignment, exception, completion, binary compatibility, runtime, etc) rules are. The devil is in the details. 2. Function types. The strawman doesn't give any semantics for these, so it is hard to evaluate. What is the syntax for checked exceptions that might be thrown by a function? How do I construct a class literal with these? Do they obey subtype rules that are covariant on return types? Contravariant on argument types? If it lacks either, it would reduce the flexibility of the ParallelArray APIs. One option is that these types map to interfaces, as BGGA, in which case we know a coherent spec in this direction is possible. I know some people would like to see method handles investigated as an implementation mechanism for function types, but I haven't seen any serious attempt at specifying that. Some language work will be required to explain how variables of function type can be invoked. Perhaps variables of function type are also added to the method namespace? It will be a bit messy; the devil is in the details. 3. Function conversion. Again, too much is missing. What is "appropriate type" and "as needed"? Is this conversion applied only to lambda expressions (as in BGGA)? Or does it also convert variables of "function types" (sec 2) to "SAM types", which suggests that function types are not interfaces? Is this an identity conversion? A subtype conversion? An assignment conversion? An argument conversion? A boxing conversion? In BGGA (and therefore FCM) it is a subtype conversion so that it can be integrated into type inference, but perhaps the strawman author has other ideas. Keeping the effect on type inference in mind should help prune the design space, but the strawman gives no hint that this has been done. What if the abstract method is generic? If SAMs include classes (with a single abstract method), then how is the constructor selected, and where do its arguments come from? Can it be an inner class? A local class? Are the SAM's members in scope within the body of the closure? If not, what is the reason to include (abstract) classes? Including (abstract) classes also interferes with the compiler's ability to select the allocation time (see second paragraph under 1 above). Overall, I believe the issues with them and the rarity of use cases argues against supporting (abstract) classes as SAMs. Again, the devil is in the details; without details it is hard to see if or how function conversions fit with the rest of the strawman. 4. Variable Capture. Needs more refinement about what is meant by "effectively final". Despite the strawman's reference, the JLS DA/DU rules can't be used for this purpose; a new and separate dataflow specification would be required. That is likely to be comparable in size to the existing JLS3 DA/DU analysis and require a significant effort to specify and implement correctly. One simple approach is to define as "effectvely final" variables that are never subject to an assignment (initialization in the declaration is not assignment), as the BGGA prototype does. That is trivial to specify. What appears to be intended here isn't (... devil ... details). The strawman says that "A shared variable can be modi?ed within the body of a lambda expression, although it must be de?nitely assigned-to before the lambda expression is evaluated." This is an error; there is no reason to require a variable be definitely assigned if it is only written by the lambda. 5. Scoping. I presume all names (except lambda parameters) and accessibility are resolved as in the lexically enclosing scope (i.e. no names inherited from the SAM). But this is far from clear (especially when used with abstract class SAMs). 6. Exception transparency ala BGGA requires the type "Nothing" to be used as an exception parameter and also in the return type for conversion of a lambda whose body cannot complete normally, but there is no mention of "Nothing" in the strawman. BGGA also introduces disjunctive types and related rules for type inference. BGGA relies on function types being interfaces, but the strawman explicitly leaves that open, making me wonder what the strawman author has in mind. There is not enough information to even guess what is envisioned here. If disjunctive exception types are supported, then the coin specification for multicatch can be simplified. It would allow the removal of the "final" requirement on disjunctive catch parameters. 8. Extension methods. I think more experience with alternatives would be valuable. My primary concern with extension methods in this form is that it undermines one of their most valuable traits - the ability to retrofit functionality on APIs without requiring access to the source. That is useful among other reasons to enable much more flexibility in future language changes. As a separate matter, extension methods could be used as a basis for a much cleaner specification of array-index syntax for lists/maps. It isn't clear if discussion of extension methods is appropriate here or in Coin. 0. Overall impression. Overall, my impression is that this strawman sets a stake in the ground about how the language features might fit together without actually working it out or verifying that the ideas are mutually compatible. It appears to address the simplest use cases only. There is not enough detail to evaluate most of it. A great deal of work will be required to turn the ideas into a coherent language specification, and that will likely require a significant revision of the initial ideas. Many of my questions would be answered in the effort; it isn't clear what purpose was served by publishing the strawman. Given the amount of language design work remaining and the short time frame (5-6 months to feature complete), does Sun plan to devote someone (or a team) with the appropriate skills (or who have the time to develop those skills) to the task? When can we expect the blanks in the strawman to be filled in? What resources and schedule are envisioned for the implementation/prototype? It would be nice to have a wiki to track progress. I can easily imagine points being lost in discussion threads that branch from a message such as this one. I've provided hosting here: , but I can easily imagine Sun could provide its own hosting facilities. (I've sent Mark the admin password separately). Cheers, Neal From fatih at coskuns-castle.de Fri Dec 11 12:26:40 2009 From: fatih at coskuns-castle.de (Fatih Coskun) Date: Fri, 11 Dec 2009 21:26:40 +0100 Subject: declaration-site extension methods possibly dangerous In-Reply-To: <4B22535F.3050608@univ-mlv.fr> References: <4B224CAE.6060209@coskuns-castle.de> <4B22535F.3050608@univ-mlv.fr> Message-ID: <4B22AB00.8000306@coskuns-castle.de> R?mi Forax wrote: > Fatih Coskun a ?crit : >> declaration-site extension methods can be easily confused with >> abstract methods of an interface. I can imagine many developers >> trying to override extension methods in their subclasses in order to >> provide different implementations. But this will not work. >> declaration-site extension methods cannot be overriden, they are >> hidden instead. > > Why ?, The proposal doesn't say anything about that. From the proposal: "An extension method in an interface is hidden in a class implementing that interface if the class de?nes a static or instance method with the same signature." The proposal states that extension methods can be hidden, i.e. they cannot be overriden. It couldn't be otherwise, because extension methods are in fact just static methods. Static methods are always statically bound (via the static type of a variable), this means it is never possible to override them in a dynamic manner like instance methods can be. > I don't understand why use-site extension don't suffer from the same > disease. use-site extension methods suffer from the same consequence in that they cannot be overriden in a class implementing the interface. But they do not suffer in the same way in that one can be easily confused about this. Because use-site extension methods are not defined in the interface, one will not be tempted to override them. The developer will not be tempted to do something that can't be done. Fatih From forax at univ-mlv.fr Fri Dec 11 13:35:41 2009 From: forax at univ-mlv.fr (=?UTF-8?B?UsOpbWkgRm9yYXg=?=) Date: Fri, 11 Dec 2009 22:35:41 +0100 Subject: declaration-site extension methods possibly dangerous In-Reply-To: <4B22AB00.8000306@coskuns-castle.de> References: <4B224CAE.6060209@coskuns-castle.de> <4B22535F.3050608@univ-mlv.fr> <4B22AB00.8000306@coskuns-castle.de> Message-ID: <4B22BB2D.3030501@univ-mlv.fr> Le 11/12/2009 21:26, Fatih Coskun a ?crit : > R?mi Forax wrote: >> Fatih Coskun a ?crit : >>> declaration-site extension methods can be easily confused with >>> abstract methods of an interface. I can imagine many developers >>> trying to override extension methods in their subclasses in order to >>> provide different implementations. But this will not work. >>> declaration-site extension methods cannot be overriden, they are >>> hidden instead. >> >> Why ?, The proposal doesn't say anything about that. > From the proposal: > "An extension method in an interface is hidden in a class implementing > that interface if the class de?nes a static or instance method with > the same signature." > > The proposal states that extension methods can be hidden, i.e. they > cannot be overriden. Ok, It seems I have un-voluntarily skip that sentence when reading the proposal. Anyway, I don't think that it's a good idea to be able to hide an extension method. > It couldn't be otherwise, because extension methods are in fact just > static methods. Static methods are always statically bound (via the > static type of a variable), this means it is never possible to > override them in a dynamic manner like instance methods can be. Yes, but the compiler can raise an error, as it do when you try to override a static method with a non-static one. >> I don't understand why use-site extension don't suffer from the same >> disease. > use-site extension methods suffer from the same consequence in that > they cannot be overriden in a class implementing the interface. But > they do not suffer in the same way in that one can be easily confused > about this. Because use-site extension methods are not defined in the > interface, one will not be tempted to override them. The developer > will not be tempted to do something that can't be done. Why, it's an extension method. By definition, you call it on an instance, so you will want to override it. It's a problem of all extension methods. > > Fatih R?mi From fatih at coskuns-castle.de Sat Dec 12 03:25:20 2009 From: fatih at coskuns-castle.de (Fatih Coskun) Date: Sat, 12 Dec 2009 12:25:20 +0100 Subject: declaration-site extension methods possibly dangerous In-Reply-To: <4B22BB2D.3030501@univ-mlv.fr> References: <4B224CAE.6060209@coskuns-castle.de> <4B22535F.3050608@univ-mlv.fr> <4B22AB00.8000306@coskuns-castle.de> <4B22BB2D.3030501@univ-mlv.fr> Message-ID: <4B237DA0.2050805@coskuns-castle.de> R?mi Forax wrote: > I don't think that it's a good idea to be able to hide an extension > method. [...] the compiler can raise an error, as it do when you try > to override a static method > with a non-static one. > > Extension methods are about adding methods to interfaces without breaking existing code. What happens, if someone has defined an instance method, which is later added as an extension method in the class' super-interface? We can't raise an error, as that would break existing code. >> Because use-site extension methods are not defined in the interface, >> one will not be tempted to override them. The developer will not be >> tempted to do something that can't be done. > > > Why, it's an extension method. By definition, you call it on an > instance, so you will want to override it. It's a problem of all > extension methods. > > Maybe. But use-site extension methods are less likely to be confused with instance methods in my opinion. Besides that, it may be easier to explain why it is not possible to override use-site extension methods. From forax at univ-mlv.fr Sat Dec 12 04:41:54 2009 From: forax at univ-mlv.fr (=?UTF-8?B?UsOpbWkgRm9yYXg=?=) Date: Sat, 12 Dec 2009 13:41:54 +0100 Subject: declaration-site extension methods possibly dangerous In-Reply-To: <4B237DA0.2050805@coskuns-castle.de> References: <4B224CAE.6060209@coskuns-castle.de> <4B22535F.3050608@univ-mlv.fr> <4B22AB00.8000306@coskuns-castle.de> <4B22BB2D.3030501@univ-mlv.fr> <4B237DA0.2050805@coskuns-castle.de> Message-ID: <4B238F92.9040402@univ-mlv.fr> Le 12/12/2009 12:25, Fatih Coskun a ?crit : > R?mi Forax wrote: >> I don't think that it's a good idea to be able to hide an extension >> method. [...] the compiler can raise an error, as it do when you try >> to override a static method >> with a non-static one. >> >> > > > Extension methods are about adding methods to interfaces without > breaking existing code. No, just adding method to an interface (see below). > What happens, if someone has defined an instance method, which is > later added as an extension method in the class' super-interface? We > can't raise an error, as that would break existing code. Yes, it will break existing code, like introducing a new public method in a class can break code. In real world, this kind of breakage doesn't appear often, I don't think it worst the cost of not raising an error is you try to override an extension method. Note that introducing an extension method can break the code in a more malicious way if the extension method overload an abstract method of the interface. interface Map { V get(Object o); V get(String s) import static Optimizeds.get; } R?mi From schulz at the-loom.de Sat Dec 12 14:43:49 2009 From: schulz at the-loom.de (Stefan Schulz) Date: Sat, 12 Dec 2009 23:43:49 +0100 Subject: Comments on the straw man... In-Reply-To: <15e8b9d20912111117i3850004dne0b391c5669e216a@mail.gmail.com> References: <15e8b9d20912111117i3850004dne0b391c5669e216a@mail.gmail.com> Message-ID: <4B241CA5.3060305@the-loom.de> Just some additional cents ... I'm not quite sure, what to make of the strawman proposal. To me, it rather looks like a quickly sketched technical wishlist for lambda expressions, especially due to the tutorial style (but I think, that's somehow what Mark mentions in the first paragraphs). As Neal pointed out, there is lots of work to be done before it could be taken as a serious proposal, and I don't think the strawman being appropriate in its current state to do this by a rather large group of people as are on this mailing list, but a reduced number of language and closure/lambda experts (not implying that I would be qualified as such an expert). The slightly heated discussion on one of the very most optional parts "extension methods" IMHO shows the problem in not having a mature base for common refinement. I ask myself, if it would be wiser to pick up the latest version of CfJ and adopt it to the ideas as written down by Mark. For the start, I would even put the enhanced syntax for method-like invocation of function types into the optional section. It seems, too many thoughts are going into the beauty of syntax before having the base done right. Stefan From scolebourne at joda.org Sat Dec 12 16:17:27 2009 From: scolebourne at joda.org (Stephen Colebourne) Date: Sun, 13 Dec 2009 00:17:27 +0000 Subject: Comments on the straw man... In-Reply-To: <4B241CA5.3060305@the-loom.de> References: <15e8b9d20912111117i3850004dne0b391c5669e216a@mail.gmail.com> <4B241CA5.3060305@the-loom.de> Message-ID: <4B243297.9000104@joda.org> Stefan Schulz wrote: > I'm not quite sure, what to make of the strawman proposal. To me, it > rather looks like a quickly sketched technical wishlist for lambda > expressions, especially due to the tutorial style (but I think, that's > somehow what Mark mentions in the first paragraphs). > > As Neal pointed out, there is lots of work to be done before it could be > taken as a serious proposal, and I don't think the strawman being > appropriate in its current state to do this by a rather large group of > people as are on this mailing list, but a reduced number of language and > closure/lambda experts (not implying that I would be qualified as such > an expert). The slightly heated discussion on one of the very most > optional parts "extension methods" IMHO shows the problem in not having > a mature base for common refinement. > > I ask myself, if it would be wiser to pick up the latest version of CfJ > and adopt it to the ideas as written down by Mark. For the start, I > would even put the enhanced syntax for method-like invocation of > function types into the optional section. It seems, too many thoughts > are going into the beauty of syntax before having the base done right. I'd like to effectively second this. Neal's work in CFJ 0.6a (which is in many respects a merger of BGGA and FCM) is the only logical place to start this work. It has had all the difficult issues thought through, and has a prototype that is isn't a million miles away. In fact, I'd go further and say that I struggle to see what the difference is between the concepts in the strawman and the real detail in CFJ (apart from extension methods, which warrant a separate debate). Mark, we have limited time to get this into JDK 7 - is NIH really the right approach here? Stephen From pcj at roundroom.net Sun Dec 13 22:23:54 2009 From: pcj at roundroom.net (Peter Jones) Date: Mon, 14 Dec 2009 01:23:54 -0500 Subject: Serialization In-Reply-To: <20091211053123.08EC7684@eggemoggin.niobe.net> References: <20091211053123.08EC7684@eggemoggin.niobe.net> Message-ID: Hi, On Dec 11, 2009, at 12:31 AM, Mark Reinhold wrote: >> Date: Thu, 10 Dec 2009 23:20:51 +0100 >> From: Patrick Wright > >> May we assume that there will be nothing about how closures are >> implemented that would prevent fields of function types in >> serializable classes? > > Good question; I hadn't yet thought about this issue. > > For a closure to be serializable would require all the values it > references to be serializable, including "this" if it captures its > enclosing instance. If that's true then offhand I don't see any > other problems and it should "just work". > > (Serialization is tricky though, so I may well be missing something.) I expect that there would be the issue that is also a problem with serializing instances of anonymous classes today: that the binary names of the classes are neither JLS-determined nor very stable across edits/recompiles. Serialization represents an object's code by its class's binary name, but these things won't have overt names. Moreover, the set of a closure's serializable fields seems likely to be less stable in practice compared to a normally-declared class. And I don't see how you could specify any of the usual customizations to serialized form or behavior (transient, readObject, etc.). What these issues suggest to me is that in cases where the writing and the reading code are from the exact same compilation of sources, then perhaps serialization of closures could work and be useful-- but I don't see it working in the more general case of communication across an API contract. And of course, for it to just work, the closure object's class would have to implement Serializable. -- Peter From david.goodenough at linkchoose.co.uk Mon Dec 14 04:30:41 2009 From: david.goodenough at linkchoose.co.uk (David Goodenough) Date: Mon, 14 Dec 2009 12:30:41 +0000 Subject: Straw man section 7: Method References Message-ID: <200912141230.41191.david.goodenough@linkchoose.co.uk> I realise that this section is TBD, but can I ask whether Field References could also be considered at the same time. I realise that they are not really part of closures, but once the basic syntax is in place for Method References then Field References are a simple extension. I can outline why I think it important to do Field References, but if you regard it as totally out of court there is little point in starting. I would however be very keen to help if this could be added, and I believe that it would benefit Java to add this functionality. It is not a large change, there are no JVM changes required and only one extra library class required of which I already have a prototype. David From pbenedict at apache.org Mon Dec 14 06:26:10 2009 From: pbenedict at apache.org (Paul Benedict) Date: Mon, 14 Dec 2009 08:26:10 -0600 Subject: Straw man section 7: Method References In-Reply-To: <200912141230.41191.david.goodenough@linkchoose.co.uk> References: <200912141230.41191.david.goodenough@linkchoose.co.uk> Message-ID: David, I find your suggestion interesting. If # helps grab a method literal, what syntax can grab a field literal? Do you have anything in mind? Paul On Mon, Dec 14, 2009 at 6:30 AM, David Goodenough wrote: > I realise that this section is TBD, but can I ask whether Field References > could also be considered at the same time. ?I realise that they are not really > part of closures, but once the basic syntax is in place for Method References > then Field References are a simple extension. > > I can outline why I think it important to do Field References, but if you > regard it as totally out of court there is little point in starting. ?I would > however be very keen to help if this could be added, and I believe that > it would benefit Java to add this functionality. It is not a large change, > there are no JVM changes required and only one extra library > class required of which I already have a prototype. > > David > > From i30817 at gmail.com Mon Dec 14 07:02:34 2009 From: i30817 at gmail.com (Paulo Levi) Date: Mon, 14 Dec 2009 15:02:34 +0000 Subject: Can extension methods be overriden? Message-ID: <212322090912140702m64ed6629h6622789dba348fae@mail.gmail.com> When i thought about this a while ago it seemed obvious that extension methods would be methods that didn't depend on any non-public methods or any state (since they are to be used in interfaces). Many times, while using the public methods of a interface is possible to implement a feature, using it efficiently requires using internal structures of the implementation class. (doing this requires that extension methods can be overriden). A example is CharSequence and the getChars method (that exists on all (?) classes that implement it, but not on the interface, but could be implemented inefficiently by using charAt). BTW if extension methods are in, that is one of the alterations i would like to see. From david.goodenough at linkchoose.co.uk Mon Dec 14 07:16:31 2009 From: david.goodenough at linkchoose.co.uk (David Goodenough) Date: Mon, 14 Dec 2009 15:16:31 +0000 Subject: Straw man section 7: Method References In-Reply-To: References: <200912141230.41191.david.goodenough@linkchoose.co.uk> Message-ID: <200912141516.31121.david.goodenough@linkchoose.co.uk> Paul, As understand it, # only helps grab a method literal if the thing to the right of the # is a method, if it were a field, then if would grab a field literal. I am not really sure having read the two links provided in section 7 that I see how method literals are encoded in BGCA, but in FCM it would be:- rhs[#lhs] where rhs is either an object or a class, and you have a chain of methods or fields on the right. This allows you to create a reference to any existing method or field. Allowing a chain of methods at first sight might seem odd, but it is certainly needed on the case of field references. Actually allowing it in the case of a method reference might obviate the need to have field references at all, so if you had a an object foo of type Foo with a field bar of type Bar which in turn had a field jim of type String then to get at the field in a manipulatable way one could either encode:- FieldRef ref = foo#bar#jim; or MethodRef ref = foo#getBar()#getJim(); This latter has the merit of not need the bending of the visibility rules, so if bar or jim are private fields, but their getters are public the former needs rules rather different to the normal "." rules, while the second form does not. The first version requires an assumption that while the field might be private, the getter is public even though it is not actually the getter that is referenced. The second form looks less intuative to use, but may be better. It is necessary to use a FieldRef or MethodRef (for want of better names) rather than Field and Method directly so that compound access (multiple #s) can be used. This is necessary in many of the field referencing cases I could produce, but not in the case of simple method references that were envisenged in the original Method Reference proposals. A Field/MethodRef also simplifies the question as to whether it is a bound reference or an Unbound one, in the second example above the unbound equivalient is Foo#getBar()#getJim() where this can be applied to any object of class Foo and you do not need an instance at the time that you create the reference. David On Monday 14 December 2009, Paul Benedict wrote: > David, > > I find your suggestion interesting. If # helps grab a method literal, > what syntax can grab a field literal? Do you have anything in mind? > > Paul > > On Mon, Dec 14, 2009 at 6:30 AM, David Goodenough > > wrote: > > I realise that this section is TBD, but can I ask whether Field > > References could also be considered at the same time. I realise that > > they are not really part of closures, but once the basic syntax is in > > place for Method References then Field References are a simple extension. > > > > I can outline why I think it important to do Field References, but if you > > regard it as totally out of court there is little point in starting. I > > would however be very keen to help if this could be added, and I believe > > that it would benefit Java to add this functionality. It is not a large > > change, there are no JVM changes required and only one extra library > > class required of which I already have a prototype. > > > > David > From markmahieu at googlemail.com Mon Dec 14 07:17:45 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Mon, 14 Dec 2009 15:17:45 +0000 Subject: Straw man section 7: Method References In-Reply-To: References: <200912141230.41191.david.goodenough@linkchoose.co.uk> Message-ID: <2AB6CD8A-9E75-4BF1-B5CB-C060AAA6493B@googlemail.com> Before diving into syntax, I think I might first like to know what a field literal is supposed to be in this context - for starters, what type does it have (is it the same as in FCM, or something else?), and how does it relate to lambdas? Mark On 14 Dec 2009, at 14:26, Paul Benedict wrote: > David, > > I find your suggestion interesting. If # helps grab a method literal, > what syntax can grab a field literal? Do you have anything in mind? > > Paul > > On Mon, Dec 14, 2009 at 6:30 AM, David Goodenough > wrote: >> I realise that this section is TBD, but can I ask whether Field References >> could also be considered at the same time. I realise that they are not really >> part of closures, but once the basic syntax is in place for Method References >> then Field References are a simple extension. >> >> I can outline why I think it important to do Field References, but if you >> regard it as totally out of court there is little point in starting. I would >> however be very keen to help if this could be added, and I believe that >> it would benefit Java to add this functionality. It is not a large change, >> there are no JVM changes required and only one extra library >> class required of which I already have a prototype. >> >> David >> >> > From neal at gafter.com Mon Dec 14 07:38:28 2009 From: neal at gafter.com (Neal Gafter) Date: Mon, 14 Dec 2009 07:38:28 -0800 Subject: Extension methods vs arrays... Message-ID: <15e8b9d20912140738m44087a79wbc36bed058f613ed@mail.gmail.com> The primary motivation for extension methods appears to be more convenient expression of concurrent operations on aggregates. Although I see much more potential for them, I don't see how the current strawman can be used to define (for example) a "reduce" operation on arrays. That is, how would we express this *int reduce(int[] array, #int(int,int) combine) { ... } * as an extension method, so it could be used to sum the data in the array * * *int[] data = ...; int result = data.reduce(#(**int **x, **int **y)x+y);** * Cheers, Neal From david.goodenough at linkchoose.co.uk Mon Dec 14 07:38:58 2009 From: david.goodenough at linkchoose.co.uk (David Goodenough) Date: Mon, 14 Dec 2009 15:38:58 +0000 Subject: Straw man section 7: Method References In-Reply-To: <2AB6CD8A-9E75-4BF1-B5CB-C060AAA6493B@googlemail.com> References: <200912141230.41191.david.goodenough@linkchoose.co.uk> <2AB6CD8A-9E75-4BF1-B5CB-C060AAA6493B@googlemail.com> Message-ID: <200912141538.58409.david.goodenough@linkchoose.co.uk> A field reference is a means to get rid of String literal field names from places like Beans, Beans Bindings, and JPA. String literal fields are uncheckable by compilers/IDEs, IDEs can not refactor them and can not provide context assist for them. The type of a Field Reference would either (as in the FCM case for a Method Reference) be a java.lang.reflect.Field, or if you read my first reply to Paul you will see that I would suggest that compound #s are really what is needed, in which case a simple wrapper class (say FieldRef/MethodRef) would be needed. Its relationship to lambda, or rather closures, is I grant indirect. It is that in many respects Fields and Methods are similar, or rather Field and Method objects are similar (in the way they are acquired at least) and so if one was being done I asked whether the other could be considered given that the heavy lifting of syntax change would already be in place. David On Monday 14 December 2009, Mark Mahieu wrote: > Before diving into syntax, I think I might first like to know what a field > literal is supposed to be in this context - for starters, what type does > it have (is it the same as in FCM, or something else?), and how does it > relate to lambdas? > > Mark > > On 14 Dec 2009, at 14:26, Paul Benedict wrote: > > David, > > > > I find your suggestion interesting. If # helps grab a method literal, > > what syntax can grab a field literal? Do you have anything in mind? > > > > Paul > > > > On Mon, Dec 14, 2009 at 6:30 AM, David Goodenough > > > > wrote: > >> I realise that this section is TBD, but can I ask whether Field > >> References could also be considered at the same time. I realise that > >> they are not really part of closures, but once the basic syntax is in > >> place for Method References then Field References are a simple > >> extension. > >> > >> I can outline why I think it important to do Field References, but if > >> you regard it as totally out of court there is little point in starting. > >> I would however be very keen to help if this could be added, and I > >> believe that it would benefit Java to add this functionality. It is not > >> a large change, there are no JVM changes required and only one extra > >> library > >> class required of which I already have a prototype. > >> > >> David > From i30817 at gmail.com Mon Dec 14 07:53:58 2009 From: i30817 at gmail.com (Paulo Levi) Date: Mon, 14 Dec 2009 15:53:58 +0000 Subject: Extension methods vs arrays... In-Reply-To: <15e8b9d20912140738m44087a79wbc36bed058f613ed@mail.gmail.com> References: <15e8b9d20912140738m44087a79wbc36bed058f613ed@mail.gmail.com> Message-ID: <212322090912140753x6bb066cdq84c8d257a0c9ed5d@mail.gmail.com> That would be very nice. From scolebourne at joda.org Mon Dec 14 08:14:24 2009 From: scolebourne at joda.org (Stephen Colebourne) Date: Mon, 14 Dec 2009 16:14:24 +0000 Subject: Straw man section 7: Method References In-Reply-To: <200912141538.58409.david.goodenough@linkchoose.co.uk> References: <200912141230.41191.david.goodenough@linkchoose.co.uk> <2AB6CD8A-9E75-4BF1-B5CB-C060AAA6493B@googlemail.com> <200912141538.58409.david.goodenough@linkchoose.co.uk> Message-ID: <4b4f45e00912140814n3c9cdf41m380e00d4097b08f1@mail.gmail.com> 2009/12/14 David Goodenough : > A field reference is a means to get rid of String literal field names from > places like Beans, Beans Bindings, and JPA. ?String literal fields are > uncheckable by compilers/IDEs, IDEs can not refactor them and can > not provide context assist for them. You are talking about Method and Field *literals*, not Method *references*. See FCM for the distinction. Mark Reinhold is only considering adding Method *references* to JDK 7 at the moment. Stephen From scolebourne at joda.org Mon Dec 14 08:18:51 2009 From: scolebourne at joda.org (Stephen Colebourne) Date: Mon, 14 Dec 2009 16:18:51 +0000 Subject: Can extension methods be overriden? In-Reply-To: <212322090912140702m64ed6629h6622789dba348fae@mail.gmail.com> References: <212322090912140702m64ed6629h6622789dba348fae@mail.gmail.com> Message-ID: <4b4f45e00912140818o3402cfa3gca8f0b6ec789f71e@mail.gmail.com> 2009/12/14 Paulo Levi : > Many times, while using the public methods of a interface is possible to > implement a feature, using it efficiently requires using internal structures > of the implementation class. I'd like it to be a goal to permit a class to "implement" an extension method more efficiently than the default implementation. However, I haven't considered how this could be achieved or even if its possible. Stephen From scolebourne at joda.org Mon Dec 14 08:21:13 2009 From: scolebourne at joda.org (Stephen Colebourne) Date: Mon, 14 Dec 2009 16:21:13 +0000 Subject: Can extension methods be overriden? In-Reply-To: <212322090912140702m64ed6629h6622789dba348fae@mail.gmail.com> References: <212322090912140702m64ed6629h6622789dba348fae@mail.gmail.com> Message-ID: <4b4f45e00912140821n67f7499dwe99ece5ca1d46a65@mail.gmail.com> 2009/12/14 Paulo Levi : > When i thought about this a while ago it seemed obvious that extension > methods would be methods that didn't depend on any non-public methods or any > state (since they are to be used in interfaces). I'd like it to be a goal to permit a class to "implement" an extension method more efficiently than the default implementation. However, I haven't considered how this could be achieved or even if its possible. Stephen PS. This is a resend, as for the umpteenth time I replied to the person rather than the list. My Christmas wish is OpenJDK mailing lists that have reply-to back to the list!!! From mthornton at optrak.co.uk Mon Dec 14 08:23:00 2009 From: mthornton at optrak.co.uk (Mark Thornton) Date: Mon, 14 Dec 2009 16:23:00 +0000 Subject: Can extension methods be overriden? In-Reply-To: <4b4f45e00912140821n67f7499dwe99ece5ca1d46a65@mail.gmail.com> References: <212322090912140702m64ed6629h6622789dba348fae@mail.gmail.com> <4b4f45e00912140821n67f7499dwe99ece5ca1d46a65@mail.gmail.com> Message-ID: <4B266664.6010805@optrak.co.uk> Stephen Colebourne wrote: > 2009/12/14 Paulo Levi : > >> When i thought about this a while ago it seemed obvious that extension >> methods would be methods that didn't depend on any non-public methods or any >> state (since they are to be used in interfaces). >> > > I'd like it to be a goal to permit a class to "implement" an extension > method more efficiently than the default implementation. However, I > haven't considered how this could be achieved or even if its possible. > I think that takes it into the realm of traits, which is possible but probably out of scope. > Stephen > > PS. This is a resend, as for the umpteenth time I replied to the > person rather than the list. My Christmas wish is OpenJDK mailing > lists that have reply-to back to the list!!! > > I second that (though on this occasion your first message also reached the list). Mark From david.goodenough at linkchoose.co.uk Mon Dec 14 09:00:27 2009 From: david.goodenough at linkchoose.co.uk (David Goodenough) Date: Mon, 14 Dec 2009 17:00:27 +0000 Subject: Straw man section 7: Method References In-Reply-To: <4b4f45e00912140814n3c9cdf41m380e00d4097b08f1@mail.gmail.com> References: <200912141230.41191.david.goodenough@linkchoose.co.uk> <200912141538.58409.david.goodenough@linkchoose.co.uk> <4b4f45e00912140814n3c9cdf41m380e00d4097b08f1@mail.gmail.com> Message-ID: <200912141700.27821.david.goodenough@linkchoose.co.uk> On Monday 14 December 2009, Stephen Colebourne wrote: > 2009/12/14 David Goodenough : > > A field reference is a means to get rid of String literal field names > > from places like Beans, Beans Bindings, and JPA. String literal fields > > are uncheckable by compilers/IDEs, IDEs can not refactor them and can not > > provide context assist for them. > > You are talking about Method and Field *literals*, not Method > *references*. See FCM for the distinction. > > Mark Reinhold is only considering adding Method *references* to JDK 7 > at the moment. > > Stephen > Having reread the FCM spec, I can not see that what I am createing is not a Method Reference. Its content might be populated with a literal syntax, but it has to be generated somehow, and I am not really that bothered by how it is generated, as long as it can be in a clean and checkable way (checkability being the vital component, cleanliness being merely desirable). In fact one of the destinctions that I get from reading the FCM docs is that they are more than just a Field (or Method). Section A3 for instance talks about a class which contains the object that this Method/Field is bound do, and I would be using a very similar method. But then of course I may have missed something in reading the FCM David From grev at miginfocom.com Mon Dec 14 09:07:43 2009 From: grev at miginfocom.com (Mikael Grev) Date: Mon, 14 Dec 2009 18:07:43 +0100 Subject: Fwd: Comments on the straw man... References: <72738E79-A9CA-4913-9606-355D061486CE@miginfocom.com> Message-ID: <6D0BCB76-0433-4E3B-B5B2-650BD1881443@miginfocom.com> I second this, however, not primarily from a technical point of view. Many parts in proposals such as Cfj and straw-man are easy to debate. What it harder though is finding consensus for the simple reason that there's no single answer that it right. It all boils down to opinions and preferences. Some of us can handle the full power of BGGA and some will never be safe beyond CICE. There is no way to know what is "right" for Java, and even after this is released we can never tell because we don't have the results for the other proposals. The grass will always be greener on the other side. So, as long as a proposal is technically well though out and that the complexity is deemed "right", what will impact success more than anything is risk. Managing risk is key, we all know that, at least if you have been a project manager of some sort. Even though we are all techie geeks that want to dig in deep in details, project risk needs to be the deciding factor for volatile projects such as this. The risk of creating yet another proposal at this stage is very high. Discussions may turn bad, key people might quit turn their back on it, or something else unexpected might happen. Because of this alone, I would like to put my vote on Cfj. The risk is much lower. All key players except Sun seem to be able to accept it. The spec is solid and the complexity is in the middle of the field, probably hitting just about right on the bell curve for all but the most junior developers. Only pride on Sun's part (NIH) can make this into something that will either not make Java 7 or push it even further into the future. Java 7 needs this and it need to be out asap. Time is of the essence, much more so than subjective syntax preferences. Cheers, Mikael Mikael Grev Systems Architect MiG InfoCom AB S:t Olofsg 28a, 3tr 753 32 Uppsala Sweden On Dec 12, 2009, at 23:43 PM, Stefan Schulz wrote: > Just some additional cents ... > > I'm not quite sure, what to make of the strawman proposal. To me, it > rather looks like a quickly sketched technical wishlist for lambda > expressions, especially due to the tutorial style (but I think, that's > somehow what Mark mentions in the first paragraphs). > > As Neal pointed out, there is lots of work to be done before it could be > taken as a serious proposal, and I don't think the strawman being > appropriate in its current state to do this by a rather large group of > people as are on this mailing list, but a reduced number of language and > closure/lambda experts (not implying that I would be qualified as such > an expert). The slightly heated discussion on one of the very most > optional parts "extension methods" IMHO shows the problem in not having > a mature base for common refinement. > > I ask myself, if it would be wiser to pick up the latest version of CfJ > and adopt it to the ideas as written down by Mark. For the start, I > would even put the enhanced syntax for method-like invocation of > function types into the optional section. It seems, too many thoughts > are going into the beauty of syntax before having the base done right. > > Stefan From neal at gafter.com Mon Dec 14 09:16:04 2009 From: neal at gafter.com (Neal Gafter) Date: Mon, 14 Dec 2009 09:16:04 -0800 Subject: Comments on the straw man... In-Reply-To: <15e8b9d20912111117i3850004dne0b391c5669e216a@mail.gmail.com> References: <15e8b9d20912111117i3850004dne0b391c5669e216a@mail.gmail.com> Message-ID: <15e8b9d20912140916t635e33acofec683efcb1b1b0c@mail.gmail.com> On Fri, Dec 11, 2009 at 11:17 AM, Neal Gafter wrote: > 4. Variable Capture. Needs more refinement about what is meant by > "effectively final". Despite the strawman's reference, the JLS DA/DU rules > can't be used for this purpose; a new and separate dataflow specification > would be required. That is likely to be comparable in size to the existing > JLS3 DA/DU analysis and require a significant effort to specify and > implement correctly. It wasn't as bad as I feared. First, extend the definition of *definitely unassigned* so it is allowed to be applied to non-final variables. Then: A local variable is *effectively final* if it is never the target of an assignment expression except where *definitely unassigned*. Cheers, Neal From scolebourne at joda.org Mon Dec 14 09:40:32 2009 From: scolebourne at joda.org (Stephen Colebourne) Date: Mon, 14 Dec 2009 17:40:32 +0000 Subject: Straw man section 7: Method References In-Reply-To: <200912141700.27821.david.goodenough@linkchoose.co.uk> References: <200912141230.41191.david.goodenough@linkchoose.co.uk> <200912141538.58409.david.goodenough@linkchoose.co.uk> <4b4f45e00912140814n3c9cdf41m380e00d4097b08f1@mail.gmail.com> <200912141700.27821.david.goodenough@linkchoose.co.uk> Message-ID: <4b4f45e00912140940y1439d7a5qdb5a77909b2e5e79@mail.gmail.com> 2009/12/14 David Goodenough : > Having reread the FCM spec, I can not see that what I am createing is > not a Method Reference. ?Its content might be populated with a literal > syntax, but it has to be generated somehow, and I am not really that > bothered by how it is generated, as long as it can be in a clean and > checkable way (checkability being the vital component, cleanliness > being merely desirable). > > In fact one of the destinctions that I get from reading the FCM docs is > that they are more than just a Field (or Method). ?Section A3 for instance > talks about a class which contains the object that this Method/Field is > bound do, and I would be using a very similar method. Field literals are of the type reflect.Field. Method literals are of the type reflect.Method. Method references are of the function type. One of the issues with FCM was how to use the same syntax to refer to objects of two different types. I understand this concern drives the omission of field/method literals (which are undoubtably useful, but optional for the Lambda requirements). Stephen From pdoubleya at gmail.com Mon Dec 14 11:41:35 2009 From: pdoubleya at gmail.com (Patrick Wright) Date: Mon, 14 Dec 2009 20:41:35 +0100 Subject: Comments on the straw man... In-Reply-To: <6D0BCB76-0433-4E3B-B5B2-650BD1881443@miginfocom.com> References: <72738E79-A9CA-4913-9606-355D061486CE@miginfocom.com> <6D0BCB76-0433-4E3B-B5B2-650BD1881443@miginfocom.com> Message-ID: <64efa1ba0912141141n6d544313o65c97ddc32800a91@mail.gmail.com> > Only pride on Sun's part (NIH) can make this into something that will either not make Java 7 or push it even further into the future. I'd like to suggest that we try to keep the discussion focused on the technical merits of the proposals. "NIH" has come up twice in this thread already. I'd prefer if we all just assume that everyone involved, wherever they are working, are aiming to do the right thing and the best thing for the platform. What we chat about over a beer, well, then it's deer season. Cheers Patrick From david.goodenough at linkchoose.co.uk Mon Dec 14 11:56:49 2009 From: david.goodenough at linkchoose.co.uk (David Goodenough) Date: Mon, 14 Dec 2009 19:56:49 +0000 Subject: Straw man section 7: Method References In-Reply-To: <4b4f45e00912140940y1439d7a5qdb5a77909b2e5e79@mail.gmail.com> References: <200912141230.41191.david.goodenough@linkchoose.co.uk> <200912141700.27821.david.goodenough@linkchoose.co.uk> <4b4f45e00912140940y1439d7a5qdb5a77909b2e5e79@mail.gmail.com> Message-ID: <200912141956.50610.david.goodenough@linkchoose.co.uk> On Monday 14 December 2009, Stephen Colebourne wrote: > 2009/12/14 David Goodenough : > > Having reread the FCM spec, I can not see that what I am createing is > > not a Method Reference. Its content might be populated with a literal > > syntax, but it has to be generated somehow, and I am not really that > > bothered by how it is generated, as long as it can be in a clean and > > checkable way (checkability being the vital component, cleanliness > > being merely desirable). > > > > In fact one of the destinctions that I get from reading the FCM docs is > > that they are more than just a Field (or Method). Section A3 for > > instance talks about a class which contains the object that this > > Method/Field is bound do, and I would be using a very similar method. > > Field literals are of the type reflect.Field. > Method literals are of the type reflect.Method. > Method references are of the function type. > > One of the issues with FCM was how to use the same syntax to refer to > objects of two different types. I understand this concern drives the > omission of field/method literals (which are undoubtably useful, but > optional for the Lambda requirements). > > Stephen > Well its the Method or Field Reference that I am interested in, not the way in which it is generated. Obviously it needs to be generated somehow in a compiler checkable way, but I do not mind how. So what I need to do is understand how it is proposed that they are generated and then then how what is proposed might be extended to Field References. David From alex.blewitt at gmail.com Mon Dec 14 12:07:30 2009 From: alex.blewitt at gmail.com (Alex Blewitt) Date: Mon, 14 Dec 2009 20:07:30 +0000 Subject: Method calls vs lambda calls Message-ID: <7783BF2B-98D6-4E01-8B97-CC19B139AE92@gmail.com> public class Example { public int fortyTwo() { return 6*9; } public void run() { System.out.println(fortyTwo()) #int() fortyTwo = #int() { return 42; } System.out.println(fortyTwo()) } } What's the result on the output here? From pbenedict at apache.org Mon Dec 14 12:10:24 2009 From: pbenedict at apache.org (Paul Benedict) Date: Mon, 14 Dec 2009 14:10:24 -0600 Subject: Comments on the straw man... In-Reply-To: <64efa1ba0912141141n6d544313o65c97ddc32800a91@mail.gmail.com> References: <72738E79-A9CA-4913-9606-355D061486CE@miginfocom.com> <6D0BCB76-0433-4E3B-B5B2-650BD1881443@miginfocom.com> <64efa1ba0912141141n6d544313o65c97ddc32800a91@mail.gmail.com> Message-ID: Patrick, On Mon, Dec 14, 2009 at 1:41 PM, Patrick Wright wrote: >> Only pride on Sun's part (NIH) can make this into something that will either not make Java 7 or push it even further into the future. > > I'd like to suggest that we try to keep the discussion focused on the > technical merits of the proposals. "NIH" has come up twice in this > thread already. I'd prefer if we all just assume that everyone > involved, wherever they are working, are aiming to do the right thing > and the best thing for the platform. What we chat about over a beer, > well, then it's deer season. > It's my opinion that the "NIH" comments came into existence because Mark's document -- I enjoyed reading it -- is viewed as immature compared to other proposals. (The immaturity is intentional, by the way, being a "straw man".) Eventually, everyone must ask themselves how best to spend one's time. Answer it how you will, but I think others don't want to start from square one again. PS: My opinion is not a vote for or against Mark's document; just offering my perspective. Paul From pdoubleya at gmail.com Mon Dec 14 12:17:30 2009 From: pdoubleya at gmail.com (Patrick Wright) Date: Mon, 14 Dec 2009 21:17:30 +0100 Subject: Comments on the straw man... In-Reply-To: References: <72738E79-A9CA-4913-9606-355D061486CE@miginfocom.com> <6D0BCB76-0433-4E3B-B5B2-650BD1881443@miginfocom.com> <64efa1ba0912141141n6d544313o65c97ddc32800a91@mail.gmail.com> Message-ID: <64efa1ba0912141217j5d9ae1eag5205fe1a951c669@mail.gmail.com> Paul The term "not-invented-here" is generally used as a soft slur. It also implies that the speaker (who's claiming NIH) knows something about the intentions of the people they are accusing of NIH. I think it's a (mild) form of ad hominem attack or criticism. I think we should just drop it. We can criticize any of the proposals on technical grounds, and that's the reason we have a public list, to gather input far and wide, but on technical grounds. There's been plenty of criticism of the various parties, whether people or corporations, related to their lack of action/decision/commitment related to closures. I don't think we need that here. There are plenty of other forums for that kind of talk. Regards Patrick From schulz at the-loom.de Mon Dec 14 12:36:12 2009 From: schulz at the-loom.de (Stefan Schulz) Date: Mon, 14 Dec 2009 21:36:12 +0100 Subject: Method calls vs lambda calls In-Reply-To: <7783BF2B-98D6-4E01-8B97-CC19B139AE92@gmail.com> References: <7783BF2B-98D6-4E01-8B97-CC19B139AE92@gmail.com> Message-ID: <4B26A1BC.9010206@the-loom.de> Am 14.12.2009 21:07, schrieb Alex Blewitt: > public class Example { > public int fortyTwo() { > return 6*9; > } > public void run() { > System.out.println(fortyTwo()) > #int() fortyTwo = #int() { return 42; } > System.out.println(fortyTwo()) > } > } > > What's the result on the output here? I'd suspect a compile error due to defining two "methods" having the same signature in the same scope. From neal at gafter.com Mon Dec 14 12:37:23 2009 From: neal at gafter.com (Neal Gafter) Date: Mon, 14 Dec 2009 12:37:23 -0800 Subject: Method calls vs lambda calls In-Reply-To: <4B26A1BC.9010206@the-loom.de> References: <7783BF2B-98D6-4E01-8B97-CC19B139AE92@gmail.com> <4B26A1BC.9010206@the-loom.de> Message-ID: <15e8b9d20912141237y24a64227yab9e0756244df8be@mail.gmail.com> I'd expect the latter to shadow the former (it is in a nested scope, not the same scope). On Mon, Dec 14, 2009 at 12:36 PM, Stefan Schulz wrote: > Am 14.12.2009 21:07, schrieb Alex Blewitt: > > public class Example { > > public int fortyTwo() { > > return 6*9; > > } > > public void run() { > > System.out.println(fortyTwo()) > > #int() fortyTwo = #int() { return 42; } > > System.out.println(fortyTwo()) > > } > > } > > > > What's the result on the output here? > > I'd suspect a compile error due to defining two "methods" having the > same signature in the same scope. > > From schulz at the-loom.de Mon Dec 14 12:51:45 2009 From: schulz at the-loom.de (Stefan Schulz) Date: Mon, 14 Dec 2009 21:51:45 +0100 Subject: Method calls vs lambda calls In-Reply-To: <15e8b9d20912141237y24a64227yab9e0756244df8be@mail.gmail.com> References: <7783BF2B-98D6-4E01-8B97-CC19B139AE92@gmail.com> <4B26A1BC.9010206@the-loom.de> <15e8b9d20912141237y24a64227yab9e0756244df8be@mail.gmail.com> Message-ID: <4B26A561.3050002@the-loom.de> You're right, of course. Same as with instance and local variables. Am 14.12.2009 21:37, schrieb Neal Gafter: > I'd expect the latter to shadow the former (it is in a nested scope, not > the same scope). > > On Mon, Dec 14, 2009 at 12:36 PM, Stefan Schulz > wrote: > > Am 14.12.2009 21:07, schrieb Alex Blewitt: > > public class Example { > > public int fortyTwo() { > > return 6*9; > > } > > public void run() { > > System.out.println(fortyTwo()) > > #int() fortyTwo = #int() { return 42; } > > System.out.println(fortyTwo()) > > } > > } > > > > What's the result on the output here? > > I'd suspect a compile error due to defining two "methods" having the > same signature in the same scope. > > From jjb at google.com Mon Dec 14 23:04:00 2009 From: jjb at google.com (Joshua Bloch) Date: Mon, 14 Dec 2009 23:04:00 -0800 Subject: Method calls vs lambda calls In-Reply-To: <4B26A561.3050002@the-loom.de> References: <7783BF2B-98D6-4E01-8B97-CC19B139AE92@gmail.com> <4B26A1BC.9010206@the-loom.de> <15e8b9d20912141237y24a64227yab9e0756244df8be@mail.gmail.com> <4B26A561.3050002@the-loom.de> Message-ID: <17b2302a0912142304x5e82ef60jabe569d527789b11@mail.gmail.com> I think that perhaps some explicit syntax should be required when invoking a function object. That would prevent this sort of confusion. Josh On Mon, Dec 14, 2009 at 12:51 PM, Stefan Schulz wrote: > You're right, of course. > Same as with instance and local variables. > > Am 14.12.2009 21:37, schrieb Neal Gafter: > > I'd expect the latter to shadow the former (it is in a nested scope, not > > the same scope). > > > > On Mon, Dec 14, 2009 at 12:36 PM, Stefan Schulz > > wrote: > > > > Am 14.12.2009 21:07, schrieb Alex Blewitt: > > > public class Example { > > > public int fortyTwo() { > > > return 6*9; > > > } > > > public void run() { > > > System.out.println(fortyTwo()) > > > #int() fortyTwo = #int() { return 42; } > > > System.out.println(fortyTwo()) > > > } > > > } > > > > > > What's the result on the output here? > > > > I'd suspect a compile error due to defining two "methods" having the > > same signature in the same scope. > > > > > > From markmahieu at googlemail.com Mon Dec 14 23:19:19 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Tue, 15 Dec 2009 07:19:19 +0000 Subject: Method calls vs lambda calls In-Reply-To: <17b2302a0912142304x5e82ef60jabe569d527789b11@mail.gmail.com> References: <7783BF2B-98D6-4E01-8B97-CC19B139AE92@gmail.com> <4B26A1BC.9010206@the-loom.de> <15e8b9d20912141237y24a64227yab9e0756244df8be@mail.gmail.com> <4B26A561.3050002@the-loom.de> <17b2302a0912142304x5e82ef60jabe569d527789b11@mail.gmail.com> Message-ID: <52A7A9BC-F574-4721-91C3-1BDADCD926B5@googlemail.com> Same here, not least because I think there's value in encouraging a certain distinction in programmers' minds between methods and functions. Many of the earlier conversations about closures became unnecessarily confused because, I believe, people were immediately translating them in their minds into anonymous classes and methods, leading to a mental mismatch of semantics around aspects like scope. Mark On 15 Dec 2009, at 07:04, Joshua Bloch wrote: > I think that perhaps some explicit syntax should be required when invoking a > function object. That would prevent this sort of confusion. > > Josh > > On Mon, Dec 14, 2009 at 12:51 PM, Stefan Schulz wrote: > >> You're right, of course. >> Same as with instance and local variables. >> >> Am 14.12.2009 21:37, schrieb Neal Gafter: >>> I'd expect the latter to shadow the former (it is in a nested scope, not >>> the same scope). >>> >>> On Mon, Dec 14, 2009 at 12:36 PM, Stefan Schulz >> > wrote: >>> >>> Am 14.12.2009 21:07, schrieb Alex Blewitt: >>>> public class Example { >>>> public int fortyTwo() { >>>> return 6*9; >>>> } >>>> public void run() { >>>> System.out.println(fortyTwo()) >>>> #int() fortyTwo = #int() { return 42; } >>>> System.out.println(fortyTwo()) >>>> } >>>> } >>>> >>>> What's the result on the output here? >>> >>> I'd suspect a compile error due to defining two "methods" having the >>> same signature in the same scope. >>> >>> >> >> > From grev at miginfocom.com Mon Dec 14 23:32:57 2009 From: grev at miginfocom.com (Mikael Grev) Date: Tue, 15 Dec 2009 08:32:57 +0100 Subject: Method calls vs lambda calls In-Reply-To: <17b2302a0912142304x5e82ef60jabe569d527789b11@mail.gmail.com> References: <7783BF2B-98D6-4E01-8B97-CC19B139AE92@gmail.com> <4B26A1BC.9010206@the-loom.de> <15e8b9d20912141237y24a64227yab9e0756244df8be@mail.gmail.com> <4B26A561.3050002@the-loom.de> <17b2302a0912142304x5e82ef60jabe569d527789b11@mail.gmail.com> Message-ID: Isn't this comparable to the problem of hiding a field with a local? I mean complexity wise. And I think the times you happen to use the same local name as a field is a lot more common. If so I think that it will be enough that the IDEs are color coding them. Disallow overloaded names is unfortunately not an option since adding new methods would then break code more frequently. Cheers, Mikael On 15 dec 2009, at 08.04, Joshua Bloch wrote: > I think that perhaps some explicit syntax should be required when invoking a > function object. That would prevent this sort of confusion. > > Josh > > On Mon, Dec 14, 2009 at 12:51 PM, Stefan Schulz wrote: > >> You're right, of course. >> Same as with instance and local variables. >> >> Am 14.12.2009 21:37, schrieb Neal Gafter: >>> I'd expect the latter to shadow the former (it is in a nested scope, not >>> the same scope). >>> >>> On Mon, Dec 14, 2009 at 12:36 PM, Stefan Schulz >> > wrote: >>> >>> Am 14.12.2009 21:07, schrieb Alex Blewitt: >>>> public class Example { >>>> public int fortyTwo() { >>>> return 6*9; >>>> } >>>> public void run() { >>>> System.out.println(fortyTwo()) >>>> #int() fortyTwo = #int() { return 42; } >>>> System.out.println(fortyTwo()) >>>> } >>>> } >>>> >>>> What's the result on the output here? >>> >>> I'd suspect a compile error due to defining two "methods" having the >>> same signature in the same scope. >>> >>> >> >> > From jjb at google.com Mon Dec 14 23:46:38 2009 From: jjb at google.com (Joshua Bloch) Date: Mon, 14 Dec 2009 23:46:38 -0800 Subject: Whither extension methods? Message-ID: <17b2302a0912142346h13243ac3wf995be1c021145ef@mail.gmail.com> Doug Lea sent this a couple of days ago, and I think it deserves our consideration: I confess to being a little confused about the rationale for extension > methods. > Suppose we have a Map, and want to some sort of apply-to-each-value > operation. The only reasonable way to do this in parallel is to somehow > splitthe work. But Map has no public methods allowing you to do this -- you > can only get an iterator, which is inherently sequential. Now, if we > could get at the representations, then we could actually do splits for most > java.util maps (at least for the most common ones -- HashMaps, TreeMaps). So > the only way I know for these to be bolted on is to introduce new interfaces > that each of the these existing classes could be changed to implement. Or am > I missing something? > You might want to read Guy Steele's nice talk on related issues at > http://groups.csail.mit.edu/mac/users/gjs/6.945/readings/MITApril2009Steele.pdf > -Doug From howard.lovatt at iee.org Tue Dec 15 03:06:39 2009 From: howard.lovatt at iee.org (Howard Lovatt) Date: Tue, 15 Dec 2009 12:06:39 +0100 Subject: Whither extension methods? Message-ID: <3dd3f56a0912150306m26f065fat882248d955524054@mail.gmail.com> I agree with this assessment that extension methods won't help for the most interesting case of parallel processing, plus people are going to be very confused by something that has the syntax of dynamic dispatch but the behavior of static dispatch. I would suggest a better alternative is a new set of Collection interfaces, as Josh and Doug suggest, or better still Traits (personal interest in Traits - see http://www.artima.com/weblogs/viewpost.jsp?thread=220916). Note with Traits you can extend the present interfaces and add serial versions of map, reduce, filter, replace, sort, etc. to the trait and then in cases for which you control the source, e.g. JDK stuff, add efficient parallel versions that override the serial version in the Trait. To make the discussion concrete consider adding sort to List via a Trait: public interface List extends Collection { void sort() { Collections.sort( this ); } ... // rest as before } Then in ArrayList you could override sort to be an efficient parallel version: @Override public void sort() { if (size() <= SMALL_PROBLEM) { List.super.sort(); return; } // efficient parallel code that takes advantage of internal implementation details } Note Traits as proposed in the blog referenced above do not need old code to be recompiled to use the new Trait methods; the linker will add missing methods. There is a backward compatibility problem if an existing method in someone's internal implementation clashes with a new Trait method. EG if someone had an implementation of List that added "List sort()" then the linker could not add "void sort()", in such a case a linking error would occur. This same issue occurs with extension methods. -- Howard. From mthornton at optrak.co.uk Tue Dec 15 03:16:11 2009 From: mthornton at optrak.co.uk (Mark Thornton) Date: Tue, 15 Dec 2009 11:16:11 +0000 Subject: Whither extension methods? In-Reply-To: <3dd3f56a0912150306m26f065fat882248d955524054@mail.gmail.com> References: <3dd3f56a0912150306m26f065fat882248d955524054@mail.gmail.com> Message-ID: <4B276FFB.6020607@optrak.co.uk> Howard Lovatt wrote: > Note Traits as proposed in the blog referenced above do not need old code to > be recompiled to use the new Trait methods; the linker will add missing > methods. There is a backward compatibility problem if an existing method in > someone's internal implementation clashes with a new Trait method. EG if > someone had an implementation of List that added "List sort()" then the > linker could not add "void sort()", in such a case a linking error > In Java "List sort()" isn't compatible with "void sort()", but at the JVM level the signature includes the return type. Would this make it possible to resolve such a 'clash' without needing to throw a linking error? Mark Thornton From howard.lovatt at iee.org Tue Dec 15 04:41:18 2009 From: howard.lovatt at iee.org (Howard Lovatt) Date: Tue, 15 Dec 2009 13:41:18 +0100 Subject: Whither extension methods? In-Reply-To: <4B276FFB.6020607@optrak.co.uk> References: <3dd3f56a0912150306m26f065fat882248d955524054@mail.gmail.com> <4B276FFB.6020607@optrak.co.uk> Message-ID: <3dd3f56a0912150441l754d3ce2nb32bfcc8efd8cc4b@mail.gmail.com> This might well be possible, but it would be more work since it is a change to the type system (it would have to infer the method to call from the LHS of an assignment). I suspect this is too big a change to the type system. 2009/12/15 Mark Thornton > Howard Lovatt wrote: > >> Note Traits as proposed in the blog referenced above do not need old code >> to >> be recompiled to use the new Trait methods; the linker will add missing >> methods. There is a backward compatibility problem if an existing method >> in >> someone's internal implementation clashes with a new Trait method. EG if >> someone had an implementation of List that added "List sort()" then the >> linker could not add "void sort()", in such a case a linking error >> >> > In Java "List sort()" isn't compatible with "void sort()", but at the > JVM level the signature includes the return type. Would this make it > possible to resolve such a 'clash' without needing to throw a linking error? > > Mark Thornton > > > > ______________________________________________________________________ > This email has been scanned by the MessageLabs Email Security System. > For more information please visit http://www.messagelabs.com/email______________________________________________________________________ > -- -- Howard. From r.spilker at gmail.com Tue Dec 15 04:42:50 2009 From: r.spilker at gmail.com (Roel Spilker) Date: Tue, 15 Dec 2009 13:42:50 +0100 Subject: Whither extension methods? In-Reply-To: <17b2302a0912142346h13243ac3wf995be1c021145ef@mail.gmail.com> References: <17b2302a0912142346h13243ac3wf995be1c021145ef@mail.gmail.com> Message-ID: Josh, or Doug, Is there also a video or audio recording of Guy Steele's talk? I couldn't easily find it using my favorite search engine :-) Roel On Tue, Dec 15, 2009 at 8:46 AM, Joshua Bloch wrote: > Doug Lea sent this a couple of days ago, and I think it deserves our > consideration: > > I confess to being a little confused about the rationale for extension > > methods. > > > > Suppose we have a Map, and want to some sort of apply-to-each-value > > operation. The only reasonable way to do this in parallel is to somehow > > splitthe work. But Map has no public methods allowing you to do this -- > you > > can only get an iterator, which is inherently sequential. Now, if we > > could get at the representations, then we could actually do splits for > most > > java.util maps (at least for the most common ones -- HashMaps, TreeMaps). > So > > the only way I know for these to be bolted on is to introduce new > interfaces > > that each of the these existing classes could be changed to implement. Or > am > > I missing something? > > > > You might want to read Guy Steele's nice talk on related issues at > > > http://groups.csail.mit.edu/mac/users/gjs/6.945/readings/MITApril2009Steele.pdf > > > > -Doug > > From mthornton at optrak.co.uk Tue Dec 15 05:43:18 2009 From: mthornton at optrak.co.uk (Mark Thornton) Date: Tue, 15 Dec 2009 13:43:18 +0000 Subject: Whither extension methods? In-Reply-To: <3dd3f56a0912150441l754d3ce2nb32bfcc8efd8cc4b@mail.gmail.com> References: <3dd3f56a0912150306m26f065fat882248d955524054@mail.gmail.com> <4B276FFB.6020607@optrak.co.uk> <3dd3f56a0912150441l754d3ce2nb32bfcc8efd8cc4b@mail.gmail.com> Message-ID: <4B279276.2040101@optrak.co.uk> Howard Lovatt wrote: > This might well be possible, but it would be more work since it is a > change to the type system (it would have to infer the method to call > from the LHS of an assignment). I suspect this is too big a change to > the type system. > I was thinking more of byte code which hadn't been recompiled. In this case the linker could allow both methods to coexist. Of course if you did recompile the source with the new definition of List, there would be an error. So binary compatible but not source compatible. Mark Thornton From alex.blewitt at gmail.com Tue Dec 15 05:59:51 2009 From: alex.blewitt at gmail.com (Alex Blewitt) Date: Tue, 15 Dec 2009 13:59:51 +0000 Subject: Method calls vs lambda calls In-Reply-To: References: <7783BF2B-98D6-4E01-8B97-CC19B139AE92@gmail.com> <4B26A1BC.9010206@the-loom.de> <15e8b9d20912141237y24a64227yab9e0756244df8be@mail.gmail.com> <4B26A561.3050002@the-loom.de> <17b2302a0912142304x5e82ef60jabe569d527789b11@mail.gmail.com> Message-ID: <4EC54BD2-4335-482D-A97B-DA06C98393DA@gmail.com> This was, of course, a leading question. Now consider: >>>>> >>>>> public class Example { #int() public fortyTwo = #int() >>>>> { return 42; } >>>>> public int fortyTwo() { >>>>> return 6*9; >>>>> } >>>>> public void run() { >>>>> System.out.println(fortyTwo()) >>>>> } >>>>> } Sent from my (new) iPhone On 15 Dec 2009, at 07:32, Mikael Grev wrote: > Isn't this comparable to the problem of hiding a field with a local? > I mean complexity wise. And I think the times you happen to use the > same local name as a field is a lot more common. > > If so I think that it will be enough that the IDEs are color coding > them. > > Disallow overloaded names is unfortunately not an option since > adding new methods would then break code more frequently. > > Cheers, > Mikael > > > On 15 dec 2009, at 08.04, Joshua Bloch wrote: > >> I think that perhaps some explicit syntax should be required when >> invoking a >> function object. That would prevent this sort of confusion. >> >> Josh >> >> On Mon, Dec 14, 2009 at 12:51 PM, Stefan Schulz > loom.de> wrote: >> >>> You're right, of course. >>> Same as with instance and local variables. >>> >>> Am 14.12.2009 21:37, schrieb Neal Gafter: >>>> I'd expect the latter to shadow the former (it is in a nested >>>> scope, not >>>> the same scope). >>>> >>>> On Mon, Dec 14, 2009 at 12:36 PM, Stefan Schulz >>> > wrote: >>>> >>>> Am 14.12.2009 21:07, schrieb Alex Blewitt: >>>>> public class Example { >>>>> public int fortyTwo() { >>>>> return 6*9; >>>>> } >>>>> public void run() { >>>>> System.out.println(fortyTwo()) >>>>> #int() fortyTwo = #int() { return 42; } >>>>> System.out.println(fortyTwo()) >>>>> } >>>>> } >>>>> >>>>> What's the result on the output here? >>>> >>>> I'd suspect a compile error due to defining two "methods" >>>> having the >>>> same signature in the same scope. >>>> >>>> >>> >>> >> > > From mthornton at optrak.co.uk Tue Dec 15 06:07:47 2009 From: mthornton at optrak.co.uk (Mark Thornton) Date: Tue, 15 Dec 2009 14:07:47 +0000 Subject: Method calls vs lambda calls In-Reply-To: <4EC54BD2-4335-482D-A97B-DA06C98393DA@gmail.com> References: <7783BF2B-98D6-4E01-8B97-CC19B139AE92@gmail.com> <4B26A1BC.9010206@the-loom.de> <15e8b9d20912141237y24a64227yab9e0756244df8be@mail.gmail.com> <4B26A561.3050002@the-loom.de> <17b2302a0912142304x5e82ef60jabe569d527789b11@mail.gmail.com> <4EC54BD2-4335-482D-A97B-DA06C98393DA@gmail.com> Message-ID: <4B279833.5010204@optrak.co.uk> Alex Blewitt wrote: > This was, of course, a leading question. Now consider: > > > > >>>>>> public class Example { #int() public fortyTwo = #int() >>>>>> { return 42; } >>>>>> public int fortyTwo() { >>>>>> return 6*9; >>>>>> } >>>>>> public void run() { >>>>>> System.out.println(fortyTwo()) >>>>>> } >>>>>> } >>>>>> > > > Sent from my (new) iPhone > > A simple solution would be to specify that method valued fields are in the method namespace. Your example would then not compile. I think this would be preferable to having different syntax to discriminate between the method call and invoking a field. Mark Thornton From mthornton at optrak.co.uk Tue Dec 15 06:21:57 2009 From: mthornton at optrak.co.uk (Mark Thornton) Date: Tue, 15 Dec 2009 14:21:57 +0000 Subject: Method calls vs lambda calls In-Reply-To: <4B279833.5010204@optrak.co.uk> References: <7783BF2B-98D6-4E01-8B97-CC19B139AE92@gmail.com> <4B26A1BC.9010206@the-loom.de> <15e8b9d20912141237y24a64227yab9e0756244df8be@mail.gmail.com> <4B26A561.3050002@the-loom.de> <17b2302a0912142304x5e82ef60jabe569d527789b11@mail.gmail.com> <4EC54BD2-4335-482D-A97B-DA06C98393DA@gmail.com> <4B279833.5010204@optrak.co.uk> Message-ID: <4B279B85.7070804@optrak.co.uk> Mark Thornton wrote: >> >> > A simple solution would be to specify that method valued fields are in > the method namespace. Your example would then not compile. I think this > would be preferable to having different syntax to discriminate between > the method call and invoking a field. > > Mark Thornton > > > I realise that this then allows public class Example { private int fourtyTwo = 42; public #int() fourtyTwo = #int() {return fourtyTwo;} public void run() { System.out.println(fourtyTwo()); } } I think I would accept that as the price for the more convenient invocation syntax. Mark Thornton From howard.lovatt at iee.org Tue Dec 15 06:26:52 2009 From: howard.lovatt at iee.org (Howard Lovatt) Date: Tue, 15 Dec 2009 15:26:52 +0100 Subject: Whither extension methods? In-Reply-To: <4B279276.2040101@optrak.co.uk> References: <3dd3f56a0912150306m26f065fat882248d955524054@mail.gmail.com> <4B276FFB.6020607@optrak.co.uk> <3dd3f56a0912150441l754d3ce2nb32bfcc8efd8cc4b@mail.gmail.com> <4B279276.2040101@optrak.co.uk> Message-ID: <3dd3f56a0912150626h7095f88dg611181fbb2342a22@mail.gmail.com> It is an interesting idea that I had not considered, this might well be a good solution. Existing code that had not being recompiled would call List sort() and when you compiled the code against the new interface you would get an error. You would have to fix the error, probably by making a new class that avoids the name clash, which would still be irritating but not impossible. It is an idea worth considering - does anyone else see a problem with this idea? 2009/12/15 Mark Thornton > Howard Lovatt wrote: > >> This might well be possible, but it would be more work since it is a >> change to the type system (it would have to infer the method to call from >> the LHS of an assignment). I suspect this is too big a change to the type >> system. >> >> I was thinking more of byte code which hadn't been recompiled. In this > case the linker could allow both methods to coexist. Of course if you did > recompile the source with the new definition of List, there would be an > error. So binary compatible but not source compatible. > > > Mark Thornton > > > ______________________________________________________________________ > This email has been scanned by the MessageLabs Email Security System. > For more information please visit http://www.messagelabs.com/email______________________________________________________________________ > -- -- Howard. From forax at univ-mlv.fr Tue Dec 15 06:29:40 2009 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Tue, 15 Dec 2009 15:29:40 +0100 Subject: Method calls vs lambda calls In-Reply-To: <4B279B85.7070804@optrak.co.uk> References: <7783BF2B-98D6-4E01-8B97-CC19B139AE92@gmail.com> <4B26A1BC.9010206@the-loom.de> <15e8b9d20912141237y24a64227yab9e0756244df8be@mail.gmail.com> <4B26A561.3050002@the-loom.de> <17b2302a0912142304x5e82ef60jabe569d527789b11@mail.gmail.com> <4EC54BD2-4335-482D-A97B-DA06C98393DA@gmail.com> <4B279833.5010204@optrak.co.uk> <4B279B85.7070804@optrak.co.uk> Message-ID: <4B279D54.9010100@univ-mlv.fr> Mark Thornton a ?crit : > Mark Thornton wrote: > >>> >>> >>> >> A simple solution would be to specify that method valued fields are in >> the method namespace. Your example would then not compile. I think this >> would be preferable to having different syntax to discriminate between >> the method call and invoking a field. >> >> Mark Thornton >> >> >> >> > I realise that this then allows > > public class Example { > private int fourtyTwo = 42; > public #int() fourtyTwo = #int() {return fourtyTwo;} > > public void run() { > System.out.println(fourtyTwo()); > } > } > > I think I would accept that as the price for the more convenient > invocation syntax. > > Mark Thornton > > > And this will not compile :( public class Example { #int() fourtyTwo = #() {return 42; }; { f(fourtyTwo); } public void f(#int v) { ... } } R?mi From schulz at the-loom.de Tue Dec 15 06:44:02 2009 From: schulz at the-loom.de (Stefan Schulz) Date: Tue, 15 Dec 2009 15:44:02 +0100 Subject: Method calls vs lambda calls In-Reply-To: <4B279833.5010204@optrak.co.uk> References: <7783BF2B-98D6-4E01-8B97-CC19B139AE92@gmail.com> <4B26A1BC.9010206@the-loom.de> <15e8b9d20912141237y24a64227yab9e0756244df8be@mail.gmail.com> <4B26A561.3050002@the-loom.de> <17b2302a0912142304x5e82ef60jabe569d527789b11@mail.gmail.com> <4EC54BD2-4335-482D-A97B-DA06C98393DA@gmail.com> <4B279833.5010204@optrak.co.uk> Message-ID: <4B27A0B2.5000303@the-loom.de> Am 15.12.2009 15:07, schrieb Mark Thornton: > Alex Blewitt wrote: >> This was, of course, a leading question. Now consider: >> >>>>>>> public class Example { #int() public fortyTwo = #int() >>>>>>> { return 42; } >>>>>>> public int fortyTwo() { >>>>>>> return 6*9; >>>>>>> } >>>>>>> public void run() { >>>>>>> System.out.println(fortyTwo()) >>>>>>> } >>>>>>> } >>>>>>> >> >> >> Sent from my (new) iPhone >> >> > A simple solution would be to specify that method valued fields are in > the method namespace. Your example would then not compile. I think this > would be preferable to having different syntax to discriminate between > the method call and invoking a field. > > Mark Thornton Yep, this is what I was thinking of on my first reply wrt. compile time error. Same scope for method and function. Might be easier to catch if function variables were defined resembling a method definition: public int #fortyTwo() = #() { return 42; }; // or #() (42); public int fortyTwo() { return 6 * 9; } Stefan From mthornton at optrak.co.uk Tue Dec 15 07:05:15 2009 From: mthornton at optrak.co.uk (Mark Thornton) Date: Tue, 15 Dec 2009 15:05:15 +0000 Subject: Method calls vs lambda calls In-Reply-To: <4B279D54.9010100@univ-mlv.fr> References: <7783BF2B-98D6-4E01-8B97-CC19B139AE92@gmail.com> <4B26A1BC.9010206@the-loom.de> <15e8b9d20912141237y24a64227yab9e0756244df8be@mail.gmail.com> <4B26A561.3050002@the-loom.de> <17b2302a0912142304x5e82ef60jabe569d527789b11@mail.gmail.com> <4EC54BD2-4335-482D-A97B-DA06C98393DA@gmail.com> <4B279833.5010204@optrak.co.uk> <4B279B85.7070804@optrak.co.uk> <4B279D54.9010100@univ-mlv.fr> Message-ID: <4B27A5AB.2080201@optrak.co.uk> R?mi Forax wrote: > Mark Thornton a ?crit : >> Mark Thornton wrote: >> >>>> >>> A simple solution would be to specify that method valued fields are >>> in the method namespace. Your example would then not compile. I >>> think this would be preferable to having different syntax to >>> discriminate between the method call and invoking a field. >>> >>> Mark Thornton >>> >>> >>> >> I realise that this then allows >> >> public class Example { private int fourtyTwo = 42; >> public #int() fourtyTwo = #int() {return fourtyTwo;} >> >> public void run() { >> System.out.println(fourtyTwo()); >> } >> } >> >> I think I would accept that as the price for the more convenient >> invocation syntax. >> >> Mark Thornton >> >> >> > And this will not compile :( > > public class Example { > #int() fourtyTwo = #() {return 42; }; > > { > f(fourtyTwo); > } > > public void f(#int v) { > ... > } > } > > > Howard Lovatt has suggested putting method references in both namespaces which would solve that problem. Mark Thornton From howard.lovatt at iee.org Tue Dec 15 07:11:32 2009 From: howard.lovatt at iee.org (Howard Lovatt) Date: Tue, 15 Dec 2009 16:11:32 +0100 Subject: Method calls vs lambda calls In-Reply-To: <3dd3f56a0912150653s6d92945albca4fc422eaf5b1f@mail.gmail.com> References: <3dd3f56a0912150653s6d92945albca4fc422eaf5b1f@mail.gmail.com> Message-ID: <3dd3f56a0912150711v25ed7a9bi73b46fc0d92fee1@mail.gmail.com> I remain to be convinced that method references are a good idea, since they pull Java much further towards structural typing than at present and this will be very confusing for people to be presented with two type systems. That desirability point aside, the technical issue of what name space a function type should be in can be resolved by putting a function type in both the method and the field/variable name spaces. You need to do this because it is used both as a field/variable: #int() fortyTwo = #() (42); // declare and assign to the field/variable or out.println( fortyTwo ); // prints something like Function_int at 0xXXXX and as a function: out.println( fortyTwo() ); // prints 42 Normal Java rules apply in all cases, if function types are in both name spaces, since you can always tell if it is a function call or a field reference. Actually there are still some rough edges since methods are dynamically resolved and fields aren't. You can paper over this difference a little by saying that function types can't be hidden. However, people might find this difference, can't hide, confusing. Mark Thornton wrote: >> >> > A simple solution would be to specify that method valued fields are in > the method namespace. Your example would then not compile. I think this > would be preferable to having different syntax to discriminate between > the method call and invoking a field. > > Mark Thornton From jjb at google.com Tue Dec 15 07:37:45 2009 From: jjb at google.com (Joshua Bloch) Date: Tue, 15 Dec 2009 07:37:45 -0800 Subject: Whither extension methods? In-Reply-To: References: <17b2302a0912142346h13243ac3wf995be1c021145ef@mail.gmail.com> Message-ID: <17b2302a0912150737p5cb58320m1c93fda597b5cac6@mail.gmail.com> Not that I know of. It sure would be nice. Josh On Tue, Dec 15, 2009 at 4:42 AM, Roel Spilker wrote: > Josh, or Doug, > > Is there also a video or audio recording of Guy Steele's talk? I couldn't > easily find it using my favorite search engine :-) > > Roel > > On Tue, Dec 15, 2009 at 8:46 AM, Joshua Bloch wrote: > >> Doug Lea sent this a couple of days ago, and I think it deserves our >> consideration: >> >> I confess to being a little confused about the rationale for extension >> > methods. >> >> >> > Suppose we have a Map, and want to some sort of apply-to-each-value >> > operation. The only reasonable way to do this in parallel is to somehow >> > splitthe work. But Map has no public methods allowing you to do this -- >> you >> > can only get an iterator, which is inherently sequential. Now, if we >> > could get at the representations, then we could actually do splits for >> most >> > java.util maps (at least for the most common ones -- HashMaps, >> TreeMaps). So >> > the only way I know for these to be bolted on is to introduce new >> interfaces >> > that each of the these existing classes could be changed to implement. >> Or am >> > I missing something? >> >> >> > You might want to read Guy Steele's nice talk on related issues at >> > >> http://groups.csail.mit.edu/mac/users/gjs/6.945/readings/MITApril2009Steele.pdf >> >> >> > -Doug >> >> > From markmahieu at googlemail.com Tue Dec 15 08:21:12 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Tue, 15 Dec 2009 16:21:12 +0000 Subject: Whither extension methods? In-Reply-To: <17b2302a0912150737p5cb58320m1c93fda597b5cac6@mail.gmail.com> References: <17b2302a0912142346h13243ac3wf995be1c021145ef@mail.gmail.com> <17b2302a0912150737p5cb58320m1c93fda597b5cac6@mail.gmail.com> Message-ID: <6E4A8F43-1179-4AEE-AB09-AAF536FA0E9E@googlemail.com> There are other (longer) versions linked at: http://research.sun.com/projects/plrg/Publications/index.html Video of the most recent talk on that page can be found here: http://www.vimeo.com/6624203 Mark On 15 Dec 2009, at 15:37, Joshua Bloch wrote: > Not that I know of. It sure would be nice. > > Josh > > On Tue, Dec 15, 2009 at 4:42 AM, Roel Spilker wrote: > >> Josh, or Doug, >> >> Is there also a video or audio recording of Guy Steele's talk? I couldn't >> easily find it using my favorite search engine :-) >> >> Roel >> >> On Tue, Dec 15, 2009 at 8:46 AM, Joshua Bloch wrote: >> >>> Doug Lea sent this a couple of days ago, and I think it deserves our >>> consideration: >>> >>> I confess to being a little confused about the rationale for extension >>>> methods. >>> >>> >>>> Suppose we have a Map, and want to some sort of apply-to-each-value >>>> operation. The only reasonable way to do this in parallel is to somehow >>>> splitthe work. But Map has no public methods allowing you to do this -- >>> you >>>> can only get an iterator, which is inherently sequential. Now, if we >>>> could get at the representations, then we could actually do splits for >>> most >>>> java.util maps (at least for the most common ones -- HashMaps, >>> TreeMaps). So >>>> the only way I know for these to be bolted on is to introduce new >>> interfaces >>>> that each of the these existing classes could be changed to implement. >>> Or am >>>> I missing something? >>> >>> >>>> You might want to read Guy Steele's nice talk on related issues at >>>> >>> http://groups.csail.mit.edu/mac/users/gjs/6.945/readings/MITApril2009Steele.pdf >>> >>> >>>> -Doug >>> >>> >> > From neal at gafter.com Tue Dec 15 08:21:26 2009 From: neal at gafter.com (Neal Gafter) Date: Tue, 15 Dec 2009 08:21:26 -0800 Subject: Method calls vs lambda calls In-Reply-To: <3dd3f56a0912150711v25ed7a9bi73b46fc0d92fee1@mail.gmail.com> References: <3dd3f56a0912150653s6d92945albca4fc422eaf5b1f@mail.gmail.com> <3dd3f56a0912150711v25ed7a9bi73b46fc0d92fee1@mail.gmail.com> Message-ID: <15e8b9d20912150821s707be3c0k4cc2ad040c3bca9@mail.gmail.com> On Tue, Dec 15, 2009 at 7:11 AM, Howard Lovatt wrote: > I remain to be convinced that method references are a good idea, since > they pull Java much further towards structural typing than at present > and this will be very confusing for people to be presented with two > type systems. > I don't know what this argument has to do about method references (are you talking about function types?), but your argument makes no sense. They're a good idea because they will confuse people? Huh? > That desirability point aside, the technical issue of what name space > a function type should be in can be resolved by putting a function > type in both the method and the field/variable name spaces. Function types are anonymous, and so don't need to go in any namespace. Do you mean a variable of function type? Actually there are still some rough edges since methods are > dynamically resolved and fields aren't. You can paper over this > difference a little by saying that function types can't be hidden. > What do you mean: hiding triggers an error (that would make code very fragile, especially where the hidden name isn't even used)? Or that the name isn't hidden? Cheers, Neal From mahmood at notnoop.com Tue Dec 15 08:32:12 2009 From: mahmood at notnoop.com (Mahmood Ali) Date: Tue, 15 Dec 2009 11:32:12 -0500 Subject: Function conversion (SAM) and ambiguity Message-ID: <453416530912150832k4ef70eb3u9a5f8eaea3521170@mail.gmail.com> Greetings, I was just wondering how the function conversion semantics interacts with method overloading, where overloaded methods accept difference SAMs. Should there be a mechanism to explicitly state which interface the closure should be converted to? For example, suppose you have the following declaration interface ThrowingRunnable { void run() throws Throwable; } interface Executor { void execute(Runnable r); void execute(ThrowingRunnable r); } Executor e = ... e.execute(#() { doSomething(); }) // ambiguous conversion e.execute(#() { throw new RuntimeException(); }) // still ambiguous I would propose resolving this ambiguity by: 1. Issuing an error where an ambigiouty is found, and 2. permitting the abstract class/interface name to appear between # and parameters: e.execute(#Runnable() { doSomething(); }); e.execute(#ThrowingRunnable() { throw new RuntimeException(); }); I realize that that space is reserved for return types in function type declarations. - Mahmood From neal at gafter.com Tue Dec 15 08:36:27 2009 From: neal at gafter.com (Neal Gafter) Date: Tue, 15 Dec 2009 08:36:27 -0800 Subject: Whither extension methods? In-Reply-To: <17b2302a0912142346h13243ac3wf995be1c021145ef@mail.gmail.com> References: <17b2302a0912142346h13243ac3wf995be1c021145ef@mail.gmail.com> Message-ID: <15e8b9d20912150836n5a553b1fp84858a74b1034f6c@mail.gmail.com> I find the described motivation for this whole exercise questionable. Multicore is certainly important, and the proposed changes do improve things, but to suggest that every issue must relate to and be decided on the basis of its impact on multicore doesn't make sense. Still, extension methods for concurrent aggregate operations can peek at the implementation of the collections they receive to take advantage of decomposition facilities where available. It would therefore be worthwhile to add interfaces for decomposability and retrofit the collections classes (not interfaces) to those interfaces. Even when decomposition is not available, very good speedup can be achieved when the operation to be done on each element is much more expensive than moving from one element to the next. Both extension methods and lambda expressions are required to support more flexible automatic parallelization of the sort that appears in Microsoft's PLinq library. It achieves nearly linear speedup on aggregate operations over ordinary collections (IEnumerable, actually, which is the equivalent of Iterable) without needing to introduce a separate set of APIs. It is more flexible than ParallelArray in that it allows the operations to be chained, and aggregates the operations per element. But to do that, you need to add support for tree lambdas. That could be done as a separate extension later; it doesn't have to be done all at once. Cheers, Neal On Mon, Dec 14, 2009 at 11:46 PM, Joshua Bloch wrote: > Doug Lea sent this a couple of days ago, and I think it deserves our > consideration: > > I confess to being a little confused about the rationale for extension > > methods. > > > > Suppose we have a Map, and want to some sort of apply-to-each-value > > operation. The only reasonable way to do this in parallel is to somehow > > splitthe work. But Map has no public methods allowing you to do this -- > you > > can only get an iterator, which is inherently sequential. Now, if we > > could get at the representations, then we could actually do splits for > most > > java.util maps (at least for the most common ones -- HashMaps, TreeMaps). > So > > the only way I know for these to be bolted on is to introduce new > interfaces > > that each of the these existing classes could be changed to implement. Or > am > > I missing something? > > > > You might want to read Guy Steele's nice talk on related issues at > > > http://groups.csail.mit.edu/mac/users/gjs/6.945/readings/MITApril2009Steele.pdf > > > > -Doug > > From opinali at gmail.com Tue Dec 15 09:13:35 2009 From: opinali at gmail.com (Osvaldo Doederlein) Date: Tue, 15 Dec 2009 15:13:35 -0200 Subject: Whither extension methods? In-Reply-To: <17b2302a0912142346h13243ac3wf995be1c021145ef@mail.gmail.com> References: <17b2302a0912142346h13243ac3wf995be1c021145ef@mail.gmail.com> Message-ID: This remembers me that collections like TreeMap and TreeSet could have a method that returns the root key or entry. So we could then use many existing methods like headMap(), higherKey() etc., for [recursive] divide-and-conquer algorithms, with or without concurrency or lambdas. A+ Osvaldo 2009/12/15 Joshua Bloch > Doug Lea sent this a couple of days ago, and I think it deserves our > consideration: > > I confess to being a little confused about the rationale for extension > > methods. > > > > Suppose we have a Map, and want to some sort of apply-to-each-value > > operation. The only reasonable way to do this in parallel is to somehow > > splitthe work. But Map has no public methods allowing you to do this -- > you > > can only get an iterator, which is inherently sequential. Now, if we > > could get at the representations, then we could actually do splits for > most > > java.util maps (at least for the most common ones -- HashMaps, TreeMaps). > So > > the only way I know for these to be bolted on is to introduce new > interfaces > > that each of the these existing classes could be changed to implement. Or > am > > I missing something? > > > > You might want to read Guy Steele's nice talk on related issues at > > > http://groups.csail.mit.edu/mac/users/gjs/6.945/readings/MITApril2009Steele.pdf > > > > -Doug > > From schulz at the-loom.de Tue Dec 15 10:25:17 2009 From: schulz at the-loom.de (Stefan Schulz) Date: Tue, 15 Dec 2009 19:25:17 +0100 Subject: Function conversion (SAM) and ambiguity In-Reply-To: <453416530912150832k4ef70eb3u9a5f8eaea3521170@mail.gmail.com> References: <453416530912150832k4ef70eb3u9a5f8eaea3521170@mail.gmail.com> Message-ID: <4B27D48D.8070607@the-loom.de> I'd expect this to be solved like it is currently solved on object type ambiguity by casting to the destined SAM. Stefan Am 15.12.2009 17:32, schrieb Mahmood Ali: > Greetings, > > I was just wondering how the function conversion semantics interacts > with method overloading, where overloaded methods accept difference > SAMs. Should there be a mechanism to explicitly state which interface > the closure should be converted to? > > For example, suppose you have the following declaration > > interface ThrowingRunnable { void run() throws Throwable; } > interface Executor { > void execute(Runnable r); > void execute(ThrowingRunnable r); > } > > Executor e = ... > e.execute(#() { doSomething(); }) // ambiguous conversion > e.execute(#() { throw new RuntimeException(); }) // still ambiguous > > I would propose resolving this ambiguity by: > 1. Issuing an error where an ambigiouty is found, and > 2. permitting the abstract class/interface name to appear between # > and parameters: > > e.execute(#Runnable() { doSomething(); }); > e.execute(#ThrowingRunnable() { throw new RuntimeException(); }); > > I realize that that space is reserved for return types in function > type declarations. > > - Mahmood > > From mr at sun.com Tue Dec 15 21:26:51 2009 From: mr at sun.com (Mark Reinhold) Date: Tue, 15 Dec 2009 21:26:51 -0800 Subject: Serialization In-Reply-To: pcj@roundroom.net; Mon, 14 Dec 2009 01:23:54 EST; Message-ID: <20091216052651.823364A0@eggemoggin.niobe.net> > Date: Mon, 14 Dec 2009 01:23:54 -0500 > From: Peter Jones > I expect that there would be the issue that is also a problem with serializing > instances of anonymous classes today: that the binary names of the classes are > neither JLS-determined nor very stable across edits/recompiles. Serialization > represents an object's code by its class's binary name, but these things won't > have overt names. Moreover, the set of a closure's serializable fields seems > likely to be less stable in practice compared to a normally-declared class. > And I don't see how you could specify any of the usual customizations to > serialized form or behavior (transient, readObject, etc.). What these issues > suggest to me is that in cases where the writing and the reading code are from > the exact same compilation of sources, then perhaps serialization of closures > could work and be useful-- but I don't see it working in the more general case > of communication across an API contract. Like I said -- serialization is tricky. Thanks Peter. Taken together these are good reasons not to make closures serializable, at least not at the outset. If there turn out to be compelling use cases then we could look in to making them serializable later on. - Mark From mr at sun.com Tue Dec 15 21:42:53 2009 From: mr at sun.com (Mark Reinhold) Date: Tue, 15 Dec 2009 21:42:53 -0800 Subject: Implicit return syntax error In-Reply-To: jason.height@gmail.com; Fri, 11 Dec 2009 09:16:06 +1030; Message-ID: <20091216054253.BCCA14A0@eggemoggin.niobe.net> > Date: Fri, 11 Dec 2009 09:16:06 +1030 > From: jason.height at gmail.com > I just started reading the strawman proposal and i would like to discuss the > benefit/reasons of having an implict return statement for the simple > expressions. I actually believe for a person with little or no experience in > closures that the statement "#()(return 42;)" rather than "#()(42)" is far > more readable and natural when compared to the existing jls. A syntax error > is be generated if one omits the "return" keyword for a function ie: > > public int getFortyTwo() { > 42; > } > > As such i propose that the straw man proposal should be changed to so > implicit returns are syntax errors. Thanks for your input, but I have to disagree. I expect that, in actual use, many lambda expressions will have expression rather than statement bodies, and so insisting upon the more verbose #(){ return 42; } syntax will just make such uses more, well, verbose. Imagine replacing "42" with a complex expression of your choice, e.g., #(double a, double b, double c)((-b + sqrt(pow(b, 2) - 4 * a * c))/(2 * a)) Does changing this to #(double a, double b, double c){ return (-b + sqrt(pow(b, 2) - 4 * a * c))/(2 * a); } increase readability, or decrease it? - Mark From mr at sun.com Tue Dec 15 21:57:18 2009 From: mr at sun.com (Mark Reinhold) Date: Tue, 15 Dec 2009 21:57:18 -0800 Subject: Extension Methods In-Reply-To: pbenedict@apache.org; Thu, 10 Dec 2009 23:45:29 CST; Message-ID: <20091216055718.239EF4A0@eggemoggin.niobe.net> > Date: Thu, 10 Dec 2009 23:45:29 -0600 > From: Paul Benedict > First, thank you and very nice job writing up the proposal. It is a > great document to read! Thanks; I'm glad you enjoyed it. > I suppose you could version control it in > Mercurial; then people can perform hi-tech diffs too. If this document proves to have staying power then I'll do that. > With regard to extension methods, I think the "declaration-site" > extensions are mostly worthless. Interfaces shouldn't be used this way > since they are suppose to define a contract to implement. I dare to > say this is an abuse of the interface mechanism. ... I do have some sympathy with this position. At the same time, however, I'm reluctant to see the classic collection classes consigned to the limits of the language as it stands today. As I said in the proposal, I don't see extension methods as a critical feature for this release. I'd be content to drop them if they prove problematic, and consider this issue again in a future release. - Mark From swingler at apple.com Tue Dec 15 22:15:27 2009 From: swingler at apple.com (Mike Swingler) Date: Tue, 15 Dec 2009 22:15:27 -0800 Subject: Implicit return syntax error In-Reply-To: <20091216054253.BCCA14A0@eggemoggin.niobe.net> References: <20091216054253.BCCA14A0@eggemoggin.niobe.net> Message-ID: On Dec 15, 2009, at 9:42 PM, Mark Reinhold wrote: >> Date: Fri, 11 Dec 2009 09:16:06 +1030 >> From: jason.height at gmail.com > >> I just started reading the strawman proposal and i would like to >> discuss the >> benefit/reasons of having an implict return statement for the simple >> expressions. I actually believe for a person with little or no >> experience in >> closures that the statement "#()(return 42;)" rather than "#()(42)" >> is far >> more readable and natural when compared to the existing jls. A >> syntax error >> is be generated if one omits the "return" keyword for a function ie: >> >> public int getFortyTwo() { >> 42; >> } >> >> As such i propose that the straw man proposal should be changed to so >> implicit returns are syntax errors. > > Thanks for your input, but I have to disagree. I expect that, in > actual > use, many lambda expressions will have expression rather than > statement > bodies, and so insisting upon the more verbose > > #(){ return 42; } > > syntax will just make such uses more, well, verbose. > > Imagine replacing "42" with a complex expression of your choice, e.g., > > #(double a, double b, double c)((-b + sqrt(pow(b, 2) - 4 * a * > c))/(2 * a)) > > Does changing this to > > #(double a, double b, double c){ return (-b + sqrt(pow(b, 2) - 4 > * a * c))/(2 * a); } > > increase readability, or decrease it? It may be terser by a few characters, but it's an impedance mismatch with the rest of the language as it exists today, which reduces understandability. I'd also counter that I'd love to rewrite a ton of event handlers using lambdas, and most would be multi-statement. I think it's important to introduce a powerful new concept like lambda expressions in terms that are as familiar and consistent as possible to the widest audience. Later, it may make sense to propose implicit return statements for the language in all contexts, and not just a one- off special case for lambdas. Regards, Mike Swingler From jjb at google.com Tue Dec 15 22:17:41 2009 From: jjb at google.com (Joshua Bloch) Date: Tue, 15 Dec 2009 22:17:41 -0800 Subject: Serialization In-Reply-To: <20091216052651.823364A0@eggemoggin.niobe.net> References: <20091216052651.823364A0@eggemoggin.niobe.net> Message-ID: <17b2302a0912152217mf1feac0ld5a9ed17cda82be1@mail.gmail.com> Mark and Peter, This is a moderately important decision. In Google's Java MapReduce API, we use SAM interfaces to represent Mapper and Reducer. Instances must be serializable, as they're serialized to pass them from the node that starts the MapReduce to the worker nodes (which do the actual mapping and reduction). That means we won't be able to use closure syntax for MapReduce, which seems like a shame. This is no worse than what we do with SAM types today, but it's no better, either. Can we do better? Josh On Tue, Dec 15, 2009 at 9:26 PM, Mark Reinhold wrote: > > Date: Mon, 14 Dec 2009 01:23:54 -0500 > > From: Peter Jones > > > I expect that there would be the issue that is also a problem with > serializing > > instances of anonymous classes today: that the binary names of the > classes are > > neither JLS-determined nor very stable across edits/recompiles. > Serialization > > represents an object's code by its class's binary name, but these things > won't > > have overt names. Moreover, the set of a closure's serializable fields > seems > > likely to be less stable in practice compared to a normally-declared > class. > > And I don't see how you could specify any of the usual customizations to > > serialized form or behavior (transient, readObject, etc.). What these > issues > > suggest to me is that in cases where the writing and the reading code > are from > > the exact same compilation of sources, then perhaps serialization of > closures > > could work and be useful-- but I don't see it working in the more > general case > > of communication across an API contract. > > Like I said -- serialization is tricky. Thanks Peter. > > Taken together these are good reasons not to make closures serializable, > at least not at the outset. If there turn out to be compelling use cases > then we could look in to making them serializable later on. > > - Mark > > From mr at sun.com Tue Dec 15 22:21:44 2009 From: mr at sun.com (Mark Reinhold) Date: Tue, 15 Dec 2009 22:21:44 -0800 Subject: Extension methods vs. Traits In-Reply-To: daniel.latremoliere@gmail.com; Fri, 11 Dec 2009 10:45:19 +0100; <4B2214AF.4080106@gmail.com> Message-ID: <20091216062144.4F2C54A0@eggemoggin.niobe.net> > Date: Fri, 11 Dec 2009 10:45:19 +0100 > From: daniel.latremoliere at gmail.com > I would like to understand the final paragraph of the proposal where you are > saying that the traits are much more significant change than extension methods > to the language and VM. > > ... >From a strictly technical standpoint adding traits might not be a (much?) more significant change than adding extension methods. >From a conceptual standpoint, however, adding traits to the language is a hugely significant change -- much more significant than adding lambda expressions. If we add traits to the language then every Java programmer will, sooner or later, need to learn how to read and compose them, and traits are very different beasts from the classes and interfaces with which we're all so familiar today. (Extension methods, by contrast, are just a fancy new variant of static imports.) Traits have worked out reasonably well in Scala, and in the long term it's worth considering adding them to Java, but now is not the right time. They're worth thinking about now, however: If traits really are a better way to achieve the goals addressed by extension methods then perhaps we should drop extension methods in this release and take up traits in the next. - Mark From mr at sun.com Tue Dec 15 22:38:57 2009 From: mr at sun.com (Mark Reinhold) Date: Tue, 15 Dec 2009 22:38:57 -0800 Subject: Serialization In-Reply-To: jjb@google.com; Tue, 15 Dec 2009 22:17:41 PST; <17b2302a0912152217mf1feac0ld5a9ed17cda82be1@mail.gmail.com> Message-ID: <20091216063857.4CC794A0@eggemoggin.niobe.net> > Date: Tue, 15 Dec 2009 22:17:41 -0800 > From: Joshua Bloch > This is a moderately important decision. In Google's Java MapReduce API, we use > SAM interfaces to represent Mapper and Reducer. Instances must be serializable, > as they're serialized to pass them from the node that starts the MapReduce to > the worker nodes (which do the actual mapping and reduction). That means we > won't be able to use closure syntax for MapReduce, which seems like a shame. > > This is no worse than what we do with SAM types today, but it's no better, > either. Can we do better? Maybe. How would you suggest we address the concerns which Peter raised? - Mark From jjb at google.com Tue Dec 15 22:58:32 2009 From: jjb at google.com (Joshua Bloch) Date: Tue, 15 Dec 2009 22:58:32 -0800 Subject: Serialization In-Reply-To: <20091216063857.4CC794A0@eggemoggin.niobe.net> References: <17b2302a0912152217mf1feac0ld5a9ed17cda82be1@mail.gmail.com> <20091216063857.4CC794A0@eggemoggin.niobe.net> Message-ID: <17b2302a0912152258u74fe428dt398613b5ec3fe167@mail.gmail.com> Mark, I'm sorry to say, I don't know. It's a hard problem. One possibility is to provide a concise syntax for named singleton subclasses of functional types. That would finesse the problem rather than solving it. Josh On Tue, Dec 15, 2009 at 10:38 PM, Mark Reinhold wrote: > > Date: Tue, 15 Dec 2009 22:17:41 -0800 > > From: Joshua Bloch > > > This is a moderately important decision. In Google's Java MapReduce API, > we use > > SAM interfaces to represent Mapper and Reducer. Instances must be > serializable, > > as they're serialized to pass them from the node that starts the > MapReduce to > > the worker nodes (which do the actual mapping and reduction). That means > we > > won't be able to use closure syntax for MapReduce, which seems like a > shame. > > > > This is no worse than what we do with SAM types today, but it's no > better, > > either. Can we do better? > > Maybe. How would you suggest we address the concerns which Peter raised? > > - Mark > From swingler at apple.com Tue Dec 15 23:13:40 2009 From: swingler at apple.com (Mike Swingler) Date: Tue, 15 Dec 2009 23:13:40 -0800 Subject: Serialization In-Reply-To: <17b2302a0912152258u74fe428dt398613b5ec3fe167@mail.gmail.com> References: <17b2302a0912152217mf1feac0ld5a9ed17cda82be1@mail.gmail.com> <20091216063857.4CC794A0@eggemoggin.niobe.net> <17b2302a0912152258u74fe428dt398613b5ec3fe167@mail.gmail.com> Message-ID: Perhaps the class and defining method name could be concatenated with a hash of the contents of the function. Cheers, Mike Swingler On Dec 15, 2009, at 10:58 PM, Joshua Bloch wrote: > Mark, > > I'm sorry to say, I don't know. It's a hard problem. One > possibility is to > provide a concise syntax for named singleton subclasses of > functional types. > That would finesse the problem rather than solving it. > > Josh > > On Tue, Dec 15, 2009 at 10:38 PM, Mark Reinhold wrote: > >>> Date: Tue, 15 Dec 2009 22:17:41 -0800 >>> From: Joshua Bloch >> >>> This is a moderately important decision. In Google's Java >>> MapReduce API, >> we use >>> SAM interfaces to represent Mapper and Reducer. Instances must be >> serializable, >>> as they're serialized to pass them from the node that starts the >> MapReduce to >>> the worker nodes (which do the actual mapping and reduction). That >>> means >> we >>> won't be able to use closure syntax for MapReduce, which seems >>> like a >> shame. >>> >>> This is no worse than what we do with SAM types today, but it's no >> better, >>> either. Can we do better? >> >> Maybe. How would you suggest we address the concerns which Peter >> raised? >> >> - Mark >> > From jjb at google.com Wed Dec 16 00:05:09 2009 From: jjb at google.com (Joshua Bloch) Date: Wed, 16 Dec 2009 00:05:09 -0800 Subject: Serialization In-Reply-To: References: <17b2302a0912152217mf1feac0ld5a9ed17cda82be1@mail.gmail.com> <20091216063857.4CC794A0@eggemoggin.niobe.net> <17b2302a0912152258u74fe428dt398613b5ec3fe167@mail.gmail.com> Message-ID: <17b2302a0912160005l40635914u1ba50eb22cd1cbc0@mail.gmail.com> Mike, I'm skeptical about this approach; using hashes for serial version UIDs was a disaster, for any number of reasons. Hashes are so fragile. Change anything and things blow up at runtime. I wish I believed this approach would work, but I'm afraid it probably won't. Sorry, Josh On Tue, Dec 15, 2009 at 11:13 PM, Mike Swingler wrote: > Perhaps the class and defining method name could be concatenated with a > hash of the contents of the function. > > Cheers, > Mike Swingler > > > On Dec 15, 2009, at 10:58 PM, Joshua Bloch wrote: > > Mark, >> >> I'm sorry to say, I don't know. It's a hard problem. One possibility is >> to >> provide a concise syntax for named singleton subclasses of functional >> types. >> That would finesse the problem rather than solving it. >> >> Josh >> >> On Tue, Dec 15, 2009 at 10:38 PM, Mark Reinhold wrote: >> >> Date: Tue, 15 Dec 2009 22:17:41 -0800 >>>> From: Joshua Bloch >>>> >>> >>> This is a moderately important decision. In Google's Java MapReduce API, >>>> >>> we use >>> >>>> SAM interfaces to represent Mapper and Reducer. Instances must be >>>> >>> serializable, >>> >>>> as they're serialized to pass them from the node that starts the >>>> >>> MapReduce to >>> >>>> the worker nodes (which do the actual mapping and reduction). That means >>>> >>> we >>> >>>> won't be able to use closure syntax for MapReduce, which seems like a >>>> >>> shame. >>> >>>> >>>> This is no worse than what we do with SAM types today, but it's no >>>> >>> better, >>> >>>> either. Can we do better? >>>> >>> >>> Maybe. How would you suggest we address the concerns which Peter raised? >>> >>> - Mark >>> >>> >> > From swingler at apple.com Wed Dec 16 00:21:18 2009 From: swingler at apple.com (Mike Swingler) Date: Wed, 16 Dec 2009 00:21:18 -0800 Subject: Serialization In-Reply-To: <17b2302a0912160005l40635914u1ba50eb22cd1cbc0@mail.gmail.com> References: <17b2302a0912152217mf1feac0ld5a9ed17cda82be1@mail.gmail.com> <20091216063857.4CC794A0@eggemoggin.niobe.net> <17b2302a0912152258u74fe428dt398613b5ec3fe167@mail.gmail.com> <17b2302a0912160005l40635914u1ba50eb22cd1cbc0@mail.gmail.com> Message-ID: Is there a definition for how annotations are added to lambdas? Perhaps a unique name and/or serial id could be added that way. ~Mike On Dec 16, 2009, at 12:05 AM, Joshua Bloch wrote: > Mike, > > I'm skeptical about this approach; using hashes for serial version > UIDs was a disaster, for any number of reasons. Hashes are so > fragile. Change anything and things blow up at runtime. I wish I > believed this approach would work, but I'm afraid it probably won't. > > Sorry, > > Josh > > On Tue, Dec 15, 2009 at 11:13 PM, Mike Swingler > wrote: > Perhaps the class and defining method name could be concatenated > with a hash of the contents of the function. > > Cheers, > Mike Swingler > > > On Dec 15, 2009, at 10:58 PM, Joshua Bloch wrote: > > Mark, > > I'm sorry to say, I don't know. It's a hard problem. One > possibility is to > provide a concise syntax for named singleton subclasses of > functional types. > That would finesse the problem rather than solving it. > > Josh > > On Tue, Dec 15, 2009 at 10:38 PM, Mark Reinhold wrote: > > Date: Tue, 15 Dec 2009 22:17:41 -0800 > From: Joshua Bloch > > This is a moderately important decision. In Google's Java MapReduce > API, > we use > SAM interfaces to represent Mapper and Reducer. Instances must be > serializable, > as they're serialized to pass them from the node that starts the > MapReduce to > the worker nodes (which do the actual mapping and reduction). That > means > we > won't be able to use closure syntax for MapReduce, which seems like a > shame. > > This is no worse than what we do with SAM types today, but it's no > better, > either. Can we do better? > > Maybe. How would you suggest we address the concerns which Peter > raised? > > - Mark > > > > From alex.blewitt at gmail.com Wed Dec 16 00:50:32 2009 From: alex.blewitt at gmail.com (Alex Blewitt) Date: Wed, 16 Dec 2009 08:50:32 +0000 Subject: Implicit return syntax error In-Reply-To: References: <20091216054253.BCCA14A0@eggemoggin.niobe.net> Message-ID: <90044083-641B-4770-BFE0-4297503B3A36@gmail.com> On Dec 16, 2009, at 06:15, Mike Swingler wrote: > It may be terser by a few characters, but it's an impedance mismatch > with the rest of the language as it exists today, which reduces > understandability. Understandability is always such a subjective measure that it probably doesn't behove to pay too much attention, particularly for things that involve new syntax in any case. Note that 'return' is not always needed; for example: int a = -b + sqrt(pow(b,2)-4*a*c)/(2*a); has no return statement in there - it's just the result of an expression. On the other hand, I don't think it matters (in the case of an expression) whether the return is needed or not; it might well be the case that it's an optional item. That would permit the more verbose format for those that are more comfortable with it whilst allowing a reduced form for those that are more comfortable with the same. In addition, other languages have this kind of construct e.g. Python: >>> sq = lambda x: x**2 >>> sq(4) 16 > Later, it may make sense to propose implicit > return statements for the language in all contexts, and not just a > one- > off special case for lambdas. That might also be interesting (but out of scope here). Of course, an optional 'return' allows that as well. As well as block expressions (i.e. those that return the last value implicitly), would we have non-block expressions? fortyTwo = #() 42; alex From alex.blewitt at gmail.com Wed Dec 16 01:04:48 2009 From: alex.blewitt at gmail.com (Alex Blewitt) Date: Wed, 16 Dec 2009 09:04:48 +0000 Subject: Method calls vs lambda calls In-Reply-To: <4B27A5AB.2080201@optrak.co.uk> References: <7783BF2B-98D6-4E01-8B97-CC19B139AE92@gmail.com> <15e8b9d20912141237y24a64227yab9e0756244df8be@mail.gmail.com> <4B26A561.3050002@the-loom.de> <17b2302a0912142304x5e82ef60jabe569d527789b11@mail.gmail.com> <4EC54BD2-4335-482D-A97B-DA06C98393DA@gmail.com> <4B279833.5010204@optrak.co.uk> <4B279B85.7070804@optrak.co.uk> <4B279D54.9010100@univ-mlv.fr> <4B27A5AB.2080201@optrak.co.uk> Message-ID: <636fd28e0912160104y61ebc078j39db9647a1fb8828@mail.gmail.com> On Tue, Dec 15, 2009 at 3:05 PM, Mark Thornton wrote: >>>> A simple solution would be to specify that method valued fields are in >>>> the method namespace. Your example would then not compile. I think this >>>> would be preferable to having different syntax to discriminate between the >>>> method call and invoking a field. > > Howard Lovatt has suggested putting method references in both namespaces > which would solve that problem. For all lambdas, or just those defined at the top level of a class? It must be the latter, surely; they are always visible in a class (other than shadowing), whereas variables of type lambda could be created in nested recursive calls on the stack. Rather than putting them in the namespace itself, why not synthesise a bona fide method for them if lambdas are in the top level of a class? public class Example { protected final double trouble = #int(int a) { a*2 }; protected final /* ACC_SYNTHESIZED */ double trouble(int b) { apply(trouble,b) }; } That way, it would be visible/understandable by other clients who would use that class (even if they didn't know about lambdas). I'm assuming here that we have an apply() keyword of some flavour which takes varargs that lets lambdas be evaluated in line. We'd need that in the case that the 'trouble' wasn't final (i.e. could be updated at a later stage) - clearly, that can't happen for the method variant. This would also address the concern of having a (top-level) method with the same name as a lambda variable. Alex From alex.blewitt at gmail.com Wed Dec 16 01:06:33 2009 From: alex.blewitt at gmail.com (Alex Blewitt) Date: Wed, 16 Dec 2009 09:06:33 +0000 Subject: SAM types and functions In-Reply-To: References: Message-ID: <636fd28e0912160106u41eb3688mc48277c3827441cb@mail.gmail.com> On Thu, Dec 10, 2009 at 10:38 PM, Alex Blewitt wrote: >> Many existing Java libraries de?ne interfaces which declare just one >> method >> or abstract classes which declare just one abstract method (so-called >> ?SAM? types). >> A function of appropriate type is converted to an anonymous instance?... > I'm not sure this is needed in the general case ... I did a scan of the Java class libraries (those with java.* or javax.*) - there's 100 interfaces and 220 classes which fall into this definition. Quite a lot more than I expected :-) And I can see where this would be useful, provided that we can deal with the ambiguous cases (e.g. as proposed earlier, with an explicit cast). Alex From peter.levart at marand.si Wed Dec 16 01:06:46 2009 From: peter.levart at marand.si (Peter Levart) Date: Wed, 16 Dec 2009 10:06:46 +0100 Subject: Serialization In-Reply-To: References: <17b2302a0912152217mf1feac0ld5a9ed17cda82be1@mail.gmail.com> <17b2302a0912160005l40635914u1ba50eb22cd1cbc0@mail.gmail.com> Message-ID: <200912161006.46969.peter.levart@marand.si> For the "name" part, maybe alternative is specifying it directly in the lambda expression like this: #int(int, int) plus = #(int a, int b) a+b; // produces annonymous class name, sensitive to position in source vs. #int(int, int) plus = #Plus(int a, int b) a+b; // producess named inner class in the namespace of outer class I think there's no way to automatically identify a closure so that the identification would move with it when you reorder code without attaching the identification on the lambda expression itself. Peter On Wednesday 16 December 2009 09:21:18 Mike Swingler wrote: > Is there a definition for how annotations are added to lambdas? > Perhaps a unique name and/or serial id could be added that way. > > ~Mike > > On Dec 16, 2009, at 12:05 AM, Joshua Bloch wrote: > > > Mike, > > > > I'm skeptical about this approach; using hashes for serial version > > UIDs was a disaster, for any number of reasons. Hashes are so > > fragile. Change anything and things blow up at runtime. I wish I > > believed this approach would work, but I'm afraid it probably won't. > > > > Sorry, > > > > Josh > > > > On Tue, Dec 15, 2009 at 11:13 PM, Mike Swingler > > wrote: > > Perhaps the class and defining method name could be concatenated > > with a hash of the contents of the function. > > > > Cheers, > > Mike Swingler > > > > > > On Dec 15, 2009, at 10:58 PM, Joshua Bloch wrote: > > > > Mark, > > > > I'm sorry to say, I don't know. It's a hard problem. One > > possibility is to > > provide a concise syntax for named singleton subclasses of > > functional types. > > That would finesse the problem rather than solving it. > > > > Josh > > > > On Tue, Dec 15, 2009 at 10:38 PM, Mark Reinhold wrote: > > > > Date: Tue, 15 Dec 2009 22:17:41 -0800 > > From: Joshua Bloch > > > > This is a moderately important decision. In Google's Java MapReduce > > API, > > we use > > SAM interfaces to represent Mapper and Reducer. Instances must be > > serializable, > > as they're serialized to pass them from the node that starts the > > MapReduce to > > the worker nodes (which do the actual mapping and reduction). That > > means > > we > > won't be able to use closure syntax for MapReduce, which seems like a > > shame. > > > > This is no worse than what we do with SAM types today, but it's no > > better, > > either. Can we do better? > > > > Maybe. How would you suggest we address the concerns which Peter > > raised? > > > > - Mark > > > > > > > > > > > From alex.blewitt at gmail.com Wed Dec 16 01:14:41 2009 From: alex.blewitt at gmail.com (Alex Blewitt) Date: Wed, 16 Dec 2009 09:14:41 +0000 Subject: Serialization In-Reply-To: <200912161006.46969.peter.levart@marand.si> References: <17b2302a0912152217mf1feac0ld5a9ed17cda82be1@mail.gmail.com> <17b2302a0912160005l40635914u1ba50eb22cd1cbc0@mail.gmail.com> <200912161006.46969.peter.levart@marand.si> Message-ID: <636fd28e0912160114o656bb1c2i6c8d66455c33deda@mail.gmail.com> On Wed, Dec 16, 2009 at 9:06 AM, Peter Levart wrote: > For the "name" part, maybe alternative is specifying it directly in the lambda expression like this: > > #int(int, int) plus = #(int a, int b) a+b; // produces annonymous class name, sensitive to position in source Why can't we just serialize they bytecode associated with a lambda? Provided that it's a static lambda (e.g. one that has no references to 'this') and captures no state (i.e. it's not a closure), we could just stream the bytecode that makes up the function itself. Ergo, make non-instanace, non-closure lambdas serializable, and make any lambda that captures (non-final?) scope non-serializable. I don't see that the name is at all relevant, since the name is part of the variable that it gets assigned to and not an intrinsic property of the lambda itself. Alex From mthornton at optrak.co.uk Wed Dec 16 01:37:03 2009 From: mthornton at optrak.co.uk (Mark Thornton) Date: Wed, 16 Dec 2009 09:37:03 +0000 Subject: Serialization In-Reply-To: <636fd28e0912160114o656bb1c2i6c8d66455c33deda@mail.gmail.com> References: <17b2302a0912152217mf1feac0ld5a9ed17cda82be1@mail.gmail.com> <17b2302a0912160005l40635914u1ba50eb22cd1cbc0@mail.gmail.com> <200912161006.46969.peter.levart@marand.si> <636fd28e0912160114o656bb1c2i6c8d66455c33deda@mail.gmail.com> Message-ID: <4B28AA3F.8060503@optrak.co.uk> Alex Blewitt wrote: > On Wed, Dec 16, 2009 at 9:06 AM, Peter Levart wrote: > >> For the "name" part, maybe alternative is specifying it directly in the lambda expression like this: >> >> #int(int, int) plus = #(int a, int b) a+b; // produces annonymous class name, sensitive to position in source >> > > I don't see that the name is at all relevant, since the name is part > of the variable that it gets assigned to and not an intrinsic property > of the lambda itself. > > The name of an anonymous class is something like ContainingClass$ where is its index in the anonymous classes generated for that container. So declaring another anonymous class changes the name of all anonymous classes appearing later in the source. Mark Thornton From Kieron.Wilkinson at paretopartners.com Wed Dec 16 01:37:27 2009 From: Kieron.Wilkinson at paretopartners.com (Kieron.Wilkinson at paretopartners.com) Date: Wed, 16 Dec 2009 09:37:27 +0000 Subject: Extension Methods Message-ID: > From: Mark Reinhold > Sent: 16 December 2009 05:57 > >> With regard to extension methods, I think the "declaration-site" >> extensions are mostly worthless. Interfaces shouldn't be used this way >> since they are suppose to define a contract to implement. I dare to >> say this is an abuse of the interface mechanism. ... > > I do have some sympathy with this position. At the same time, however, > I'm reluctant to see the classic collection classes consigned to the > limits of the language as it stands today. > > As I said in the proposal, I don't see extension methods as a critical > feature for this release. I'd be content to drop them if they prove > problematic, and consider this issue again in a future release. I don't know if the following suggestion has merit, but given your other comments about considering traits in the future, perhaps it is worth considering making extension methods strictly private to the collection classes and/or the java.* package? This way, extension methods become more of an implementation detail, and if it is later decided to swap that implementation with something like full trait support (yes please! :), it is hopefully possible to do so - you at least have no external client code to worry about. Using the new "closures" with the collection classes would indeed be fantastic, and not enabling that in some form would, I think, bring on a wave of new alternative collection libraries (even I have a one, for functional/immutable uses, that I might feel worth making public), which wouldn't be a particularly ideal situation. My motivation for the suggestion is just that I don't really like the idea of extension methods as a general "language feature". It might be better if they could be overridden in implementation classes, but I'm guessing that would also make it a far more difficult problem to implement... Kieron Wilkinson P.S. Apologies in advance for what follows, it's added by the outgoing email server. This message may contain confidential and privileged information and is intended solely for the use of the named addressee. Access, copying or re-use of the e-mail or any information contained therein by any other person is not authorised. If you are not the intended recipient please notify us immediately by returning the e-mail to the originator and then immediately delete this message. Although we attempt to sweep e-mail and attachments for viruses, we do not guarantee that either are virus-free and accept no liability for any damage sustained as a result of viruses. Please refer to http://www.bnymellon.com/disclaimer/piml.html for certain disclosures. From alex.blewitt at gmail.com Wed Dec 16 01:47:10 2009 From: alex.blewitt at gmail.com (Alex Blewitt) Date: Wed, 16 Dec 2009 09:47:10 +0000 Subject: Serialization In-Reply-To: <4B28AA3F.8060503@optrak.co.uk> References: <17b2302a0912152217mf1feac0ld5a9ed17cda82be1@mail.gmail.com> <17b2302a0912160005l40635914u1ba50eb22cd1cbc0@mail.gmail.com> <200912161006.46969.peter.levart@marand.si> <636fd28e0912160114o656bb1c2i6c8d66455c33deda@mail.gmail.com> <4B28AA3F.8060503@optrak.co.uk> Message-ID: <6EBB4D4F-7C97-4904-A967-4FEED1D57181@gmail.com> On Dec 16, 2009, at 09:37, Mark Thornton wrote: > Alex Blewitt wrote: >> On Wed, Dec 16, 2009 at 9:06 AM, Peter Levart >> wrote: >> >>> For the "name" part, maybe alternative is specifying it directly >>> in the lambda expression like this: >>> >>> #int(int, int) plus = #(int a, int b) a+b; // produces annonymous >>> class name, sensitive to position in source >> >> I don't see that the name is at all relevant, since the name is part >> of the variable that it gets assigned to and not an intrinsic >> property >> of the lambda itself. > The name of an anonymous class is something like ContainingClass$ > where is its index in the anonymous classes generated for that > container. So declaring another anonymous class changes the name of > all anonymous classes appearing later in the source. It won't be generally safe to safe to use the name of the class anyway, will it? ContainingClass may well not exist on the other end. Serialization will need to deal with these specifically, rather than using the classname as an identifer for what to deserialize. It may mean that there is some special kind of class (say, GlobalLambda) to which deserialized lambdas get attached to upon reserialization. An SHA-1 hash of the bytecode to be used is at least as sufficient as Git's mechanism for determining contents of files. So upon writing a lambda, we write out GlobalLambda$sha1hash [bytecode], and on the other end, deserialize the same. Alex From schulz at the-loom.de Wed Dec 16 01:52:43 2009 From: schulz at the-loom.de (Stefan Schulz) Date: Wed, 16 Dec 2009 10:52:43 +0100 Subject: Method calls vs lambda calls In-Reply-To: <636fd28e0912160104y61ebc078j39db9647a1fb8828@mail.gmail.com> References: <7783BF2B-98D6-4E01-8B97-CC19B139AE92@gmail.com> <15e8b9d20912141237y24a64227yab9e0756244df8be@mail.gmail.com> <4B26A561.3050002@the-loom.de> <17b2302a0912142304x5e82ef60jabe569d527789b11@mail.gmail.com> <4EC54BD2-4335-482D-A97B-DA06C98393DA@gmail.com> <4B279833.5010204@optrak.co.uk> <4B279B85.7070804@optrak.co.uk> <4B279D54.9010100@univ-mlv.fr> <4B27A5AB.2080201@optrak.co.uk> <636fd28e0912160104y61ebc078j39db9647a1fb8828@mail.gmail.com> Message-ID: <4B28ADEB.10909@the-loom.de> Alex Blewitt wrote: > On Tue, Dec 15, 2009 at 3:05 PM, Mark Thornton wrote: >>>>> A simple solution would be to specify that method valued fields are in >>>>> the method namespace. Your example would then not compile. I think this >>>>> would be preferable to having different syntax to discriminate between the >>>>> method call and invoking a field. >> >> Howard Lovatt has suggested putting method references in both namespaces >> which would solve that problem. > > For all lambdas, or just those defined at the top level of a class? It > must be the latter, surely; they are always visible in a class (other > than shadowing), whereas variables of type lambda could be created in > nested recursive calls on the stack. Are you confusing lambdas with function-typed variables here? To my understanding, any function-typed variable has to follow the namespace rules because of conflict and hiding issues. > Rather than putting them in the namespace itself, why not synthesise a > bona fide method for them if lambdas are in the top level of a class? This would not work with local and method variables. > protected final double trouble = #int(int a) { a*2 }; I assume you meant the following: #double(int) trouble = #(int a) ( a*2 ); (Not sure, if the compiler takes int to double compatibility.) > That way, it would be visible/understandable by other clients who > would use that class (even if they didn't know about lambdas). Which would only cover a tiny use-side of directly invoking a stored lambda via a method. I don't see the use-cases of such an approach, as it is always possible to write a wrapping method in this case. Stefan From daniel.latremoliere at gmail.com Wed Dec 16 02:35:59 2009 From: daniel.latremoliere at gmail.com (=?ISO-8859-1?Q?Daniel_Latr=E9moli=E8re?=) Date: Wed, 16 Dec 2009 11:35:59 +0100 Subject: Extension methods vs. JSR 292 [Was: Re: Extension methods vs. Traits] In-Reply-To: <20091216062144.4F2C54A0@eggemoggin.niobe.net> References: <20091216062144.4F2C54A0@eggemoggin.niobe.net> Message-ID: <4B28B80F.8000200@gmail.com> >> I would like to understand the final paragraph of the proposal where you are >> saying that the traits are much more significant change than extension methods >> to the language and VM. >> > >From a strictly technical standpoint adding traits might not be a (much?) > more significant change than adding extension methods. > > >From a conceptual standpoint, however, adding traits to the language is > a hugely significant change -- much more significant than adding lambda > expressions. > As new Java knowledge required for programmer, I am OK with the knowledge complexity of traits, given traits will probably need to be a third type like interface (but not a contract) and class (but only one, partly independent, part of implementation without state). A good and very useful implementation will probably need some others changes, like "import MyClass with MyTrait1, MyTrait2;". It is reasonable for me, given current Java7 roadmap, to not include it. Thanks for the response and details, ... then another question between extension methods and JSR 292. > (Extension methods, by contrast, are just a fancy new > variant of static imports.) > Given extension methods are a new Java syntax, I would prefer if fancy variants are only in IDE and doesn't change Java language (even if it is not available for programmers who are not using IDE but can understand better the real Java language). Reading will be slightly more complex because it will be a static call to another class, but cleaner. Then, I have nothing against adding annotations for driving suggests of IDE, like this: @DeclarationSiteExtension(methodName="sort", targetClass="java.util.Collection", targetMethod="sort") public interface List extends Collection { ... } if IDE write call in Java source code as "Collections.sort(list);". You can even add support of this annotation in javadoc if you like it, for helping user by giving him useful methods references for using his List instance. ---------- If you want real extension methods: If you want a source code of the call like "list.sort();", I would prefer if this call becomes a short syntax for a more common invokedynamic call (JSR 292) [3] using another separator than '.' (like ':' in following example), even if IDE add automatically the static call, to the method registering JSR 292 call sites in linkage, using new attributes in preceding @DeclarationSiteExtension annotation [4] or user's configuration for use-site extensions (because use-site extensions are possible with the same syntax/changes). // Example for better understanding public MyClass() { // added by IDE when making call expression to the extension // of List (using the annotation of List). static { Linkage.registerBootstrapMethod(CollectionsExtensions.class, "addListExtensions"); } public void myMethod(List list) { list:sort(); // use ':' and not '.' // compiled with invokedynamic bytecode like // InvokeDynamic.sort(list); } } package java.util; public class CollectionsExtensions { public static void addListExtensions(CallSite site, Object... args) { assert(args[0] instance of List); switch(site.name()) { case "sort": assert(args.length == 1); MethodType sortType = MethodType.make(void.class, List.class); MethodHandle sort = MethodHandles.findStatic(Collection.class, "sort", sortType); site.setTarget(sort); break; } } } [3]: Eat your own dog food. (Or more seriously reuse as much as possible current linkage changes allowed by JSR 292 and why inventing a new specific syntax?). [4]: This will need these two new attributes to declaration-site annotation: @DeclarationSiteExtension(declaratorClass=CollectionsExtensions.class, declaratorMethod="addListExtensions") My personal conclusion: An interface as a contract means that implementers expects no changes in contract, then all user's features doesn't need to pollute the contract: it is not the problem of implementer. I only see annotations (because without effects on code by Java definition) as possible room for helping users of interface and giving them others useful methods. If you want some sort of extension methods in method calls, please add a short syntax for JSR 292 like ':' for compiling "list:sort();" as "InvokeDynamic.sort(list);": it will be useful for many more Java code than simple extension methods. You will have, near for free, declaration-site extensions (with an annotation added) and IDE completion using this annotation, use-site extensions (with some user code for managing CallSite) but without IDE completion if there is not a new annotation on the registered linkage method for declaring extensions added on classes. Thanks for some explanations on lack of relations between extension methods and JSR 292, Daniel. From forax at univ-mlv.fr Wed Dec 16 02:43:35 2009 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Wed, 16 Dec 2009 11:43:35 +0100 Subject: Serialization In-Reply-To: <17b2302a0912152258u74fe428dt398613b5ec3fe167@mail.gmail.com> References: <17b2302a0912152217mf1feac0ld5a9ed17cda82be1@mail.gmail.com> <20091216063857.4CC794A0@eggemoggin.niobe.net> <17b2302a0912152258u74fe428dt398613b5ec3fe167@mail.gmail.com> Message-ID: <4B28B9D7.4050804@univ-mlv.fr> I am affraid that the only solution is to serialize the bytecode of the lambda expression/statement. R?mi Joshua Bloch a ?crit : > Mark, > > I'm sorry to say, I don't know. It's a hard problem. One possibility is to > provide a concise syntax for named singleton subclasses of functional types. > That would finesse the problem rather than solving it. > > Josh > > On Tue, Dec 15, 2009 at 10:38 PM, Mark Reinhold wrote: > > >>> Date: Tue, 15 Dec 2009 22:17:41 -0800 >>> From: Joshua Bloch >>> >>> This is a moderately important decision. In Google's Java MapReduce API, >>> >> we use >> >>> SAM interfaces to represent Mapper and Reducer. Instances must be >>> >> serializable, >> >>> as they're serialized to pass them from the node that starts the >>> >> MapReduce to >> >>> the worker nodes (which do the actual mapping and reduction). That means >>> >> we >> >>> won't be able to use closure syntax for MapReduce, which seems like a >>> >> shame. >> >>> This is no worse than what we do with SAM types today, but it's no >>> >> better, >> >>> either. Can we do better? >>> >> Maybe. How would you suggest we address the concerns which Peter raised? >> >> - Mark >> >> > > From peter.levart at marand.si Wed Dec 16 03:49:19 2009 From: peter.levart at marand.si (Peter Levart) Date: Wed, 16 Dec 2009 12:49:19 +0100 Subject: Serialization In-Reply-To: <4B28B9D7.4050804@univ-mlv.fr> References: <17b2302a0912152217mf1feac0ld5a9ed17cda82be1@mail.gmail.com> <17b2302a0912152258u74fe428dt398613b5ec3fe167@mail.gmail.com> <4B28B9D7.4050804@univ-mlv.fr> Message-ID: <200912161249.19149.peter.levart@marand.si> You don't need to bury that into closure's default serialization logic. You can achieve the same by custom serialization of a class that is a container for a closure. The only service you need from closure is obtaining it's code identification (class name?) and stable serialization of closure's fields. Bytecode can be obtained from closure's class' classloader. Peter On Wednesday 16 December 2009 11:43:35 R?mi Forax wrote: > I am affraid that the only solution is to serialize the bytecode of the > lambda expression/statement. > > R?mi > > Joshua Bloch a ?crit : > > Mark, > > > > I'm sorry to say, I don't know. It's a hard problem. One possibility is to > > provide a concise syntax for named singleton subclasses of functional types. > > That would finesse the problem rather than solving it. > > > > Josh > > > > On Tue, Dec 15, 2009 at 10:38 PM, Mark Reinhold wrote: > > > > > >>> Date: Tue, 15 Dec 2009 22:17:41 -0800 > >>> From: Joshua Bloch > >>> > >>> This is a moderately important decision. In Google's Java MapReduce API, > >>> > >> we use > >> > >>> SAM interfaces to represent Mapper and Reducer. Instances must be > >>> > >> serializable, > >> > >>> as they're serialized to pass them from the node that starts the > >>> > >> MapReduce to > >> > >>> the worker nodes (which do the actual mapping and reduction). That means > >>> > >> we > >> > >>> won't be able to use closure syntax for MapReduce, which seems like a > >>> > >> shame. > >> > >>> This is no worse than what we do with SAM types today, but it's no > >>> > >> better, > >> > >>> either. Can we do better? > >>> > >> Maybe. How would you suggest we address the concerns which Peter raised? > >> > >> - Mark > >> > >> > > > > > > > From forax at univ-mlv.fr Wed Dec 16 03:55:10 2009 From: forax at univ-mlv.fr (=?UTF-8?B?UsOpbWkgRm9yYXg=?=) Date: Wed, 16 Dec 2009 12:55:10 +0100 Subject: Serialization In-Reply-To: <200912161249.19149.peter.levart@marand.si> References: <17b2302a0912152217mf1feac0ld5a9ed17cda82be1@mail.gmail.com> <17b2302a0912152258u74fe428dt398613b5ec3fe167@mail.gmail.com> <4B28B9D7.4050804@univ-mlv.fr> <200912161249.19149.peter.levart@marand.si> Message-ID: <4B28CA9E.50906@univ-mlv.fr> Peter Levart a ?crit : > You don't need to bury that into closure's default serialization logic. You can achieve the same by custom serialization of a class that is a container for a closure. The only service you need from closure is obtaining it's code identification (class name?) and stable serialization of closure's fields. Bytecode can be obtained from closure's class' classloader. > > Peter > Yes, but how to have a stable class name ? R?mi > On Wednesday 16 December 2009 11:43:35 R?mi Forax wrote: > >> I am affraid that the only solution is to serialize the bytecode of the >> lambda expression/statement. >> >> R?mi >> >> Joshua Bloch a ?crit : >> >>> Mark, >>> >>> I'm sorry to say, I don't know. It's a hard problem. One possibility is to >>> provide a concise syntax for named singleton subclasses of functional types. >>> That would finesse the problem rather than solving it. >>> >>> Josh >>> >>> On Tue, Dec 15, 2009 at 10:38 PM, Mark Reinhold wrote: >>> >>> >>> >>>>> Date: Tue, 15 Dec 2009 22:17:41 -0800 >>>>> From: Joshua Bloch >>>>> >>>>> This is a moderately important decision. In Google's Java MapReduce API, >>>>> >>>>> >>>> we use >>>> >>>> >>>>> SAM interfaces to represent Mapper and Reducer. Instances must be >>>>> >>>>> >>>> serializable, >>>> >>>> >>>>> as they're serialized to pass them from the node that starts the >>>>> >>>>> >>>> MapReduce to >>>> >>>> >>>>> the worker nodes (which do the actual mapping and reduction). That means >>>>> >>>>> >>>> we >>>> >>>> >>>>> won't be able to use closure syntax for MapReduce, which seems like a >>>>> >>>>> >>>> shame. >>>> >>>> >>>>> This is no worse than what we do with SAM types today, but it's no >>>>> >>>>> >>>> better, >>>> >>>> >>>>> either. Can we do better? >>>>> >>>>> >>>> Maybe. How would you suggest we address the concerns which Peter raised? >>>> >>>> - Mark >>>> >>>> >>>> >>> >>> >> >> From mthornton at optrak.co.uk Wed Dec 16 04:06:59 2009 From: mthornton at optrak.co.uk (Mark Thornton) Date: Wed, 16 Dec 2009 12:06:59 +0000 Subject: Serialization In-Reply-To: <200912161249.19149.peter.levart@marand.si> References: <17b2302a0912152217mf1feac0ld5a9ed17cda82be1@mail.gmail.com> <17b2302a0912152258u74fe428dt398613b5ec3fe167@mail.gmail.com> <4B28B9D7.4050804@univ-mlv.fr> <200912161249.19149.peter.levart@marand.si> Message-ID: <4B28CD63.6090708@optrak.co.uk> Peter Levart wrote: > Bytecode can be obtained from closure's class' classloader. > > Peter > That will need a change to the existing API. Mark Thornton From peter.levart at marand.si Wed Dec 16 04:19:03 2009 From: peter.levart at marand.si (Peter Levart) Date: Wed, 16 Dec 2009 13:19:03 +0100 Subject: Serialization In-Reply-To: <4B28CA9E.50906@univ-mlv.fr> References: <17b2302a0912152217mf1feac0ld5a9ed17cda82be1@mail.gmail.com> <200912161249.19149.peter.levart@marand.si> <4B28CA9E.50906@univ-mlv.fr> Message-ID: <200912161319.03484.peter.levart@marand.si> On Wednesday 16 December 2009 12:55:10 R?mi Forax wrote: > Peter Levart a ?crit : > > You don't need to bury that into closure's default serialization logic. You can achieve the same by custom serialization of a class that is a container for a closure. The only service you need from closure is obtaining it's code identification (class name?) and stable serialization of closure's fields. Bytecode can be obtained from closure's class' classloader. > > > > Peter > > > > Yes, but how to have a stable class name ? By specifying it (see my previous mail). You won't be referring to closure's class name in code anywhere statically, but serialization logic could, dynamically. Peter > > R?mi > > > On Wednesday 16 December 2009 11:43:35 R?mi Forax wrote: > > > >> I am affraid that the only solution is to serialize the bytecode of the > >> lambda expression/statement. > >> > >> R?mi > >> > >> Joshua Bloch a ?crit : > >> > >>> Mark, > >>> > >>> I'm sorry to say, I don't know. It's a hard problem. One possibility is to > >>> provide a concise syntax for named singleton subclasses of functional types. > >>> That would finesse the problem rather than solving it. > >>> > >>> Josh > >>> > >>> On Tue, Dec 15, 2009 at 10:38 PM, Mark Reinhold wrote: > >>> > >>> > >>> > >>>>> Date: Tue, 15 Dec 2009 22:17:41 -0800 > >>>>> From: Joshua Bloch > >>>>> > >>>>> This is a moderately important decision. In Google's Java MapReduce API, > >>>>> > >>>>> > >>>> we use > >>>> > >>>> > >>>>> SAM interfaces to represent Mapper and Reducer. Instances must be > >>>>> > >>>>> > >>>> serializable, > >>>> > >>>> > >>>>> as they're serialized to pass them from the node that starts the > >>>>> > >>>>> > >>>> MapReduce to > >>>> > >>>> > >>>>> the worker nodes (which do the actual mapping and reduction). That means > >>>>> > >>>>> > >>>> we > >>>> > >>>> > >>>>> won't be able to use closure syntax for MapReduce, which seems like a > >>>>> > >>>>> > >>>> shame. > >>>> > >>>> > >>>>> This is no worse than what we do with SAM types today, but it's no > >>>>> > >>>>> > >>>> better, > >>>> > >>>> > >>>>> either. Can we do better? > >>>>> > >>>>> > >>>> Maybe. How would you suggest we address the concerns which Peter raised? > >>>> > >>>> - Mark > >>>> > >>>> > >>>> > >>> > >>> > >> > >> > > From peter.levart at marand.si Wed Dec 16 04:23:22 2009 From: peter.levart at marand.si (Peter Levart) Date: Wed, 16 Dec 2009 13:23:22 +0100 Subject: Serialization In-Reply-To: <4B28CD63.6090708@optrak.co.uk> References: <17b2302a0912152217mf1feac0ld5a9ed17cda82be1@mail.gmail.com> <200912161249.19149.peter.levart@marand.si> <4B28CD63.6090708@optrak.co.uk> Message-ID: <200912161323.22403.peter.levart@marand.si> On Wednesday 16 December 2009 13:06:59 Mark Thornton wrote: > Peter Levart wrote: > > Bytecode can be obtained from closure's class' classloader. > > > > Peter > > > > That will need a change to the existing API. > > Mark Thornton > > Using existing API, this should allways work: #void() someClosure = #() { ... }; URL bytecode = someClosure.getClass().getClassLoader().getResource(someClosure.getClass().getName().replace('.', '/') + ".class"); Peter From mthornton at optrak.co.uk Wed Dec 16 04:32:40 2009 From: mthornton at optrak.co.uk (Mark Thornton) Date: Wed, 16 Dec 2009 12:32:40 +0000 Subject: Serialization In-Reply-To: <200912161323.22403.peter.levart@marand.si> References: <17b2302a0912152217mf1feac0ld5a9ed17cda82be1@mail.gmail.com> <200912161249.19149.peter.levart@marand.si> <4B28CD63.6090708@optrak.co.uk> <200912161323.22403.peter.levart@marand.si> Message-ID: <4B28D368.5010106@optrak.co.uk> Peter Levart wrote: > On Wednesday 16 December 2009 13:06:59 Mark Thornton wrote: > >> Peter Levart wrote: >> >>> Bytecode can be obtained from closure's class' classloader. >>> >>> Peter >>> >>> >> That will need a change to the existing API. >> >> Mark Thornton >> >> >> > > Using existing API, this should allways work: > > #void() someClosure = #() { ... }; > > URL bytecode = someClosure.getClass().getClassLoader().getResource(someClosure.getClass().getName().replace('.', '/') + ".class"); > > > Peter > I can't find anything in the documentation that *guarantees* that will work. Nothing seems to prevent a ClassLoader from using separate spaces for classes and regular resources. Mark Thornton From howard.lovatt at iee.org Wed Dec 16 04:50:19 2009 From: howard.lovatt at iee.org (Howard Lovatt) Date: Wed, 16 Dec 2009 13:50:19 +0100 Subject: Method calls vs lambda calls In-Reply-To: <15e8b9d20912150821s707be3c0k4cc2ad040c3bca9@mail.gmail.com> References: <3dd3f56a0912150653s6d92945albca4fc422eaf5b1f@mail.gmail.com> <3dd3f56a0912150711v25ed7a9bi73b46fc0d92fee1@mail.gmail.com> <15e8b9d20912150821s707be3c0k4cc2ad040c3bca9@mail.gmail.com> Message-ID: <3dd3f56a0912160450y67c61db3l21ffc97556d1f8ba@mail.gmail.com> Answers inline below 2009/12/15 Neal Gafter : > On Tue, Dec 15, 2009 at 7:11 AM, Howard Lovatt > wrote: >> >> I remain to be convinced that method references are a good idea, since >> they pull Java much further towards structural typing than at present >> and this will be very confusing for people to be presented with two >> type systems. > > I don't know what this argument has to do about method references (are you > talking about function types?), Yes, my mistake I meant to say function types > but your argument makes no sense.? They're a > good idea because they will confuse people?? Huh? I think you might have misread what I said, I said "I *remain* to be convinced ... since ... this will be very confusing". Your confusion was probably caused by my mistake of saying method references - sorry. To spell this out I think that *function types* are a bad idea because they will confuse people. People will be confused because they are structurally typed, whereas as the rest (well most) of Java is nominally typed. >> >> That desirability point aside, the technical issue of what name space >> a function type should be in can be resolved by putting a function >> type in both the method and the field/variable name spaces. > > Function types are anonymous, and so don't need to go in any namespace.? Do > you mean a variable of function type? Yes, I had assumed that was apparent from the context of the discussion - that is what the thread is about. This discussion in the thread is centered on how you get the following to work: #int() fortyTwo = #int() (42); out.println( fortyTwo ); // prints something like Function_intATSomeAddress (I used AT instead of an At symbol because of pipermail) out.println( fortyTwo() ); // prints 42 >> Actually there are still some rough edges since methods are >> dynamically resolved and fields aren't. You can paper over this >> >> difference a little by saying that function types can't be hidden. > > What do you mean: hiding triggers an error (that would make code very > fragile, especially where the hidden name isn't even used)?? Or that the > name isn't hidden? If you allow function-type variables to be hidden (static case) or shadowed (instance case) then it can be very confusing, e.g.: class FortyOne { int f() { return 41; } #int() ft = #int() (41); } class FortyTwo extends FortyOne { int f() { return 42; } #int() ft = #int() (42); } FortyOne aFortyTWO = new FortyTwo(); out.println( aFortyTWO.f() ); // prints 42 out.println( aFortyTWO.ft() ); // prints 41!!! To prevent the above confusion you could say that function-type variables cannot be hidden/shadowed then this makes the above example an error, on the other hand it isn't very Java like. The other options are: 1. The FCM solution of requiring call, e.g. aFortyTwo.ft.call() 2. Introduce properties and say that function types can only be used as a property (a much bigger change and odd that function types can only be a property) 3. Only allow the non-call syntax, e.g. aFortyTWO.ft(), if there is no method called ft and if ft hasn't been shadowed or hidden by another field/local (again, not very Java like) 4. Don't allow function types at all - my favorite! Cheers, -- Howard. > > Cheers, > Neal > > ______________________________________________________________________ > This email has been scanned by the MessageLabs Email Security System. > For more information please visit http://www.messagelabs.com/email > ______________________________________________________________________ > -- -- Howard. From schulz at the-loom.de Wed Dec 16 05:03:28 2009 From: schulz at the-loom.de (Stefan Schulz) Date: Wed, 16 Dec 2009 14:03:28 +0100 Subject: Method calls vs lambda calls In-Reply-To: <3dd3f56a0912160450y67c61db3l21ffc97556d1f8ba@mail.gmail.com> References: <3dd3f56a0912150653s6d92945albca4fc422eaf5b1f@mail.gmail.com> <3dd3f56a0912150711v25ed7a9bi73b46fc0d92fee1@mail.gmail.com> <15e8b9d20912150821s707be3c0k4cc2ad040c3bca9@mail.gmail.com> <3dd3f56a0912160450y67c61db3l21ffc97556d1f8ba@mail.gmail.com> Message-ID: <4B28DAA0.6050302@the-loom.de> Howard Lovatt wrote: > If you allow function-type variables to be hidden (static case) or > shadowed (instance case) then it can be very confusing, e.g.: > > class FortyOne { > int f() { return 41; } > #int() ft = #int() (41); > } > class FortyTwo extends FortyOne { > int f() { return 42; } > #int() ft = #int() (42); > } > FortyOne aFortyTWO = new FortyTwo(); > out.println( aFortyTWO.f() ); // prints 42 > out.println( aFortyTWO.ft() ); // prints 41!!! If function-typed variables are in the method name scope, why should not ft be overridden in the same way that f is overridden? Stefan From peter.levart at marand.si Wed Dec 16 05:09:02 2009 From: peter.levart at marand.si (Peter Levart) Date: Wed, 16 Dec 2009 14:09:02 +0100 Subject: Serialization In-Reply-To: <4B28D368.5010106@optrak.co.uk> References: <17b2302a0912152217mf1feac0ld5a9ed17cda82be1@mail.gmail.com> <200912161323.22403.peter.levart@marand.si> <4B28D368.5010106@optrak.co.uk> Message-ID: <200912161409.02274.peter.levart@marand.si> On Wednesday 16 December 2009 13:32:40 Mark Thornton wrote: > >> That will need a change to the existing API. > >> > >> Mark Thornton > >> > >> > >> > > > > Using existing API, this should allways work: > > > > #void() someClosure = #() { ... }; > > > > URL bytecode = someClosure.getClass().getClassLoader().getResource(someClosure.getClass().getName().replace('.', '/') + ".class"); > > > > > > Peter > > > I can't find anything in the documentation that guarantees that will > work. Nothing seems to prevent a ClassLoader from using separate spaces > for classes and regular resources. But I haven't seen any implementation that separates those two. JDK platform classloader's don't as far as I know. Peter From howard.lovatt at iee.org Wed Dec 16 06:16:32 2009 From: howard.lovatt at iee.org (Howard Lovatt) Date: Wed, 16 Dec 2009 15:16:32 +0100 Subject: Method calls vs lambda calls Message-ID: <3dd3f56a0912160616p478ec54m88aad23e2c8a9c78@mail.gmail.com> > If function-typed variables are in the method name scope, why should not > ft be overridden in the same way that f is overridden? Alex Blewitt also touched on this point, you can't actually make a method called ft because you could assign a different lambda to it which would require the methods body to change. As I said in the previous post you could do this via something like properties (which have to be fields), e.g. assume that properties were automatically generated by the compiler (like Scala) and that when you wrote: property #int() ft = #int() (41); What the compiler actually produced was: private #int() ft = ftInit(); public #int() initFt() { return #int() (42); } public final #int() getFt() { return ft; } public final #int() setFt( final #int() ft ) { this.ft = ft; return ft; } public final int ft() { return ft.call(); } And the following translations were also performed by the compiler: You write -> Compiler outputs ft = #int() (42); -> setFt( #int() (42) ); #int() i = ft; -> #int() i = getFt(); And in a derived class if the property is initialized to a different value, i.e. you write "property #int() ft = #int() (43);" in a derived class then the compiler outputs: @Override public #int() initFt() { return #int() (43) }; in the derived class. Anyway I thought this too big a change and that a function-type variable having to be a property was odd and hence suggested just putting the name in both name spaces as easier (but not actually generating the method). Putting the name in both spaces, as I said before, also has some undesirable effects. All in all, I think it best to forget about function-type variables altogether. From schulz at the-loom.de Wed Dec 16 06:36:31 2009 From: schulz at the-loom.de (Stefan Schulz) Date: Wed, 16 Dec 2009 15:36:31 +0100 Subject: Method calls vs lambda calls In-Reply-To: <3dd3f56a0912160616p478ec54m88aad23e2c8a9c78@mail.gmail.com> References: <3dd3f56a0912160616p478ec54m88aad23e2c8a9c78@mail.gmail.com> Message-ID: <4B28F06F.1030402@the-loom.de> Howard Lovatt wrote: >> If function-typed variables are in the method name scope, why should not >> ft be overridden in the same way that f is overridden? > > Alex Blewitt also touched on this point, you can't actually make a > method called ft because you could assign a different lambda to it > which would require the methods body to change. As I said in the > previous post you could do this via something like properties (which > have to be fields), e.g. assume that properties were automatically > generated by the compiler (like Scala) and that when you wrote: I didn't say anything about making a method. If the short-hand invocation syntax is allowed, putting names of function-typed variables in the same (scope-relative) space like methods is a way to ensure not to have methods and function-typed variables with the same name. As this has to hold for inheritance, too, I do not see a problem in function-typed variables of subclasses to @Override those of a superclass, as the information is already there. (Of course, they must additionally hide normal variables having the same name.) > All in all, I think it best to forget about function-type variables altogether. Without function-types, lambda functions are of very reduced use. Stefan From jjb at google.com Wed Dec 16 07:46:14 2009 From: jjb at google.com (Joshua Bloch) Date: Wed, 16 Dec 2009 07:46:14 -0800 Subject: Serialization In-Reply-To: <200912161409.02274.peter.levart@marand.si> References: <17b2302a0912152217mf1feac0ld5a9ed17cda82be1@mail.gmail.com> <200912161323.22403.peter.levart@marand.si> <4B28D368.5010106@optrak.co.uk> <200912161409.02274.peter.levart@marand.si> Message-ID: <17b2302a0912160746o49ca8dfx97427314e4c0bc3a@mail.gmail.com> Folks, Associating a class name with a closure is only half the battle. Loosely speaking, it takes you from serializing an anonymous class instance to a named *non-static* nested class. But even the latter is generally considered a bad idea, because you end up serializing the enclosing instance, which is rarely what you want. The serializable SAM interfaces that we use in MapReduce are typically nested *static *classes (hence no enclosing instance). I'd argue that this is a reasonable restriction for serializable function objects (the static part, not the nested part). Josh From neal at gafter.com Wed Dec 16 08:07:53 2009 From: neal at gafter.com (Neal Gafter) Date: Wed, 16 Dec 2009 08:07:53 -0800 Subject: Method calls vs lambda calls In-Reply-To: <4B28F06F.1030402@the-loom.de> References: <3dd3f56a0912160616p478ec54m88aad23e2c8a9c78@mail.gmail.com> <4B28F06F.1030402@the-loom.de> Message-ID: <15e8b9d20912160807l4132b88au2965410582b62f13@mail.gmail.com> On Wed, Dec 16, 2009 at 6:36 AM, Stefan Schulz wrote: > Howard Lovatt wrote: > >> If function-typed variables are in the method name scope, why should not > >> ft be overridden in the same way that f is overridden? > > > > Alex Blewitt also touched on this point, you can't actually make a > > method called ft because you could assign a different lambda to it > > which would require the methods body to change. As I said in the > > previous post you could do this via something like properties (which > > have to be fields), e.g. assume that properties were automatically > > generated by the compiler (like Scala) and that when you wrote: > > I didn't say anything about making a method. If the short-hand > invocation syntax is allowed, putting names of function-typed variables > in the same (scope-relative) space like methods is a way to ensure not > to have methods and function-typed variables with the same name. I'm afraid it doesn't ensure that at all. Because methods may overload, a given scope may have many definitions for a given name in the method namespace. > As this > has to hold for inheritance, too, I do not see a problem in > function-typed variables of subclasses to @Override those of a > superclass, as the information is already there. (Of course, they must > additionally hide normal variables having the same name.) > What semantics are you imagining for this overriding? What if the thing being overridden is a method? From peter.levart at marand.si Wed Dec 16 08:43:15 2009 From: peter.levart at marand.si (Peter Levart) Date: Wed, 16 Dec 2009 17:43:15 +0100 Subject: Serialization In-Reply-To: <17b2302a0912160746o49ca8dfx97427314e4c0bc3a@mail.gmail.com> References: <17b2302a0912152217mf1feac0ld5a9ed17cda82be1@mail.gmail.com> <200912161409.02274.peter.levart@marand.si> <17b2302a0912160746o49ca8dfx97427314e4c0bc3a@mail.gmail.com> Message-ID: <200912161743.15659.peter.levart@marand.si> On Wednesday 16 December 2009 16:46:14 Joshua Bloch wrote: > Folks, > > Associating a class name with a closure is only half the battle. Loosely > speaking, it takes you from serializing an anonymous class instance to a > named *non-static* nested class. But even the latter is generally > considered a bad idea, because you end up serializing the enclosing > instance, which is rarely what you want. The serializable SAM interfaces > that we use in MapReduce are typically nested *static *classes (hence no > enclosing instance). I'd argue that this is a reasonable restriction for > serializable function objects (the static part, not the nested part). > > Josh > > Compiler can generate static class if closure doesn't capture any instance variables of the enclosing class and doesn't call any instance methods of the enclosing class and doesn't use "this" keyword. Capturing local variables does not prevent compiler from generating static class. I wouldn't prevent serializability of non-static closures though. If one should be worried about that, the compiler could issue a special warning that is opt-in type (accompanied with annotation for the same purpose). What is important I think is that generated closure class uses the same names for it's fields as the names of corresponding captured local variables. This way the serialization format stays the same if the set of capcured local variables does not change (regardles of the inner rearrangements of closure's code). Renaming a captured local variable then has the same effect for serialization format of the closure as renaming an instance variable has for a normal class. Peter From jjb at google.com Wed Dec 16 08:51:24 2009 From: jjb at google.com (Joshua Bloch) Date: Wed, 16 Dec 2009 08:51:24 -0800 Subject: Serialization In-Reply-To: <200912161743.15659.peter.levart@marand.si> References: <17b2302a0912152217mf1feac0ld5a9ed17cda82be1@mail.gmail.com> <200912161409.02274.peter.levart@marand.si> <17b2302a0912160746o49ca8dfx97427314e4c0bc3a@mail.gmail.com> <200912161743.15659.peter.levart@marand.si> Message-ID: <17b2302a0912160851w30c3b4ddp9e053a983d64119b@mail.gmail.com> Peter, Compiler can generate static class if closure doesn't capture any instance > variables of the enclosing class and doesn't call any instance methods of > the enclosing class and doesn't use "this" keyword. Capturing local > variables does not prevent compiler from generating static class. Agreed. > I wouldn't prevent serializability of non-static closures though. If one > should be worried about that, the compiler could issue a special warning > that is opt-in type (accompanied with annotation for the same purpose). > I'm not sure where the compiler would issue the warning: serialization is not a language feature; it's accomplished by invoking a method. The compiler may have no indication that the object being serialized is of a function type. I agree that it's inconsistent with our current approach to serialization (where we do let people serialize instances of non-static nested classes), but it's usually a mistake when people do it. > > What is important I think is that generated closure class uses the same > names for it's fields as the names of corresponding captured local > variables. This way the serialization format stays the same if the set of > capcured local variables does not change (regardles of the inner > rearrangements of closure's code). Renaming a captured local variable then > has the same effect for serialization format of the closure as renaming an > instance variable has for a normal class. Agreed. I see this as necessary but not sufficient, though. Josh From mr at sun.com Wed Dec 16 08:54:24 2009 From: mr at sun.com (Mark Reinhold) Date: Wed, 16 Dec 2009 08:54:24 -0800 Subject: Revising interfaces In-Reply-To: mthornton@optrak.co.uk; Fri, 11 Dec 2009 10:16:17 GMT; <4B221BF1.9090700@optrak.co.uk> Message-ID: <20091216165424.95B31560@eggemoggin.niobe.net> > Date: Fri, 11 Dec 2009 10:16:17 +0000 > From: Mark Thornton > There are some interfaces (e.g. java.sql.ResultSet) that have been > changed many times. Presumably the theory is that not too many implement > those interfaces and thus not too many will be annoyed by the changes. Exactly. > Could we consider annotating interface methods (@since("1.1") perhaps) > and providing a default implementation for those methods. Then require > the JVM to insert the default implementation when loading > implementations of the interface (and where the method is not already > implemented). > > This would preserve all the existing character of interfaces. The down > side is potential collision with existing methods having the same > signature, but that is something of a hazard with extension methods as well. I think this boils down to essentially the same thing as traits, with all of the same issues. - Mark From mr at sun.com Wed Dec 16 09:00:11 2009 From: mr at sun.com (Mark Reinhold) Date: Wed, 16 Dec 2009 09:00:11 -0800 Subject: Extension methods and API evolution In-Reply-To: pdoubleya@gmail.com; Fri, 11 Dec 2009 12:02:50 +0100; <64efa1ba0912110302g2aa55447mcd4256618492d2f2@mail.gmail.com> Message-ID: <20091216170011.52F20560@eggemoggin.niobe.net> > Date: Fri, 11 Dec 2009 12:02:50 +0100 > From: Patrick Wright > I'd like to restate a comment regarding declaration-site extension > methods that I posted to Peter Ah?'s blog when he suggested them a > couple of years ago > (http://digital-sushi.org/entry/declaration-site-extension-methods/). > > Use-site extension methods have the advantage that the extension > methods are not necessarily part of the JDK. ... > > I understand the risk of creating "dialects" of code by allowing > use-site extension methods, but I think the alternative is simply too > restrictive. I understand your view, but I can't agree. One of the primary values of the Java language is its inherent readability. Use-site extension methods, like many other oft-requested features (e.g., macros), would significantly degrade that value. - Mark From pbenedict at apache.org Wed Dec 16 09:24:10 2009 From: pbenedict at apache.org (Paul Benedict) Date: Wed, 16 Dec 2009 11:24:10 -0600 Subject: Extension methods and API evolution In-Reply-To: <20091216170011.52F20560@eggemoggin.niobe.net> References: <64efa1ba0912110302g2aa55447mcd4256618492d2f2@mail.gmail.com> <20091216170011.52F20560@eggemoggin.niobe.net> Message-ID: Mark, > I understand your view, but I can't agree. ?One of the primary values > of the Java language is its inherent readability. ?Use-site extension > methods, like many other oft-requested features (e.g., macros), would > significantly degrade that value. It's true that use-site extensions degrade readability, but it's because of static import. The loss of the class qualifier is always a problem for readability. I see that as a lesser evil compared to adding interface methods to declaration-site extensions, which, as it shows, aren't really interface methods for implementing. Paul From pdoubleya at gmail.com Wed Dec 16 09:31:18 2009 From: pdoubleya at gmail.com (Patrick Wright) Date: Wed, 16 Dec 2009 18:31:18 +0100 Subject: Extension methods and API evolution In-Reply-To: <20091216170011.52F20560@eggemoggin.niobe.net> References: <64efa1ba0912110302g2aa55447mcd4256618492d2f2@mail.gmail.com> <20091216170011.52F20560@eggemoggin.niobe.net> Message-ID: <64efa1ba0912160931k1867f9d3l58aeae4f329d61a4@mail.gmail.com> > I understand your view, but I can't agree. ?One of the primary values > of the Java language is its inherent readability. ?Use-site extension > methods, like many other oft-requested features (e.g., macros), would > significantly degrade that value. I understand that point, and, putting aside use-case extension methods as a potential solution, think that we will still have a problem. If extension methods are declaration-site, then java.util.List and friends will have some methods added to them in JDK 7. These will then be part of the official JDK API, which means, first, you have until mid-2010 to get them right, second, you will never be able to change or remove them, and third, we will all have to wait until 201X to have any new(er) improved extension methods for those interfaces. It would seem if this will block any opportunity for exploring improvements, and distributing those via, e.g. open source projects. Essentially, for the standard Collections API, we will be adding a special sort of workaround to allow the interfaces to seem as if it had been extended; it will avoid the problems with actually modifying the interfaces in question, but will not allow for "real" evolution outside of the JDK release cycle. This seems too constraining. Evolution involves trial and error over time. I think what no one wants are magic extensions which appear in the code without any choice on the part of the programmer, and are not obvious from the source. But if there were some way to (waving hands vaguely) to declare in the imports "...and extend List with BetterReduceMethods" then that would not be an issue. Perhaps I'm missing some way to reconcile this... Regards Patrick Regards Patrick From schulz at the-loom.de Wed Dec 16 11:10:58 2009 From: schulz at the-loom.de (Stefan Schulz) Date: Wed, 16 Dec 2009 20:10:58 +0100 Subject: Method calls vs lambda calls In-Reply-To: <15e8b9d20912160807l4132b88au2965410582b62f13@mail.gmail.com> References: <3dd3f56a0912160616p478ec54m88aad23e2c8a9c78@mail.gmail.com> <4B28F06F.1030402@the-loom.de> <15e8b9d20912160807l4132b88au2965410582b62f13@mail.gmail.com> Message-ID: <4B2930C2.5010309@the-loom.de> Neal Gafter wrote: > On Wed, Dec 16, 2009 at 6:36 AM, Stefan Schulz > wrote: > I didn't say anything about making a method. If the short-hand > invocation syntax is allowed, putting names of function-typed variables > in the same (scope-relative) space like methods is a way to ensure not > to have methods and function-typed variables with the same name. > > I'm afraid it doesn't ensure that at all. Because methods may overload, > a given scope may have many definitions for a given name in the method > namespace. Too bad. Is there any possibility to hold the full signature of methods and function-typed variables in some way to being able to resolve these conflicts? Maybe an additional function space? Sorry, if this sounds a bit naive. > As this > has to hold for inheritance, too, I do not see a problem in > function-typed variables of subclasses to @Override those of a > superclass, as the information is already there. (Of course, they must > additionally hide normal variables having the same name.) > > > What semantics are you imagining for this overriding? What if the thing > being overridden is a method? I didn't mean to being able to override methods with function-typed variables, or vice versa (although this sounds interesting). So, what would be the conclusion? * If any method m exists in a class's hierarchy, one cannot define a function-typed field m? * If a function-typed field m exists in a class's hierarchy, one cannot define a method named m? * If a function-typed field m exists in a class's hierarchy, will a field named m (of any type?) in a subclass hide the function-typed field m? * If a non-function-typed field m hides a superclass's function-typed field m, would it be possible to define a method named m in that very subclass? Stefan From neal at gafter.com Wed Dec 16 11:38:46 2009 From: neal at gafter.com (Neal Gafter) Date: Wed, 16 Dec 2009 11:38:46 -0800 Subject: Method calls vs lambda calls In-Reply-To: <4B2930C2.5010309@the-loom.de> References: <3dd3f56a0912160616p478ec54m88aad23e2c8a9c78@mail.gmail.com> <4B28F06F.1030402@the-loom.de> <15e8b9d20912160807l4132b88au2965410582b62f13@mail.gmail.com> <4B2930C2.5010309@the-loom.de> Message-ID: <15e8b9d20912161138o2c2042f8u14b8983034b91b1@mail.gmail.com> On Wed, Dec 16, 2009 at 11:10 AM, Stefan Schulz wrote: > Neal Gafter wrote: > >> On Wed, Dec 16, 2009 at 6:36 AM, Stefan Schulz > > wrote: >> I didn't say anything about making a method. If the short-hand >> invocation syntax is allowed, putting names of function-typed variables >> in the same (scope-relative) space like methods is a way to ensure not >> to have methods and function-typed variables with the same name. >> >> I'm afraid it doesn't ensure that at all. Because methods may overload, >> a given scope may have many definitions for a given name in the method >> namespace. >> > > Too bad. Is there any possibility to hold the full signature of methods and > function-typed variables in some way to being able to resolve these > conflicts? Maybe an additional function space? Sorry, if this sounds a bit > naive. I'm not sure what you're asking. The mechanism for resolving these conflicts today is (compile-time) overload resolution. It would have to be extended to handle the case of a mixture of methods and variables of function type. > As this >> has to hold for inheritance, too, I do not see a problem in >> function-typed variables of subclasses to @Override those of a >> superclass, as the information is already there. (Of course, they must >> additionally hide normal variables having the same name.) >> >> >> What semantics are you imagining for this overriding? What if the thing >> being overridden is a method? >> > > I didn't mean to being able to override methods with function-typed > variables, or vice versa (although this sounds interesting). > > So, what would be the conclusion? > * If any method m exists in a class's hierarchy, one cannot define a > function-typed field m? > * If a function-typed field m exists in a class's hierarchy, one cannot > define a method named m? > * If a function-typed field m exists in a class's hierarchy, will a field > named m (of any type?) in a subclass hide the function-typed field m? > * If a non-function-typed field m hides a superclass's function-typed field > m, would it be possible to define a method named m in that very subclass? Good questions, and there are many more. Function-typed variables can be declared as local variables and parameters too. They can also have a type of a generic parameter in a superclass but be inherited into a subclass as a function type: *class Base { T t; int t(int x) { return x; } } class Derived: Base<#int(int)> {} * if Derived.t in the function namespace? A complete specification must provide clear answers to all these questions. Cheers, Neal From mr at sun.com Wed Dec 16 11:45:19 2009 From: mr at sun.com (Mark Reinhold) Date: Wed, 16 Dec 2009 11:45:19 -0800 Subject: Comments on the straw man... In-Reply-To: neal@gafter.com; Fri, 11 Dec 2009 11:17:51 PST; <15e8b9d20912111117i3850004dne0b391c5669e216a@mail.gmail.com> Message-ID: <20091216194519.8D710560@eggemoggin.niobe.net> > Date: Fri, 11 Dec 2009 11:17:51 -0800 > From: Neal Gafter > These are thoughts that occur to me on first reading of Mark's strawman. > > [ Many good questions, many of which are not answered > by any existing proposal ] > > ... > > 0. Overall impression. > > Overall, my impression is that this strawman sets a stake in the ground > about how the language features might fit together without actually working > it out or verifying that the ideas are mutually compatible. It appears to > address the simplest use cases only. There is not enough detail to evaluate > most of it. A great deal of work will be required to turn the ideas into a > coherent language specification, and that will likely require a significant > revision of the initial ideas. Many of my questions would be answered in > the effort; it isn't clear what purpose was served by publishing the > strawman. Well, as you yourself say, the purpose was to set "a stake in the ground about how the language features might fit together without actually working it out." So of course many details are missing. I committed publicly to initiate an open discussion, and publishing the straw-man proposal seemed the best way to do that. I could, alternatively, have waited and posted a more-complete proposal, but that would no doubt have triggered cries of "NIH". (Such cries have, sadly, already been raised.) I could have chosen one of the existing proposals as a starting point but that would've been seen, rightly, as heavy-handed. Neither of these alternatives would have been a good way to begin an effort to build consensus around the ultimate design. It may well be that one of the existing proposals is a good starting point, but I'd like to see some discussion of that topic before making such a decision. > Given the amount of language design work remaining and the short time frame > (5-6 months to feature complete), does Sun plan to devote someone (or a > team) with the appropriate skills (or who have the time to develop those > skills) to the task? Yes, of course. - Mark From neal at gafter.com Wed Dec 16 11:59:15 2009 From: neal at gafter.com (Neal Gafter) Date: Wed, 16 Dec 2009 11:59:15 -0800 Subject: Comments on the straw man... In-Reply-To: <20091216194519.8D710560@eggemoggin.niobe.net> References: <15e8b9d20912111117i3850004dne0b391c5669e216a@mail.gmail.com> <20091216194519.8D710560@eggemoggin.niobe.net> Message-ID: <15e8b9d20912161159g790ed77cq2784795014bfb714@mail.gmail.com> On Wed, Dec 16, 2009 at 11:45 AM, Mark Reinhold wrote: > > Given the amount of language design work remaining and the short time > frame > > (5-6 months to feature complete), does Sun plan to devote someone (or a > > team) with the appropriate skills (or who have the time to develop those > > skills) to the task? > > Yes, of course. > Can you please give us a hint who will be devoted to the effort? Cheers, Neal From john at milsson.nu Wed Dec 16 12:27:12 2009 From: john at milsson.nu (John Nilsson) Date: Wed, 16 Dec 2009 21:27:12 +0100 Subject: Implicit return syntax error In-Reply-To: <90044083-641B-4770-BFE0-4297503B3A36@gmail.com> References: <20091216054253.BCCA14A0@eggemoggin.niobe.net> <90044083-641B-4770-BFE0-4297503B3A36@gmail.com> Message-ID: On Wed, Dec 16, 2009 at 9:50 AM, Alex Blewitt wrote: > Python: > > >>> sq = lambda x: x**2 > >>> sq(4) > 16 Speaking of terseness. What do people think of a syntax like this: #int(int,int) op = (*) or int prod = intList.reduce(*) In a similar vein String s = someList.map(.toString()).reduce(+","+) BR, John From grev at miginfocom.com Wed Dec 16 13:06:15 2009 From: grev at miginfocom.com (Mikael Grev) Date: Wed, 16 Dec 2009 22:06:15 +0100 Subject: Comments on the straw man... In-Reply-To: <20091216194519.8D710560@eggemoggin.niobe.net> References: <20091216194519.8D710560@eggemoggin.niobe.net> Message-ID: <1B6F5BBF-40EB-4B63-B0CD-2E20860CB00A@miginfocom.com> > I could, alternatively, have waited and posted a more-complete proposal, > but that would no doubt have triggered cries of "NIH". (Such cries have, > sadly, already been raised.) I could have chosen one of the existing > proposals as a starting point but that would've been seen, rightly, as > heavy-handed. Neither of these alternatives would have been a good way > to begin an effort to build consensus around the ultimate design. A fourth way might have been to blog that closures was again on the table because of new time constraints. That the right amount of complexity is probably something in the middle and with that input if the developer community could unite behind something like BGGA but without control structures (or FCM without JCA). To me that would have a good possibility to unite. But, if you are 100% confident that you can get unification around a new proposal, implement and test it in time for Java 7 then that's fine. I just find it pretty risky. About the crying. If you have three-four very serious proposals, developed by really smart people, using hundreds of hours of work and you still squeeze in a new Sun made proposal in between, what did you expect? Cheers, Mikael From alex.blewitt at gmail.com Wed Dec 16 13:06:17 2009 From: alex.blewitt at gmail.com (Alex Blewitt) Date: Wed, 16 Dec 2009 21:06:17 +0000 Subject: Serialization In-Reply-To: <17b2302a0912160746o49ca8dfx97427314e4c0bc3a@mail.gmail.com> References: <17b2302a0912152217mf1feac0ld5a9ed17cda82be1@mail.gmail.com> <200912161323.22403.peter.levart@marand.si> <4B28D368.5010106@optrak.co.uk> <200912161409.02274.peter.levart@marand.si> <17b2302a0912160746o49ca8dfx97427314e4c0bc3a@mail.gmail.com> Message-ID: <636fd28e0912161306h72104706scce3e7d4d4aeb52e@mail.gmail.com> On Wed, Dec 16, 2009 at 3:46 PM, Joshua Bloch wrote: > Associating a class name with a closure is only half the battle. ?Loosely > speaking, it takes you from serializing an anonymous class instance to a > named *non-static* nested class. ?But even the latter is generally > considered a bad idea, because you end up serializing the enclosing > instance, which is rarely what you want. The serializable SAM interfaces > that we use in MapReduce are typically nested *static *classes (hence no > enclosing instance). I'd argue that this is a reasonable restriction for > serializable function objects (the static part, not the nested part). I agree that not all lambdas should be serializable. Are we talking 'static' as defined by the compiler, or by the developer in the source? I'd argue that a good compiler should be able to promote (for want of a better description) 'instance' closures to 'static' closures automatically iff the appropriate conditions hold (no references to this variables etc.). In that case, one would be able to use #int(int a) { return a*42; } as a serializable lambda, regardless of whether it was defined (in the source) as a static, instance, or stack-based variable. Alex From jjb at google.com Wed Dec 16 13:20:07 2009 From: jjb at google.com (Joshua Bloch) Date: Wed, 16 Dec 2009 13:20:07 -0800 Subject: Comments on the straw man... In-Reply-To: <1B6F5BBF-40EB-4B63-B0CD-2E20860CB00A@miginfocom.com> References: <20091216194519.8D710560@eggemoggin.niobe.net> <1B6F5BBF-40EB-4B63-B0CD-2E20860CB00A@miginfocom.com> Message-ID: <17b2302a0912161320h7085ad05ge7b19723a12eb973@mail.gmail.com> Mikael, Hi. I have a different perspective on this. On Wed, Dec 16, 2009 at 1:06 PM, Mikael Grev wrote: > > if you are 100% confident that you can get unification around a new > proposal, implement and test it in time for Java 7 then that's fine. I just > find it pretty risky. > I'm not worried about the risk of missing Java 7. I'm much more worried about harming the platform by putting in something that we later regret. If we can come to consensus and build something good in time for inclusion in Java 7, great. If not, so be it. Primum non nocere. > > About the crying. If you have three-four very serious proposals, developed > by really smart people, using hundreds of hours of work and you still > squeeze in a new Sun made proposal in between, what did you expect? > I was involved in one of those proposals, and I'm glad that it (and the other proposals) are not being adopted by Sun as the basis for this effort. Starting with a nearly blank slate and a target use-case seems like a prudent approach. Josh From grev at miginfocom.com Wed Dec 16 13:29:43 2009 From: grev at miginfocom.com (Mikael Grev) Date: Wed, 16 Dec 2009 22:29:43 +0100 Subject: Comments on the straw man... In-Reply-To: <17b2302a0912161320h7085ad05ge7b19723a12eb973@mail.gmail.com> References: <20091216194519.8D710560@eggemoggin.niobe.net> <1B6F5BBF-40EB-4B63-B0CD-2E20860CB00A@miginfocom.com> <17b2302a0912161320h7085ad05ge7b19723a12eb973@mail.gmail.com> Message-ID: <8B854195-E383-4160-85C9-155FD735ED7E@miginfocom.com> Josh, Starting over with a clean slate is always tempting, especially for the technically inclined. We'll do it better next time. I get that. I is seldom an economically sound thing to do though as the winnings is less than the cost in many cases. The work seems always easier than it is. I just think that the only thing you can get is a _different_ proposal, not necessary a better one. Well, at least I know the best are working on the new proposal and I wholeheartedly hope that I'm wrong about the risk and the project plan runs smoothly. Cheers, Mikael On Dec 16, 2009, at 22:20 PM, Joshua Bloch wrote: > Mikael, > > Hi. I have a different perspective on this. > > On Wed, Dec 16, 2009 at 1:06 PM, Mikael Grev wrote: > > if you are 100% confident that you can get unification around a new proposal, implement and test it in time for Java 7 then that's fine. I just find it pretty risky. > > I'm not worried about the risk of missing Java 7. I'm much more worried about harming the platform by putting in something that we later regret. If we can come to consensus and build something good in time for inclusion in Java 7, great. If not, so be it. Primum non nocere. > > > About the crying. If you have three-four very serious proposals, developed by really smart people, using hundreds of hours of work and you still squeeze in a new Sun made proposal in between, what did you expect? > > I was involved in one of those proposals, and I'm glad that it (and the other proposals) are not being adopted by Sun as the basis for this effort. Starting with a nearly blank slate and a target use-case seems like a prudent approach. > > Josh > From Thomas.Hawtin at Sun.COM Wed Dec 16 14:00:57 2009 From: Thomas.Hawtin at Sun.COM (Tom Hawtin) Date: Wed, 16 Dec 2009 22:00:57 +0000 Subject: Serialization In-Reply-To: <636fd28e0912161306h72104706scce3e7d4d4aeb52e@mail.gmail.com> References: <17b2302a0912152217mf1feac0ld5a9ed17cda82be1@mail.gmail.com> <200912161323.22403.peter.levart@marand.si> <4B28D368.5010106@optrak.co.uk> <200912161409.02274.peter.levart@marand.si> <17b2302a0912160746o49ca8dfx97427314e4c0bc3a@mail.gmail.com> <636fd28e0912161306h72104706scce3e7d4d4aeb52e@mail.gmail.com> Message-ID: <4B295899.8080308@sun.com> Alex Blewitt wrote: > I agree that not all lambdas should be serializable. Are we talking > 'static' as defined by the compiler, or by the developer in the > source? I'd argue that a good compiler should be able to promote (for > want of a better description) 'instance' closures to 'static' closures > automatically iff the appropriate conditions hold (no references to > this variables etc.). In that case, one would be able to use #int(int > a) { return a*42; } as a serializable lambda, regardless of whether it > was defined (in the source) as a static, instance, or stack-based > variable. Even without considering serialisation, I don't think we should be faithfully copying inner class' semantics of always taking the outer this. For small operations it's an absolute waste. Further, in light of the 1.5 JMM special treatment of final fields, I think we can drop the outer this if the lambda only uses final fields from outer instances. Yay for final. FWIW, RMI allows remote code loading from the opposite party, using support provided by the serialisation mechanism. It's the RMI party trick. The Java Tutorial example for RMI is a general purpose compute engine. I don't really have a problem from a compatability point of view with serialising lambdas if they are going to be deserialised with the *exact* same class files. However, from a security point of view automatically serialisable lambdas scares the hell out of me. Even function types where untrusted code comes into contact with more trusted code, I don't see working. We have enough trouble with the weak-typing interpretation of Runnable. "The general contract of the method run is that it may take any action whatsoever." This is essentially the contract of function types as well. Tom From neal at gafter.com Thu Dec 17 00:00:25 2009 From: neal at gafter.com (Neal Gafter) Date: Thu, 17 Dec 2009 00:00:25 -0800 Subject: Comments on the straw man... In-Reply-To: <17b2302a0912161320h7085ad05ge7b19723a12eb973@mail.gmail.com> References: <20091216194519.8D710560@eggemoggin.niobe.net> <1B6F5BBF-40EB-4B63-B0CD-2E20860CB00A@miginfocom.com> <17b2302a0912161320h7085ad05ge7b19723a12eb973@mail.gmail.com> Message-ID: <15e8b9d20912170000g662f71f2g398ecbd8e7a72a6b@mail.gmail.com> On Wed, Dec 16, 2009 at 1:20 PM, Joshua Bloch wrote: > Starting with a nearly blank slate and a target use-case seems like a > prudent approach. > It is, for API design. Not so much for language design. See < http://gafter.blogspot.com/2006/09/failure-of-imagination-in-language_17.html >. Cheers, Neal From howard.lovatt at iee.org Thu Dec 17 00:02:56 2009 From: howard.lovatt at iee.org (Howard Lovatt) Date: Thu, 17 Dec 2009 09:02:56 +0100 Subject: Method calls vs lambda calls In-Reply-To: <15e8b9d20912161138o2c2042f8u14b8983034b91b1@mail.gmail.com> References: <3dd3f56a0912160616p478ec54m88aad23e2c8a9c78@mail.gmail.com> <4B28F06F.1030402@the-loom.de> <15e8b9d20912160807l4132b88au2965410582b62f13@mail.gmail.com> <4B2930C2.5010309@the-loom.de> <15e8b9d20912161138o2c2042f8u14b8983034b91b1@mail.gmail.com> Message-ID: <3dd3f56a0912170002h15d7093bj555a48c8a705c4e@mail.gmail.com> Based on Neal's generic example, here is a particularly nasty case: class Base { T t; T t1; void t() { out.println( t ); } } class Derived extends Base<#int()> { { t = #int() (42); // Can't override t() because it has a different signature t1 = #int() (41); } void test() { out.println( t1 ); // Prints Function_intATXXX out.println( t1() ); // Would be nice if this printed 41 out.println( t ); // Prints Function_intATXXX out.println( t() ); // Error t() returns void } } I think this example leaves only three options: 1. The FCM solution of always using call(); i.e. in the example above, out.println( t.call() ) and out.println( t1.call() ). This solution is nice and simple. 2. You can only use t() to mean t.call() when there is no ambiguity; i.e. in the example above, out.println( t.call() ) but out.println( t1() ). People may well be confused by this since it is unlike the rest of Java in both the way t() with the meaning t.call() is 'overloaded' and with when t() is valid shorthand for t.call(). 3. Don't have function-types. This is the simplest solution and the best fit with current Java since it retains nominal typing and therefore by the KISS principle my favorite and importantly it does not preclude adding function types later. This is similar to 1 above if you define some interfaces, i.e. interface Callable0 { R call(); }, interface Callable1 { R call( A a); }, etc. Note 1 will still require the interfaces for the JVM, but the programmer wouldn't use them directly. Can anyone think of any other options? -- Howard. 2009/12/16 Neal Gafter : > On Wed, Dec 16, 2009 at 11:10 AM, Stefan Schulz wrote: >> >> Neal Gafter wrote: >>> >>> On Wed, Dec 16, 2009 at 6:36 AM, Stefan Schulz >> > wrote: >>> ? ?I didn't say anything about making a method. If the short-hand >>> ? ?invocation syntax is allowed, putting names of function-typed >>> variables >>> ? ?in the same (scope-relative) space like methods is a way to ensure not >>> ? ?to have methods and function-typed variables with the same name. >>> >>> I'm afraid it doesn't ensure that at all. ?Because methods may overload, >>> a given scope may have many definitions for a given name in the method >>> namespace. >> >> Too bad. Is there any possibility to hold the full signature of methods >> and function-typed variables in some way to being able to resolve these >> conflicts? Maybe an additional function space? Sorry, if this sounds a bit >> naive. > > I'm not sure what you're asking.? The mechanism for resolving these > conflicts today is (compile-time) overload resolution.? It would have to be > extended to handle the case of a mixture of methods and variables of > function type. > >>> >>> ? ?As this >>> ? ?has to hold for inheritance, too, I do not see a problem in >>> ? ?function-typed variables of subclasses to @Override those of a >>> ? ?superclass, as the information is already there. (Of course, they must >>> ? ?additionally hide normal variables having the same name.) >>> >>> >>> What semantics are you imagining for this overriding? ?What if the thing >>> being overridden is a method? >> >> I didn't mean to being able to override methods with function-typed >> variables, or vice versa (although this sounds interesting). >> >> So, what would be the conclusion? >> * If any method m exists in a class's hierarchy, one cannot define a >> function-typed field m? >> * If a function-typed field m exists in a class's hierarchy, one cannot >> define a method named m? >> * If a function-typed field m exists in a class's hierarchy, will a field >> named m (of any type?) in a subclass hide the function-typed field m? >> * If a non-function-typed field m hides a superclass's function-typed >> field m, would it be possible to define a method named m in that very >> subclass? > > Good questions, and there are many more.? Function-typed variables can be > declared as local variables and parameters too.? They can also have a type > of a generic parameter in a superclass but be inherited into a subclass as a > function type: > > class Base { T t; int t(int x) { return x; } } > class Derived: Base<#int(int)> {} > > if Derived.t in the function namespace? > > A complete specification must provide clear answers to all these questions. > > Cheers, > Neal > > ______________________________________________________________________ > This email has been scanned by the MessageLabs Email Security System. > For more information please visit http://www.messagelabs.com/email > ______________________________________________________________________ > -- -- Howard. From neal at gafter.com Thu Dec 17 00:09:02 2009 From: neal at gafter.com (Neal Gafter) Date: Thu, 17 Dec 2009 00:09:02 -0800 Subject: Method calls vs lambda calls In-Reply-To: <3dd3f56a0912170002h15d7093bj555a48c8a705c4e@mail.gmail.com> References: <3dd3f56a0912160616p478ec54m88aad23e2c8a9c78@mail.gmail.com> <4B28F06F.1030402@the-loom.de> <15e8b9d20912160807l4132b88au2965410582b62f13@mail.gmail.com> <4B2930C2.5010309@the-loom.de> <15e8b9d20912161138o2c2042f8u14b8983034b91b1@mail.gmail.com> <3dd3f56a0912170002h15d7093bj555a48c8a705c4e@mail.gmail.com> Message-ID: <15e8b9d20912170009v4cdc701bm183511ebb29fa50e@mail.gmail.com> On Thu, Dec 17, 2009 at 12:02 AM, Howard Lovatt wrote: > Based on Neal's generic example, here is a particularly nasty case: > > class Base { > T t; > T t1; > void t() { out.println( t ); } > } > > class Derived extends Base<#int()> { > { > t = #int() (42); // Can't override t() because it has a different > signature > t1 = #int() (41); > } > void test() { > out.println( t1 ); // Prints Function_intATXXX > out.println( t1() ); // Would be nice if this printed 41 > out.println( t ); // Prints Function_intATXXX > out.println( t() ); // Error t() returns void > } > } > ... > Can anyone think of any other options? > Yes: a variable is added to the method namespace only when declared with a function type. In this example, t and t1 are not declared with a function type, but rather are declared with the type of a type parameter (T). Therefore shorthand invocation is not available for them. This is a nice solution because it prevents names being inherited into a namespace in which they did not previously appear. Cheers, Neal From schulz at the-loom.de Thu Dec 17 00:32:07 2009 From: schulz at the-loom.de (Stefan Schulz) Date: Thu, 17 Dec 2009 09:32:07 +0100 Subject: More questions / function type hierarchy (was: Re: Method calls vs lambda calls) In-Reply-To: <15e8b9d20912170009v4cdc701bm183511ebb29fa50e@mail.gmail.com> References: <3dd3f56a0912160616p478ec54m88aad23e2c8a9c78@mail.gmail.com> <4B28F06F.1030402@the-loom.de> <15e8b9d20912160807l4132b88au2965410582b62f13@mail.gmail.com> <4B2930C2.5010309@the-loom.de> <15e8b9d20912161138o2c2042f8u14b8983034b91b1@mail.gmail.com> <3dd3f56a0912170002h15d7093bj555a48c8a705c4e@mail.gmail.com> <15e8b9d20912170009v4cdc701bm183511ebb29fa50e@mail.gmail.com> Message-ID: <4B29EC87.2090400@the-loom.de> Neal Gafter wrote: > Yes: a variable is added to the method namespace only when declared with > a function type. In this example, t and t1 are not declared with a > function type, but rather are declared with the type of a type parameter > (T). Therefore shorthand invocation is not available for them. > > This is a nice solution because it prevents names being inherited into a > namespace in which they did not previously appear. Allowing function types for generic parameters and the above issue raises some questions in my eyes (maybe not to be answered right now, but to be put on a lambda-questionaire): * would something like be allowed? * if the above, what types will fulfill T? * would it make sense to have some notation or supertype denoting a generic parameter to be of any function type (e.g. )? IMHO, similar questions arise for method overriding and co-variance of return types. Cheers, Stefan From howard.lovatt at iee.org Thu Dec 17 01:22:02 2009 From: howard.lovatt at iee.org (Howard Lovatt) Date: Thu, 17 Dec 2009 10:22:02 +0100 Subject: Method calls vs lambda calls In-Reply-To: <15e8b9d20912170009v4cdc701bm183511ebb29fa50e@mail.gmail.com> References: <3dd3f56a0912160616p478ec54m88aad23e2c8a9c78@mail.gmail.com> <4B28F06F.1030402@the-loom.de> <15e8b9d20912160807l4132b88au2965410582b62f13@mail.gmail.com> <4B2930C2.5010309@the-loom.de> <15e8b9d20912161138o2c2042f8u14b8983034b91b1@mail.gmail.com> <3dd3f56a0912170002h15d7093bj555a48c8a705c4e@mail.gmail.com> <15e8b9d20912170009v4cdc701bm183511ebb29fa50e@mail.gmail.com> Message-ID: <3dd3f56a0912170122m17315735p6464754bb824dc8@mail.gmail.com> Yes that is a forth option; but it is confusing because people expect generic types to behave like concrete types (that's the point of generics). Anomalous behavior of generics, e.g. interaction with arrays, is already a problem and this option will only increase the problems. For example the following would work with the option I listed as 2, but not with this fourth option: class Base { T t; } class Reasonable extends Base> { { t = new ArrayList(); } void reasonable() { t.add( 1 ); } } class Unreasonable extends Base<#int()> { { t = #int() (42); } void unreasonable() { out.println( t(); } // Error, T is not behaving as a #int() } If in reasonable() I can treat T as a List, why in unreasonable() can't I treat T as a #int()? (Ok in some circumstances I can treat T as a #int(), but not in all.) -- Howard. 2009/12/17 Neal Gafter : > On Thu, Dec 17, 2009 at 12:02 AM, Howard Lovatt > wrote: >> >> Based on Neal's generic example, here is a particularly nasty case: >> >> class Base { >> ?T t; >> ?T t1; >> ?void t() { out.println( t ); } >> } >> >> class Derived extends Base<#int()> { >> ?{ >> ? ?t = #int() (42); // Can't override t() because it has a different >> signature >> ? ?t1 = #int() (41); >> ?} >> ?void test() { >> ? ?out.println( t1 ); // Prints Function_intATXXX >> ? ?out.println( t1() ); // Would be nice if this printed 41 >> ? ?out.println( t ); // Prints Function_intATXXX >> ? ?out.println( t() ); // Error t() returns void >> ?} >> } >> ... >> Can anyone think of any other options? > > Yes: a variable is added to the method namespace only when declared with a > function type.? In this example, t and t1 are not declared with a function > type, but rather are declared with the type of a type parameter (T). > Therefore shorthand invocation is not available for them. > > This is a nice solution because it prevents names being inherited into a > namespace in which they did not previously appear. > > Cheers, > Neal > > ______________________________________________________________________ > This email has been scanned by the MessageLabs Email Security System. > For more information please visit http://www.messagelabs.com/email > ______________________________________________________________________ From peter.levart at marand.si Thu Dec 17 03:13:40 2009 From: peter.levart at marand.si (Peter Levart) Date: Thu, 17 Dec 2009 12:13:40 +0100 Subject: Serialization Message-ID: <200912171213.40802.peter.levart@marand.si> On Wednesday 16 December 2009 17:51:24 you wrote: > > I wouldn't prevent serializability of non-static closures though. If one > > should be worried about that, the compiler could issue a special warning > > that is opt-in type (accompanied with annotation for the same purpose). > > > I'm not sure where the compiler would issue the warning: serialization is > not a language feature; it's accomplished by invoking a method. The > compiler may have no indication that the object being serialized is of a > function type. I agree that it's inconsistent with our current approach to > serialization (where we do let people serialize instances of non-static > nested classes), but it's usually a mistake when people do it. > I was thinking about a warning like: "Lambda expression references outer instance. Serializing lambda expression will serialize outer instance." Just that. If one is building a distributed execution system (like Google's map-reduce) he wants to be sure he's codebase contains static-only closures so that the serialization footprint is within the resonable bounds. He might then enable this warning to check the code. Peter From alex.blewitt at gmail.com Thu Dec 17 04:24:20 2009 From: alex.blewitt at gmail.com (Alex Blewitt) Date: Thu, 17 Dec 2009 12:24:20 +0000 Subject: Terminology Message-ID: <636fd28e0912170424l687d0c7bm5a11b02c5feab4ff@mail.gmail.com> We've been debating various levels of lambdas, and using modifiers like 'static' and 'instance' without necessarily agreeing on what we are implying by those terms. In addition, the definition of the location (whether it is inside or outside a method, or even whether it is inside or outside another lambda) is lacking clear terminology. So, here are some cases: Location A. public class A { private ... a = #() {...}; } Location B. public class B { public void b() { ... a = #() {...}; } } Location C. public class C { public void c() { ... = #() {... c = #() {...} }; } } Capturing: Capture D. ... d = #int() { 42 }; // Captures nothing i.e. a 'pure' lambda, not a closure Capture E. public class Ea { public void eb() { int x = 42; ... e = #int() { x *2 }; // captures local variable in stack scope } } Capture F. public class Fa { private int x = 42; public void fb() { ... f = #int() { x*2 }; // captures implicit 'this.x' reference } } Capture G. public class Ga { private static int x = 42; public void gb() { ... g = #int() { x*2 }; // captures implicit 'class.x' static reference } } Capture H. public class Ha { public void hb() { ... = #int() { int x = 42; ... g = #int() { x*2} }; // capturing stack scope from within another lambda } } It would be good if we had some kind of wiki to record these, and/or make them publicly available, and determine what we're going to call each one. Furthermore, we've been using terms like 'static' - the strawman distinguishes between accessing static members and non-static members (determined by whether the fields are visible or not). Whilst I think it useful to be able to declaratively restrict the scope of certain lambdas, the compiler should be able to promote lambdas to restricted or static scope automatically based on whether or not any fields are accessed or not. For example, Capture F above accesses an instance field of the current class. However, consider: public class F2 { public void f2a() { ... f2 = #int() { 42 }; } } in this case, the method (f2a) is still an instance method, but the lambda f2 does not capture any instance-specific scope. So it could be promoted to be a constant or shared lambda; in fact, one could argue that the instantiation of that lambda (assuming it's translated to an inner class, then, it would be a static inner class) would be a static final. So it might transform to: public class F2 { private /* ACC_SYNTH etc */ static class f2 { protected int f2() { return 42 }; } private static final f2 = new f2(); public void f2a() { ... f2.f2() } } The point of observing this optimisation is to be able to define what conditions this might hold, rather than purely the call-site. Clearly a lambda defined in a static method should only be able to see static fields; however, a lambda defined in an instance method doesn't have to see instance fields of the enclosing class. We might have keywords to provide enforced stricter visibility, but the compiler should be intelligent enough to auto-demote where necessary. Alex From scolebourne at joda.org Thu Dec 17 04:51:14 2009 From: scolebourne at joda.org (Stephen Colebourne) Date: Thu, 17 Dec 2009 12:51:14 +0000 Subject: Comments on the straw man... In-Reply-To: <20091216194519.8D710560@eggemoggin.niobe.net> References: <15e8b9d20912111117i3850004dne0b391c5669e216a@mail.gmail.com> <20091216194519.8D710560@eggemoggin.niobe.net> Message-ID: <4b4f45e00912170451o4f89f148y3cdadcf03cb790ac@mail.gmail.com> 2009/12/16 Mark Reinhold : > I committed > publicly to initiate an open discussion, and publishing the straw-man > proposal seemed the best way to do that. > I could, alternatively, have waited and posted a more-complete proposal, Personally, I would have preferred to see a statement of requirements - "lambda-blocks will have local returns", "this keyword will be lexically scoped", "function types are required", "short syntax", "method references are desirable". Instead, we are effectively extracting requirements from the straw-man. Mark, would you consider writing up a document at more of a requirements level? > I could have chosen one of the existing > proposals as a starting point but that would've been seen, rightly, as > heavy-handed. Neither of these alternatives would have been a good way > to begin an effort to build consensus around the ultimate design. I'd note that we should not see CFJ 0.6a as one of the original proposals. It may come from the same author, but the differences are significant enough to what went before to make it effectively a new proposal. > It may well be that one of the existing proposals is a good starting > point, but I'd like to see some discussion of that topic before making > such a decision. As I've indicated, the requirements in the straw-man appear to match CFJ 0.6a but perhaps there is a requirement we're not seeing? Stephen From forax at univ-mlv.fr Thu Dec 17 06:23:55 2009 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Thu, 17 Dec 2009 15:23:55 +0100 Subject: Lambda and JSR 292 method handle Message-ID: <4B2A3EFB.5030406@univ-mlv.fr> I've seen lot of comments about relation between JSR 292 method handle and lambdas, and I think it's time to make some clarifications. In my opinion, there is two runtime models to implement lambda in Java : The former is the 'class model', function types are interfaces and lambdas are classes. The later is the 'function model', function types are translated to one class java.dyn.MethodHandle and lambdas are instance of that class. A method handle is a decorated safe function pointer that is why you don't need different subtypes to represent all lambdas. The class model creates one class by lambda and one interface by function type. To reduce the number of generated interfaces and ease subtyping between function types, BGGA proposes to use generics and wildcard. This model are severals weak points: 1) VMs are built to manage lot of instance of few classes, this model creates lot of classes with few instances. So this model doesn't fit very well with current VM implementations. You can already observe this effect in JRuby, current implementation creates lot of small class that acts as lambda and thus requires by example a big perm gen [1] 2) method that takes a function type (here an interface) creates megamorphic call sites and the VM is not able to inline it if the method is called by different method (see [3] and [4]). foreach(Collection c, #void(T) fun) { for(T t:c) fun(t); // megamorphic ! } 3) Who is in charge of creating interfaces representing function types ? Currently the BGGA compiler creates these interfaces when needed at compile time. This solution is not feasible if you have jars or modules, it generates double definitions and conflicts. I haven't seen any serious proposal to resolve that problem. 4) because function types are generic types, this model has the limitation of generics, no reification (cast unsafe, instanceof illegal, etc) The function model creates one function by lambda. class A { public static void main(String[] args) { #int(int) f = #(int x) (x+x); f(2); } } is translated to: class A { public static void main(String[] args) { ldc static lambda$1(int)int // (1) astore 1 // (2) aload 1 aconst_2 invokevirtual A.invokeLambda(int)int // (3) pop } private static int lambda$1(int x) { return x+x; } } I've written the body of the main in bytecode because there is non equivalent in Java. First, the JSR 292 define a new constant pool constant (see [2]) that allow to reference a function (here a static method) using opcode ldc. So instantiating a lambda is just a ldc (1). At runtime, this object is a java.dyn.MethodHandle, so it can be stored as an object (2). To call the lambda, the VM allows to call a magic method (3) named invokeLambda (name may changed). At runtime, the VM checks that the method handle type is compatible with the type of invokeLambda and call the function pointer stored in the method handle. Because a method handle knows its runtime type, it's possible to implement instanceof and cast on a function type. Function type that are parametrized have the same constraint that parameterized type, i.e cast are unsafe. If function type are translated to method handle, megamorphic call site problem can be solved because JIT can recognize the pattern (a method that takes a method handle) and do an aggressive inlining of such method. In summary, JSR 292 method handles was introduced by JSR 292 expert group because it solves common problems encounters when dealing with function pointer encoded using interfaces. It will be stupid to don't eating our own dog food. R?mi [1] http://java.net/blog/eileeny/archive/2009/12/10/jruby-performance-glassfish-v3-part-1 [2] http://wiki.jvmlangsummit.com/DinnerAtPiatti (look for Constant Pool Constants) [3] http://thread.gmane.org/gmane.comp.lang.scala.internals/865 [4] http://blog.juma.me.uk/2009/10/26/new-jvm-options-and-scala-iteration-performance/ From mthornton at optrak.co.uk Thu Dec 17 06:18:21 2009 From: mthornton at optrak.co.uk (Mark Thornton) Date: Thu, 17 Dec 2009 14:18:21 +0000 Subject: Lambda and JSR 292 method handle In-Reply-To: <4B2A3EFB.5030406@univ-mlv.fr> References: <4B2A3EFB.5030406@univ-mlv.fr> Message-ID: <4B2A3DAD.70202@optrak.co.uk> R?mi Forax wrote: > This model are severals weak points: > 1) VMs are built to manage lot of instance of few classes, this model > creates lot of classes > with few instances. So this model doesn't fit very well with > current VM implementations. > There was a proposal to update the class file format to better (and more compactly) represent nested/inner classes. This might be expected to improve the ability of VM's to manage large numbers of such classes. Mark Thornton From forax at univ-mlv.fr Thu Dec 17 06:22:58 2009 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Thu, 17 Dec 2009 15:22:58 +0100 Subject: Lambda and JSR 292 method handle In-Reply-To: <4B2A3DAD.70202@optrak.co.uk> References: <4B2A3EFB.5030406@univ-mlv.fr> <4B2A3DAD.70202@optrak.co.uk> Message-ID: <4B2A3EC2.5030203@univ-mlv.fr> Le 17/12/2009 15:18, Mark Thornton a ?crit : > R?mi Forax wrote: >> This model are severals weak points: >> 1) VMs are built to manage lot of instance of few classes, this model >> creates lot of classes >> with few instances. So this model doesn't fit very well with >> current VM implementations. > There was a proposal to update the class file format to better (and > more compactly) represent nested/inner classes. This might be expected > to improve the ability of VM's to manage large numbers of such classes. The problem is not only loading time or external class format but also : - the size of the metadata associated with each class (java.lang.Class) at runtime. - some JIT optimisations that work better is the number of classes in a hierachy is small (instanceof/cast test or CHA by example). > > Mark Thornton > R?mi From alex.blewitt at gmail.com Thu Dec 17 06:37:21 2009 From: alex.blewitt at gmail.com (Alex Blewitt) Date: Thu, 17 Dec 2009 14:37:21 +0000 Subject: Comments on the straw man... In-Reply-To: <4b4f45e00912170451o4f89f148y3cdadcf03cb790ac@mail.gmail.com> References: <15e8b9d20912111117i3850004dne0b391c5669e216a@mail.gmail.com> <20091216194519.8D710560@eggemoggin.niobe.net> <4b4f45e00912170451o4f89f148y3cdadcf03cb790ac@mail.gmail.com> Message-ID: On Dec 17, 2009, at 12:51, Stephen Colebourne wrote: > 2009/12/16 Mark Reinhold : >> I committed >> publicly to initiate an open discussion, and publishing the straw-man >> proposal seemed the best way to do that. >> I could, alternatively, have waited and posted a more-complete >> proposal, > > Personally, I would have preferred to see a statement of requirements > - "lambda-blocks will have local returns", "this keyword will be > lexically scoped", "function types are required", "short syntax", > "method references are desirable". Instead, we are effectively > extracting requirements from the straw-man. Agreed - a list of requirements would enable us to better target what the resultant structure is. Furthermore, it will then allow us to all agree on what the mandatory requirements are (i.e. those which if the project doesn't deliver, it has failed), what the highly desirable ones are (like automatic SAM conversion), right down to the wouldn't- it-be-good-if requirements (like extension methods, exception support). I think our discussions are touching on some of these points, but we should really consider ordering them relative to each other and then start with a solution that meets all the mandatory ones and then build up from there. Alex From opinali at gmail.com Thu Dec 17 06:37:31 2009 From: opinali at gmail.com (Osvaldo Doederlein) Date: Thu, 17 Dec 2009 12:37:31 -0200 Subject: Lambda and JSR 292 method handle In-Reply-To: <4B2A3EFB.5030406@univ-mlv.fr> References: <4B2A3EFB.5030406@univ-mlv.fr> Message-ID: When I complained about the "weight" and "bloat" of lambdas, I didn't remember the issue of megamorphic callsites. Aggressive inlining would be the only general exit for the problem. But then, it's much better to not have this problems in the first place. The code size / permgen is the less evil, as I don't see Java apps using enough closures to have a problem in the scale of JRuby. Java already has (IMHO) too much reliance on JIT compilation. I've long complained about other issues like the classfile's constant pool failure to efficiently encode arrays and objects with constructors simple enough for compile-time evaluation (ex.: new Point2D(0,0)) - requiring bulky static initializers, which are of course executed in interpreted mode. (I hope Jigsaw's new packaging format will address this?) The result is the loading times that we all know and hate (and that Sun is now pouring tremendous effort to reduce, for the good of a client-side renaissance). Anyway, my (non-expert) view of MethodHandles is that they are intrinsically more efficient than the current alternatives, even before an advanced JIT (that we DON'T have in the Client VM...) kicks in and performs all necessary incantations. Neal said that a design/impl of lambdas over MethodHandles is difficult and any such effort should start right now - that's bad news because we don't even have a firm language design yet. I suppose that in the worse case, we could change the implementation to benefit from MethodHandles later down the road, in some JDK 7 Update XX. As long as the new implementation won't have any observable effect in the typesystem; I fear your item 4 implies the opposite? A+ Osvaldo 2009/12/17 R?mi Forax > I've seen lot of comments about relation between JSR 292 method handle > and lambdas, > and I think it's time to make some clarifications. > > In my opinion, there is two runtime models to implement lambda in Java : > The former is the 'class model', function types are interfaces and > lambdas are classes. > The later is the 'function model', function types are translated to one > class > java.dyn.MethodHandle and lambdas are instance of that class. > A method handle is a decorated safe function pointer that is why you > don't need > different subtypes to represent all lambdas. > > The class model creates one class by lambda and one interface by > function type. > To reduce the number of generated interfaces and ease subtyping between > function types, > BGGA proposes to use generics and wildcard. > > This model are severals weak points: > 1) VMs are built to manage lot of instance of few classes, this model > creates lot of classes > with few instances. So this model doesn't fit very well with > current VM implementations. > You can already observe this effect in JRuby, current > implementation creates > lot of small class that acts as lambda and thus requires by example > a big perm gen [1] > > > 2) method that takes a function type (here an interface) creates > megamorphic call sites > and the VM is not able to inline it if the method is called by > different method > (see [3] and [4]). > > foreach(Collection c, #void(T) fun) { > for(T t:c) > fun(t); // megamorphic ! > } > > > 3) Who is in charge of creating interfaces representing function types ? > Currently the BGGA compiler creates these interfaces when needed at > compile time. > This solution is not feasible if you have jars or modules, > it generates double definitions and conflicts. > I haven't seen any serious proposal to resolve that problem. > > > 4) because function types are generic types, this model has the > limitation of generics, > no reification (cast unsafe, instanceof illegal, etc) > > > The function model creates one function by lambda. > > class A { > public static void main(String[] args) { > #int(int) f = #(int x) (x+x); > f(2); > } > } > > is translated to: > > class A { > public static void main(String[] args) { > ldc static lambda$1(int)int // (1) > astore 1 // (2) > aload 1 > aconst_2 > invokevirtual A.invokeLambda(int)int // (3) > pop > } > > private static int lambda$1(int x) { > return x+x; > } > } > > I've written the body of the main in bytecode because there is non > equivalent in Java. > First, the JSR 292 define a new constant pool constant (see [2]) > that allow to reference a function (here a static method) using opcode ldc. > So instantiating a lambda is just a ldc (1). > At runtime, this object is a java.dyn.MethodHandle, so it can be stored > as an object (2). > To call the lambda, the VM allows to call a magic method (3) named > invokeLambda (name may changed). > At runtime, the VM checks that the method handle type is compatible with > the type of invokeLambda > and call the function pointer stored in the method handle. > > Because a method handle knows its runtime type, it's possible to > implement instanceof and > cast on a function type. > Function type that are parametrized have the same constraint that > parameterized type, i.e > cast are unsafe. > > If function type are translated to method handle, megamorphic call site > problem can be solved because > JIT can recognize the pattern (a method that takes a method handle) and > do an aggressive inlining of > such method. > > > In summary, JSR 292 method handles was introduced by JSR 292 expert > group because it solves > common problems encounters when dealing with function pointer encoded > using interfaces. > It will be stupid to don't eating our own dog food. > > R?mi > > > [1] > > http://java.net/blog/eileeny/archive/2009/12/10/jruby-performance-glassfish-v3-part-1 > [2] http://wiki.jvmlangsummit.com/DinnerAtPiatti (look for Constant Pool > Constants) > [3] http://thread.gmane.org/gmane.comp.lang.scala.internals/865 > [4] > > http://blog.juma.me.uk/2009/10/26/new-jvm-options-and-scala-iteration-performance/ > > From forax at univ-mlv.fr Thu Dec 17 06:58:09 2009 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Thu, 17 Dec 2009 15:58:09 +0100 Subject: Lambda and JSR 292 method handle In-Reply-To: References: <4B2A3EFB.5030406@univ-mlv.fr> Message-ID: <4B2A4701.5090300@univ-mlv.fr> Le 17/12/2009 15:37, Osvaldo Doederlein a ?crit : > When I complained about the "weight" and "bloat" of lambdas, I didn't > remember the issue of megamorphic callsites. Aggressive inlining would > be the only general exit for the problem. But then, it's much better > to not have this problems in the first place. The code size / permgen > is the less evil, as I don't see Java apps using enough closures to > have a problem in the scale of JRuby. > > Java already has (IMHO) too much reliance on JIT compilation. I've > long complained about other issues like the classfile's constant pool > failure to efficiently encode arrays and objects with constructors > simple enough for compile-time evaluation (ex.: new Point2D(0,0)) - > requiring bulky static initializers, which are of course executed in > interpreted mode. (I hope Jigsaw's new packaging format will address > this?) The result is the loading times that we all know and hate (and > that Sun is now pouring tremendous effort to reduce, for the good of a > client-side renaissance). Anyway, my (non-expert) view of > MethodHandles is that they are intrinsically more efficient than the > current alternatives, even before an advanced JIT (that we DON'T have > in the Client VM...) kicks in and performs all necessary incantations. I remember Terrence Parr saying something similar about array and 65535 bytecode size limit at last JVM Summit. > > Neal said that a design/impl of lambdas over MethodHandles is > difficult and any such effort should start right now - that's bad news > because we don't even have a firm language design yet. I suppose that > in the worse case, we could change the implementation to benefit from > MethodHandles later down the road, in some JDK 7 Update XX. As long as > the new implementation won't have any observable effect in the > typesystem; I fear your item 4 implies the opposite? Neal forget than method handle is one of the core feature of JSR 292 so all teams that develop a dynamic language on top of the VM (at least JRuby, Jython aznd Groovy) already have someone that have implemented a prototype of its favorite language using method handle. This is not like starting from stratch. But I agree with him that we need a specification and exorcise the devil (from the details :) I don't belive changing the implementation after is possible, you can prevent someone to use getClass(). > > A+ > Osvaldo R?mi From peter.levart at marand.si Thu Dec 17 07:03:04 2009 From: peter.levart at marand.si (Peter Levart) Date: Thu, 17 Dec 2009 16:03:04 +0100 Subject: Terminology In-Reply-To: <636fd28e0912170424l687d0c7bm5a11b02c5feab4ff@mail.gmail.com> References: <636fd28e0912170424l687d0c7bm5a11b02c5feab4ff@mail.gmail.com> Message-ID: <200912171603.04175.peter.levart@marand.si> On Thursday 17 December 2009 13:24:20 Alex Blewitt wrote: > For example, Capture F above accesses an instance field of the current > class. However, consider: > > public class F2 { > public void f2a() { > ... f2 = #int() { 42 }; > } > } > > in this case, the method (f2a) is still an instance method, but the lambda > f2 does not capture any instance-specific scope. > So it could be promoted to > be a constant or shared lambda; in fact, one could argue that the > instantiation of that lambda (assuming it's translated to an inner class, > then, it would be a static inner class) would be a static final. So it might > transform to: > > public class F2 { > private /* ACC_SYNTH etc */ static class f2 { > protected int f2() { return 42 }; > } > private static final f2 = new f2(); > public void f2a() { > ... f2.f2() > } > } I would even go further in this case and create the following equivalent code: public class F2 { private static class $GeneratedAnonymousName$ implements java.lang.function.FI, java.io.Serializable { private static final java.lang.function.FI INSTANCE = new $GeneratedAnonymousName$(); public int invoke() { return 42; } Object readResolve() { return INSTANCE; } } public void f2a() { ... f2 = F2.$GeneratedAnonymousName$.INSTANCE; } } The holder of the closure singleton should be the generated closure class itself. This way deserialization can return the singleton instance without loading and initializing the defining class (F2 in this case). Peter From alex.blewitt at gmail.com Thu Dec 17 07:08:58 2009 From: alex.blewitt at gmail.com (Alex Blewitt) Date: Thu, 17 Dec 2009 15:08:58 +0000 Subject: Terminology In-Reply-To: <200912171603.04175.peter.levart@marand.si> References: <636fd28e0912170424l687d0c7bm5a11b02c5feab4ff@mail.gmail.com> <200912171603.04175.peter.levart@marand.si> Message-ID: On Dec 17, 2009, at 15:03, Peter Levart wrote: > On Thursday 17 December 2009 13:24:20 Alex Blewitt wrote: >> For example, Capture F above accesses an instance field of the >> current >> class. However, consider: > > I would even go further in this case and create the following > equivalent code: The point was to try and identify the terminology used, so we could discuss the implementation detail later. For those that were serializable, having a readResolve would make sense though. > The holder of the closure singleton should be the generated closure > class itself. This way deserialization can return the singleton > instance without loading and initializing the defining class (F2 in > this case). An important thing to note is that it is not, in fact, a closure. It's a lambda. Some lambdas are closures, and some closures are lambdas, but all lambdas are not closures and all closures are not lambdas. This is one of the reasons to try and nail down terminology :-) Alex From peter.levart at marand.si Thu Dec 17 07:43:49 2009 From: peter.levart at marand.si (Peter Levart) Date: Thu, 17 Dec 2009 16:43:49 +0100 Subject: Lambda and JSR 292 method handle In-Reply-To: <4B2A3EFB.5030406@univ-mlv.fr> References: <4B2A3EFB.5030406@univ-mlv.fr> Message-ID: <200912171643.49575.peter.levart@marand.si> I haven read the JSR 292 spec, so please bear with me if I talk rubbish... Ok, so in your example, the lambda was a function, so the MethodHandle is refering to a static method. In case the lambda was a closure that just referenced instance fields/methods, the MethodHandle I presume could be refering to an instance method of that instance. But what about the case where lambda was a closure closing over some local variables. I expect you would have to create a special class and instance holding all this state and refer from MethodHandle to the instance method of that class. Still this would eleminate megamorphic call sites because no interfaces would be involved and the generated class/method could be final to enable JIT inlining. Peter On Thursday 17 December 2009 15:23:55 R?mi Forax wrote: > The function model creates one function by lambda. > > class A { > public static void main(String[] args) { > #int(int) f = #(int x) (x+x); > f(2); > } > } > > is translated to: > > class A { > public static void main(String[] args) { > ldc static lambda$1(int)int // (1) > astore 1 // (2) > aload 1 > aconst_2 > invokevirtual A.invokeLambda(int)int // (3) > pop > } > > private static int lambda$1(int x) { > return x+x; > } > } > > I've written the body of the main in bytecode because there is non > equivalent in Java. > First, the JSR 292 define a new constant pool constant (see [2]) > that allow to reference a function (here a static method) using opcode ldc. > So instantiating a lambda is just a ldc (1). > At runtime, this object is a java.dyn.MethodHandle, so it can be stored > as an object (2). > To call the lambda, the VM allows to call a magic method (3) named > invokeLambda (name may changed). > At runtime, the VM checks that the method handle type is compatible with > the type of invokeLambda > and call the function pointer stored in the method handle. > > Because a method handle knows its runtime type, it's possible to > implement instanceof and > cast on a function type. > Function type that are parametrized have the same constraint that > parameterized type, i.e > cast are unsafe. > > If function type are translated to method handle, megamorphic call site > problem can be solved because > JIT can recognize the pattern (a method that takes a method handle) and > do an aggressive inlining of > such method. > > > In summary, JSR 292 method handles was introduced by JSR 292 expert > group because it solves > common problems encounters when dealing with function pointer encoded > using interfaces. > It will be stupid to don't eating our own dog food. > > R?mi > From opinali at gmail.com Thu Dec 17 08:00:30 2009 From: opinali at gmail.com (Osvaldo Doederlein) Date: Thu, 17 Dec 2009 14:00:30 -0200 Subject: Lambda and JSR 292 method handle In-Reply-To: <4B2A4701.5090300@univ-mlv.fr> References: <4B2A3EFB.5030406@univ-mlv.fr> <4B2A4701.5090300@univ-mlv.fr> Message-ID: 2009/12/17 R?mi Forax > Le 17/12/2009 15:37, Osvaldo Doederlein a ?crit : > > When I complained about the "weight" and "bloat" of lambdas, I didn't >> remember the issue of megamorphic callsites. Aggressive inlining would be >> the only general exit for the problem. But then, it's much better to not >> have this problems in the first place. The code size / permgen is the less >> evil, as I don't see Java apps using enough closures to have a problem in >> the scale of JRuby. >> >> Java already has (IMHO) too much reliance on JIT compilation. I've long >> complained about other issues like the classfile's constant pool failure to >> efficiently encode arrays and objects with constructors simple enough for >> compile-time evaluation (ex.: new Point2D(0,0)) - requiring bulky static >> initializers, which are of course executed in interpreted mode. (I hope >> Jigsaw's new packaging format will address this?) The result is the loading >> times that we all know and hate (and that Sun is now pouring tremendous >> effort to reduce, for the good of a client-side renaissance). Anyway, my >> (non-expert) view of MethodHandles is that they are intrinsically more >> efficient than the current alternatives, even before an advanced JIT (that >> we DON'T have in the Client VM...) kicks in and performs all necessary >> incantations. >> > > I remember Terrence Parr saying something similar about array and 65535 > bytecode size limit > at last JVM Summit. Terrence described some tricks, like encoding numeric data in Strings because these can go in the constant pool. And I suppose that core libraries can do even more evil things with access to Unsafe. But I'm wishing for solutions, not hacks :) I don't belive changing the implementation after is possible, > you can prevent someone to use getClass(). > [can = can't?] This is not a problem (IMHO) if we make it clear which things are part of the language and which are implementation detail. See this bug I describe here: http://www.javalobby.org/java/forums/m92074023.html#92072670 The developer can always shoot himself in the foot by relying on undocumented implementation detail. For closures, as I suggested before we could make a best-effort to forbid bad things statically; for one thing we can emit warnings of potential portability issues for any reflection over closures. Of course, it's much better if we can at least decide on the important typing/linking/RRBC issues to use MethodHandle, even if, due to the short time, we have a initial implementation that's sub-optimal with method handling wrapping over bulky classes - if the latter are opaque, then that's something that can be optimized incrementally in maintenance releases. A+ Osvaldo From forax at univ-mlv.fr Thu Dec 17 08:03:46 2009 From: forax at univ-mlv.fr (=?UTF-8?B?UsOpbWkgRm9yYXg=?=) Date: Thu, 17 Dec 2009 17:03:46 +0100 Subject: Lambda and JSR 292 method handle In-Reply-To: <200912171643.49575.peter.levart@marand.si> References: <4B2A3EFB.5030406@univ-mlv.fr> <200912171643.49575.peter.levart@marand.si> Message-ID: <4B2A5662.5050105@univ-mlv.fr> Le 17/12/2009 16:43, Peter Levart a ?crit : > I haven read the JSR 292 spec, so please bear with me if I talk rubbish... > > Ok, so in your example, the lambda was a function, so the MethodHandle is refering to a static method. > > In case the lambda was a closure that just referenced instance fields/methods, the MethodHandle I presume could be refering to an instance method of that instance. > yes, you have a ldc virtual lambda$1(int)int. > But what about the case where lambda was a closure closing over some local variables. I expect you would have to create a special class and instance holding all this state and refer from MethodHandle to the instance method of that class. You don't need a class. There is a special operation named insertArguments that allow to specify the first arguments of a method handle in order to create another method handle. This operation is commonly called currying. http://download.java.net/jdk7/docs/api/java/dyn/MethodHandles.html#insertArgument%28java.dyn.MethodHandle,%20int,%20java.lang.Object%29 Let's take an example: class A { public static void main(String[] args) { #int(void) f = #() ( args.length ); f(); } } is translated to: class A { public static void main(String[] args) { ldc static lambda$1(String)int iconst_0 anewarray java/lang/Object dup iconst_0 aload 0 // load args invokestatic MethodHandles.insertArguments(java/dyn/MethodHandle,Object[])java/dyn/MethodHandle astore 1 aload 1 aconst_2 invokevirtual MethodHandle.invokeLambda() pop } private static int lambda$1(String[] args) { return args.length; } } the method lambda$1 takes a String[] as parameter and in the main, args is inserted as first argument. R?mi > Still this would eleminate megamorphic call sites because no interfaces would be involved and the generated class/method could be final to enable JIT inlining. > > Peter > > On Thursday 17 December 2009 15:23:55 R?mi Forax wrote: > >> The function model creates one function by lambda. >> >> class A { >> public static void main(String[] args) { >> #int(int) f = #(int x) (x+x); >> f(2); >> } >> } >> >> is translated to: >> >> class A { >> public static void main(String[] args) { >> ldc static lambda$1(int)int // (1) >> astore 1 // (2) >> aload 1 >> aconst_2 >> invokevirtual A.invokeLambda(int)int // (3) >> pop >> } >> >> private static int lambda$1(int x) { >> return x+x; >> } >> } >> >> I've written the body of the main in bytecode because there is non >> equivalent in Java. >> First, the JSR 292 define a new constant pool constant (see [2]) >> that allow to reference a function (here a static method) using opcode ldc. >> So instantiating a lambda is just a ldc (1). >> At runtime, this object is a java.dyn.MethodHandle, so it can be stored >> as an object (2). >> To call the lambda, the VM allows to call a magic method (3) named >> invokeLambda (name may changed). >> At runtime, the VM checks that the method handle type is compatible with >> the type of invokeLambda >> and call the function pointer stored in the method handle. >> >> Because a method handle knows its runtime type, it's possible to >> implement instanceof and >> cast on a function type. >> Function type that are parametrized have the same constraint that >> parameterized type, i.e >> cast are unsafe. >> >> If function type are translated to method handle, megamorphic call site >> problem can be solved because >> JIT can recognize the pattern (a method that takes a method handle) and >> do an aggressive inlining of >> such method. >> >> >> In summary, JSR 292 method handles was introduced by JSR 292 expert >> group because it solves >> common problems encounters when dealing with function pointer encoded >> using interfaces. >> It will be stupid to don't eating our own dog food. >> >> R?mi >> >> From neal at gafter.com Thu Dec 17 08:16:20 2009 From: neal at gafter.com (Neal Gafter) Date: Thu, 17 Dec 2009 08:16:20 -0800 Subject: Method calls vs lambda calls In-Reply-To: <3dd3f56a0912170122m17315735p6464754bb824dc8@mail.gmail.com> References: <3dd3f56a0912160616p478ec54m88aad23e2c8a9c78@mail.gmail.com> <4B28F06F.1030402@the-loom.de> <15e8b9d20912160807l4132b88au2965410582b62f13@mail.gmail.com> <4B2930C2.5010309@the-loom.de> <15e8b9d20912161138o2c2042f8u14b8983034b91b1@mail.gmail.com> <3dd3f56a0912170002h15d7093bj555a48c8a705c4e@mail.gmail.com> <15e8b9d20912170009v4cdc701bm183511ebb29fa50e@mail.gmail.com> <3dd3f56a0912170122m17315735p6464754bb824dc8@mail.gmail.com> Message-ID: <15e8b9d20912170816s78409d47k7c32513d89b518cc@mail.gmail.com> This is a more general problem of the shorthand syntax being or not being available in subtypes of function types. If we have class C implements #int(int) { ... } C c; Can we use the shorthand c(4)? Cheers, Neal On Thu, Dec 17, 2009 at 1:22 AM, Howard Lovatt wrote: > Yes that is a forth option; but it is confusing because people expect > generic types to behave like concrete types (that's the point of > generics). Anomalous behavior of generics, e.g. interaction with > arrays, is already a problem and this option will only increase the > problems. For example the following would work with the option I > listed as 2, but not with this fourth option: > > class Base { T t; } > class Reasonable extends Base> { > { t = new ArrayList(); } > void reasonable() { t.add( 1 ); } > } > class Unreasonable extends Base<#int()> { > { t = #int() (42); } > void unreasonable() { out.println( t(); } // Error, T is not > behaving as a #int() > } > > If in reasonable() I can treat T as a List, why in unreasonable() > can't I treat T as a #int()? (Ok in some circumstances I can treat T > as a #int(), but not in all.) > > -- Howard. > > 2009/12/17 Neal Gafter : > > On Thu, Dec 17, 2009 at 12:02 AM, Howard Lovatt > > wrote: > >> > >> Based on Neal's generic example, here is a particularly nasty case: > >> > >> class Base { > >> T t; > >> T t1; > >> void t() { out.println( t ); } > >> } > >> > >> class Derived extends Base<#int()> { > >> { > >> t = #int() (42); // Can't override t() because it has a different > >> signature > >> t1 = #int() (41); > >> } > >> void test() { > >> out.println( t1 ); // Prints Function_intATXXX > >> out.println( t1() ); // Would be nice if this printed 41 > >> out.println( t ); // Prints Function_intATXXX > >> out.println( t() ); // Error t() returns void > >> } > >> } > >> ... > >> Can anyone think of any other options? > > > > Yes: a variable is added to the method namespace only when declared with > a > > function type. In this example, t and t1 are not declared with a > function > > type, but rather are declared with the type of a type parameter (T). > > Therefore shorthand invocation is not available for them. > > > > This is a nice solution because it prevents names being inherited into a > > namespace in which they did not previously appear. > > > > Cheers, > > Neal > > > > ______________________________________________________________________ > > This email has been scanned by the MessageLabs Email Security System. > > For more information please visit http://www.messagelabs.com/email > > ______________________________________________________________________ > From john at milsson.nu Thu Dec 17 12:14:35 2009 From: john at milsson.nu (John Nilsson) Date: Thu, 17 Dec 2009 21:14:35 +0100 Subject: Lambda and JSR 292 method handle In-Reply-To: <4B2A5662.5050105@univ-mlv.fr> References: <4B2A3EFB.5030406@univ-mlv.fr> <200912171643.49575.peter.levart@marand.si> <4B2A5662.5050105@univ-mlv.fr> Message-ID: On Thu, Dec 17, 2009 at 5:03 PM, R?mi Forax wrote: > You don't need a class. There is a special operation named insertArguments > that allow to specify the first arguments of a method handle in order to > create > another method handle. This operation is commonly called currying. In reference to the earlier thread about being careful about terminology it would be more correct to call it partial application. Currying is the act of taking #R(A1,A2,...,An) and turn it into ###...#R(An)...(A2)(TA1) (I must say that this type syntax isn't really nice to higher order functions ... ) BR, John From markmahieu at googlemail.com Thu Dec 17 16:09:35 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Fri, 18 Dec 2009 01:09:35 +0100 Subject: Lambda and JSR 292 method handle In-Reply-To: <4B2A3EFB.5030406@univ-mlv.fr> References: <4B2A3EFB.5030406@univ-mlv.fr> Message-ID: <5E77B1F9-EDF6-4C17-82C7-E8A79C96D8E3@googlemail.com> On 17 Dec 2009, at 15:23, R?mi Forax wrote: > > 3) Who is in charge of creating interfaces representing function types ? > Currently the BGGA compiler creates these interfaces when needed at > compile time. > This solution is not feasible if you have jars or modules, > it generates double definitions and conflicts. > I haven't seen any serious proposal to resolve that problem. > I believe the idea was that, in a production-quality implementation, those interfaces would be synthesised when needed by the runtime. Mark From forax at univ-mlv.fr Thu Dec 17 16:27:28 2009 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Fri, 18 Dec 2009 01:27:28 +0100 Subject: Lambda and JSR 292 method handle In-Reply-To: <5E77B1F9-EDF6-4C17-82C7-E8A79C96D8E3@googlemail.com> References: <4B2A3EFB.5030406@univ-mlv.fr> <5E77B1F9-EDF6-4C17-82C7-E8A79C96D8E3@googlemail.com> Message-ID: <4B2ACC70.6060005@univ-mlv.fr> Le 18/12/2009 01:09, Mark Mahieu a ?crit : > > On 17 Dec 2009, at 15:23, R?mi Forax wrote: >> >> 3) Who is in charge of creating interfaces representing function types ? >> Currently the BGGA compiler creates these interfaces when needed at >> compile time. >> This solution is not feasible if you have jars or modules, >> it generates double definitions and conflicts. >> I haven't seen any serious proposal to resolve that problem. >> > > I believe the idea was that, in a production-quality implementation, > those interfaces would be synthesised when needed by the runtime. > > Mark > > This will require to modify the VM or is there a trick ? R?mi From markmahieu at googlemail.com Thu Dec 17 16:29:51 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Fri, 18 Dec 2009 01:29:51 +0100 Subject: Lambda and JSR 292 method handle In-Reply-To: References: <4B2A3EFB.5030406@univ-mlv.fr> <200912171643.49575.peter.levart@marand.si> <4B2A5662.5050105@univ-mlv.fr> Message-ID: On 17 Dec 2009, at 21:14, John Nilsson wrote: > On Thu, Dec 17, 2009 at 5:03 PM, R?mi Forax wrote: > >> You don't need a class. There is a special operation named insertArguments >> that allow to specify the first arguments of a method handle in order to >> create >> another method handle. This operation is commonly called currying. > > > In reference to the earlier thread about being careful about terminology it > would be more correct to call it partial application. > > Currying is the act of taking #R(A1,A2,...,An) and turn it into > ###...#R(An)...(A2)(TA1) > (I must say that this type syntax isn't really nice to higher order > functions ... ) > > BR, > John > The syntax isn't really nice to a couple of other things either, once you move away from simple 'soundbite' examples. And I'm also glad you raised the distinction between currying and partial application; there have been numerous requests to support 'currying' closures/lambdas during related discussions, but it has rarely been clear whether the perceived need really is for currying or for partial application, and moreover what use cases the person requesting it has in mind. Whichever it is that people are after, a few examples of envisaged usage would be a big help. Mark From markmahieu at googlemail.com Thu Dec 17 16:35:41 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Fri, 18 Dec 2009 01:35:41 +0100 Subject: Lambda and JSR 292 method handle In-Reply-To: <4B2ACC70.6060005@univ-mlv.fr> References: <4B2A3EFB.5030406@univ-mlv.fr> <5E77B1F9-EDF6-4C17-82C7-E8A79C96D8E3@googlemail.com> <4B2ACC70.6060005@univ-mlv.fr> Message-ID: <37D25CDB-5494-4E86-BC3E-25BD68697A69@googlemail.com> On 18 Dec 2009, at 01:27, R?mi Forax wrote: > Le 18/12/2009 01:09, Mark Mahieu a ?crit : >> >> >> On 17 Dec 2009, at 15:23, R?mi Forax wrote: >>> >>> 3) Who is in charge of creating interfaces representing function types ? >>> Currently the BGGA compiler creates these interfaces when needed at >>> compile time. >>> This solution is not feasible if you have jars or modules, >>> it generates double definitions and conflicts. >>> I haven't seen any serious proposal to resolve that problem. >>> >> >> I believe the idea was that, in a production-quality implementation, those interfaces would be synthesised when needed by the runtime. >> >> Mark >> >> > > This will require to modify the VM or is there a trick ? > > R?mi From http://www.javac.info/issues-v05.html : "The system class loader should dynamically generate function type interfaces. The interfaces corresponding to function types should be generated on demand by the bootstrap class loader, so they can be shared among all user code. For the prototype, we may have javac generate these interfaces so prototype-generated code can run on stock (JDK5-6) VMs." Mark From neal at gafter.com Thu Dec 17 21:22:44 2009 From: neal at gafter.com (Neal Gafter) Date: Thu, 17 Dec 2009 21:22:44 -0800 Subject: Method calls vs lambda calls In-Reply-To: References: <3dd3f56a0912160616p478ec54m88aad23e2c8a9c78@mail.gmail.com> <4B28F06F.1030402@the-loom.de> <15e8b9d20912160807l4132b88au2965410582b62f13@mail.gmail.com> <4B2930C2.5010309@the-loom.de> <15e8b9d20912161138o2c2042f8u14b8983034b91b1@mail.gmail.com> <3dd3f56a0912170002h15d7093bj555a48c8a705c4e@mail.gmail.com> <15e8b9d20912170009v4cdc701bm183511ebb29fa50e@mail.gmail.com> <3dd3f56a0912170122m17315735p6464754bb824dc8@mail.gmail.com> <15e8b9d20912170816s78409d47k7c32513d89b518cc@mail.gmail.com> Message-ID: <15e8b9d20912172122p2fa092dam13c4343bf36acd6e@mail.gmail.com> On Thu, Dec 17, 2009 at 11:04 AM, Howard Lovatt wrote: > Yes, another good one :(. I suspect that the short form just isn't > practical. > Good questions just need good answers. I think it's far too early to give up. From mr at sun.com Thu Dec 17 21:43:33 2009 From: mr at sun.com (Mark Reinhold) Date: Thu, 17 Dec 2009 21:43:33 -0800 Subject: Whither extension methods? In-Reply-To: jjb@google.com; Mon, 14 Dec 2009 23:46:38 PST; <17b2302a0912142346h13243ac3wf995be1c021145ef@mail.gmail.com> Message-ID: <20091218054333.365DA68F@eggemoggin.niobe.net> > Date: Mon, 14 Dec 2009 23:46:38 -0800 > From: Joshua Bloch > Doug Lea sent this a couple of days ago, and I think it deserves our > consideration: > >> I confess to being a little confused about the rationale for extension >> methods. >> >> Suppose we have a Map, and want to some sort of apply-to-each-value >> operation. The only reasonable way to do this in parallel is to somehow >> splitthe work. But Map has no public methods allowing you to do this -- you >> can only get an iterator, which is inherently sequential. Now, if we >> could get at the representations, then we could actually do splits for most >> java.util maps (at least for the most common ones -- HashMaps, TreeMaps). So >> the only way I know for these to be bolted on is to introduce new interfaces >> that each of the these existing classes could be changed to implement. Or am >> I missing something? The rationale for extension methods (or something like them) is to allow lambda expressions to be used to express sequential computations upon instances of the existing collection classes, in much the same manner as will be possible with parallel arrays, without the need to cast such instances to some new, specialized type. This rationale doesn't take into account the possibility of implementing these bulk-data operations automagically in parallel when appropriate. I agree that's something worth exploring, and I realize that the outcome could be another argument against adding extension methods in the first place. - Mark From pbenedict at apache.org Thu Dec 17 22:12:26 2009 From: pbenedict at apache.org (Paul Benedict) Date: Fri, 18 Dec 2009 00:12:26 -0600 Subject: Method calls vs lambda calls In-Reply-To: <15e8b9d20912172122p2fa092dam13c4343bf36acd6e@mail.gmail.com> References: <3dd3f56a0912160616p478ec54m88aad23e2c8a9c78@mail.gmail.com> <15e8b9d20912160807l4132b88au2965410582b62f13@mail.gmail.com> <4B2930C2.5010309@the-loom.de> <15e8b9d20912161138o2c2042f8u14b8983034b91b1@mail.gmail.com> <3dd3f56a0912170002h15d7093bj555a48c8a705c4e@mail.gmail.com> <15e8b9d20912170009v4cdc701bm183511ebb29fa50e@mail.gmail.com> <3dd3f56a0912170122m17315735p6464754bb824dc8@mail.gmail.com> <15e8b9d20912170816s78409d47k7c32513d89b518cc@mail.gmail.com> <15e8b9d20912172122p2fa092dam13c4343bf36acd6e@mail.gmail.com> Message-ID: Neal, Not that you are the forum's bookkeeper, but are the "good questions" being tracked anywhere? Paul On Thu, Dec 17, 2009 at 11:22 PM, Neal Gafter wrote: > On Thu, Dec 17, 2009 at 11:04 AM, Howard Lovatt wrote: > >> ?Yes, another good one :(. I suspect that the short form just isn't >> practical. >> > > Good questions just need good answers. ?I think it's far too early to give > up. > > From i30817 at gmail.com Fri Dec 18 01:12:40 2009 From: i30817 at gmail.com (Paulo Levi) Date: Fri, 18 Dec 2009 09:12:40 +0000 Subject: Extension methods and API evolution In-Reply-To: <64efa1ba0912160931k1867f9d3l58aeae4f329d61a4@mail.gmail.com> References: <64efa1ba0912110302g2aa55447mcd4256618492d2f2@mail.gmail.com> <20091216170011.52F20560@eggemoggin.niobe.net> <64efa1ba0912160931k1867f9d3l58aeae4f329d61a4@mail.gmail.com> Message-ID: <212322090912180112k30cfdf51t2b5edfda2e178fb2@mail.gmail.com> Very strange that you seem to value fragmentation over centralization. The "useful" higher order functions have been explored for more than ten years in languages like haskell, that have no problem with breaking compatibility. Your solution would be what? Wait for 10 different Collections clones and choose the "best" for each project? I for one am tired of that. As for traits, i believe that either extension methods should be in but hidden, so traits could be implemented later, or traits come at the same time as lambdas. Override-ability is key for the success of any additional methods in the "interfaces". From howard.lovatt at iee.org Fri Dec 18 02:55:52 2009 From: howard.lovatt at iee.org (Howard Lovatt) Date: Fri, 18 Dec 2009 11:55:52 +0100 Subject: Lambda and JSR 292 method handle Message-ID: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> R?mi, I thought the idea from the JSR 292 group was to use JavaMethodHandle [1] (which extends MethodHandle). The difference is that the JavaMethodHandle retains the type information, needed by Java, and it can implement interfaces so you can use a lambda with an existing function. Your example: class A { public static void main(String[] args) { #int(int) f = #(int x) (x+x); f(2); } } Would get translated to: class A { private static final class Lambda$1 extends JavaMethodHandle implements CallableIntInt { private static final Lambda$1 instance = new Lambda$1(); @Override public int call( int x ) { return x + x; } private Lambda$1() { super "CALL"; } private static final MethodHandle CALL = MethodHandles.lookup().findVirtual( Lambda$1.class, "call", MethodHandles.methodType( int.class, int.class ) ); } public static void main(String[] args) { CallableIntInt f = Lambda$1.instance; f.call(2); } } Where CallableIntInt is either a standard interface, in java.lang say, or a synthetic interface (depending on implementation details) and is: public interface CallableIntInt { int call( int a ); } If you use a MethodHandle directly then you can't pass it to anything because you have lost the type information, i.e. an invokeGeneric on a method handle will accept any arguments (though will throw a runtime exception). EG if I have a method: void m( #int(int) f ) { out.println( f( 2 ) ); } Then if you use MethodHandles directly it would be translated to: void m( MethodHandle f ) { out.println( f.invokeGeneric( 2 ) ); } But then I could say: m( #void() () ); And the compiler couldn't catch the mistake. Using JavaMethodHandles instead, would mean m is translated into: void m( CallableIntInt f ) { out.println( f.call( 2 ) ); } And hence retains type safety. The above JavaMethodHandle version doesn't seem to be that much better than using an inner class directly! There was also, at least originally, talk of anonymous classes in JSR 292 [2]; these would seem to be more useful, are they still part of JSR 292? (I ask because I think you are on the expert group.) -- Howard. PS The above APIs are in a state of flux, I have used the versions (at least I tried to without having a compiler to check my code) from the paper you can download from [3]. Ref: [1] http://cr.openjdk.java.net/~jrose/pres/indy-javadoc-b59/ [2] http://blogs.sun.com/jrose/resource/DVMTest.java.txt [3] http://blogs.sun.com/jrose/entry/vmil_paper_on_invokedynamic From forax at univ-mlv.fr Fri Dec 18 06:05:53 2009 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Fri, 18 Dec 2009 15:05:53 +0100 Subject: Lambda and JSR 292 method handle In-Reply-To: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> Message-ID: <4B2B8C41.2020705@univ-mlv.fr> Le 18/12/2009 11:55, Howard Lovatt a ?crit : > R?mi, > > I thought the idea from the JSR 292 group was to use JavaMethodHandle > [1] (which extends MethodHandle). The difference is that the > JavaMethodHandle retains the type information, needed by Java, and it > can implement interfaces so you can use a lambda with an existing > function. Your example: > > class A { > public static void main(String[] args) { > #int(int) f = #(int x) (x+x); > f(2); > } > } > Here is what I am thinking: A JavaMethodHandle is a method handle that allow you to implement one or more interface. One goal is to use it to implement function conversion, i.e when you want to use a lambda as a class implementing an interface like Runnable, Callable, etc to be able to use legacy code. Because a JavaMethodHandle is a method handle, you don't need an interface like CallableInitInt, you already can invoke it using .invokeLambda(). This approach is too heavyweight for being used for 'classical' lambda because it requires to create a new class for each lambda. Some experts in JSR 292 expert group think that JavaMethodHandle aren't neccessary. They complexify the implementation and may disable some optimizations done by the VM. So this feature is still under consideration. You can notice that function conversion (the one of the strawman proposal and the one of BGGA) doesn't require that the resulting object to be a lambda. Runnable r = #() { System.out.println("run"); } #void() f = (#void()) r; // works with JavaMethodHandle but not required by the spec So function conversion can be implemented without JavaMethodHandle. Cheers, R?mi > Would get translated to: > > class A { > private static final class Lambda$1 extends JavaMethodHandle > implements CallableIntInt { > private static final Lambda$1 instance = new Lambda$1(); > @Override public int call( int x ) { return x + x; } > private Lambda$1() { super "CALL"; } > private static final MethodHandle CALL = > MethodHandles.lookup().findVirtual( Lambda$1.class, "call", > MethodHandles.methodType( int.class, int.class ) ); > } > public static void main(String[] args) { > CallableIntInt f = Lambda$1.instance; > f.call(2); > } > } > > Where CallableIntInt is either a standard interface, in java.lang say, > or a synthetic interface (depending on implementation details) and is: > > public interface CallableIntInt { int call( int a ); } > > If you use a MethodHandle directly then you can't pass it to anything > because you have lost the type information, i.e. an invokeGeneric on a > method handle will accept any arguments (though will throw a runtime > exception). EG if I have a method: > > void m( #int(int) f ) { out.println( f( 2 ) ); } > > Then if you use MethodHandles directly it would be translated to: > > void m( MethodHandle f ) { out.println( f.invokeGeneric( 2 ) ); } > > But then I could say: > > m( #void() () ); > > And the compiler couldn't catch the mistake. Using JavaMethodHandles > instead, would mean m is translated into: > > void m( CallableIntInt f ) { out.println( f.call( 2 ) ); } > > And hence retains type safety. > > The above JavaMethodHandle version doesn't seem to be that much better > than using an inner class directly! There was also, at least > originally, talk of anonymous classes in JSR 292 [2]; these would seem > to be more useful, are they still part of JSR 292? (I ask because I > think you are on the expert group.) > > -- Howard. > > PS The above APIs are in a state of flux, I have used the versions (at > least I tried to without having a compiler to check my code) from the > paper you can download from [3]. > > Ref: > [1] http://cr.openjdk.java.net/~jrose/pres/indy-javadoc-b59/ > [2] http://blogs.sun.com/jrose/resource/DVMTest.java.txt > [3] http://blogs.sun.com/jrose/entry/vmil_paper_on_invokedynamic > From neal at gafter.com Fri Dec 18 06:35:27 2009 From: neal at gafter.com (Neal Gafter) Date: Fri, 18 Dec 2009 06:35:27 -0800 Subject: Method calls vs lambda calls In-Reply-To: References: <3dd3f56a0912160616p478ec54m88aad23e2c8a9c78@mail.gmail.com> <4B2930C2.5010309@the-loom.de> <15e8b9d20912161138o2c2042f8u14b8983034b91b1@mail.gmail.com> <3dd3f56a0912170002h15d7093bj555a48c8a705c4e@mail.gmail.com> <15e8b9d20912170009v4cdc701bm183511ebb29fa50e@mail.gmail.com> <3dd3f56a0912170122m17315735p6464754bb824dc8@mail.gmail.com> <15e8b9d20912170816s78409d47k7c32513d89b518cc@mail.gmail.com> <15e8b9d20912172122p2fa092dam13c4343bf36acd6e@mail.gmail.com> Message-ID: <15e8b9d20912180635g36193dc9xee0d430eda9494f5@mail.gmail.com> On Thu, Dec 17, 2009 at 10:12 PM, Paul Benedict wrote: > Not that you are the forum's bookkeeper, but are the "good questions" > being tracked anywhere? > Mark Reinhold explicitly declined the use of the wiki I provided because of IP concerns. I don't know if he's arranging something else. Cheers, Neal From neal at gafter.com Fri Dec 18 06:41:42 2009 From: neal at gafter.com (Neal Gafter) Date: Fri, 18 Dec 2009 06:41:42 -0800 Subject: Lambda and JSR 292 method handle In-Reply-To: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> Message-ID: <15e8b9d20912180641u780ef412w9d5f03b228481f01@mail.gmail.com> On Fri, Dec 18, 2009 at 2:55 AM, Howard Lovatt wrote: > I thought the idea from the JSR 292 group was to use JavaMethodHandle > [1] (which extends MethodHandle). The difference is that the > JavaMethodHandle retains the type information, needed by Java, and it > can implement interfaces so you can use a lambda with an existing > function. Do the types representing jsr292's JavaMethodHandle obey subtype relationships that make them covariant on return type and contravariant on argument types? Or, at least, is it possible to use the consistently so they act that way? Cheers, Neal From howard.lovatt at iee.org Fri Dec 18 06:47:51 2009 From: howard.lovatt at iee.org (Howard Lovatt) Date: Fri, 18 Dec 2009 15:47:51 +0100 Subject: Lambda and JSR 292 method handle In-Reply-To: <15e8b9d20912180641u780ef412w9d5f03b228481f01@mail.gmail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <15e8b9d20912180641u780ef412w9d5f03b228481f01@mail.gmail.com> Message-ID: <3dd3f56a0912180647q1525a6ebodf91f1e43099da76@mail.gmail.com> It is my reading of John's paper that an invokeGeneric on a MethodHandle will do all the subtyping and that JavaMethodHandle uses invokeGeneric under the covers, therefore yes to your point. I will re-iterate that is my reading of his paper, I don't have any inside knowledge. -- Howard. 2009/12/18 Neal Gafter : > On Fri, Dec 18, 2009 at 2:55 AM, Howard Lovatt > wrote: >> >> I thought the idea from the JSR 292 group was to use JavaMethodHandle >> [1] (which extends MethodHandle). The difference is that the >> JavaMethodHandle retains the type information, needed by Java, and it >> can implement interfaces so you can use a lambda with an existing >> function. > > Do the types representing jsr292's JavaMethodHandle obey subtype > relationships that make them covariant on return type and contravariant on > argument types?? Or, at least, is it possible to use the consistently so > they act that way? > > Cheers, > Neal > > > ______________________________________________________________________ > This email has been scanned by the MessageLabs Email Security System. > For more information please visit http://www.messagelabs.com/email > ______________________________________________________________________ > -- -- Howard. From forax at univ-mlv.fr Fri Dec 18 06:48:28 2009 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Fri, 18 Dec 2009 15:48:28 +0100 Subject: Lambda and JSR 292 method handle In-Reply-To: <15e8b9d20912180641u780ef412w9d5f03b228481f01@mail.gmail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <15e8b9d20912180641u780ef412w9d5f03b228481f01@mail.gmail.com> Message-ID: <4B2B963C.9080805@univ-mlv.fr> Le 18/12/2009 15:41, Neal Gafter a ?crit : > On Fri, Dec 18, 2009 at 2:55 AM, Howard Lovattwrote: > > >> I thought the idea from the JSR 292 group was to use JavaMethodHandle >> [1] (which extends MethodHandle). The difference is that the >> JavaMethodHandle retains the type information, needed by Java, and it >> can implement interfaces so you can use a lambda with an existing >> function. >> > > Do the types representing jsr292's JavaMethodHandle obey subtype > relationships that make them covariant on return type and contravariant on > argument types? Yes, if they are invoked using invokeLambda() and no other invoke*. For the record, even if this could changed, there are two other method invoke*, invokeExact that requires the exaxct same signature and invokeGeneric that is able to do conversion like boxing/unboxing etc. > Or, at least, is it possible to use the consistently so > they act that way? > > Cheers, > Neal > > Cheers, R?mi From howard.lovatt at iee.org Fri Dec 18 06:57:46 2009 From: howard.lovatt at iee.org (Howard Lovatt) Date: Fri, 18 Dec 2009 15:57:46 +0100 Subject: Lambda and JSR 292 method handle In-Reply-To: <15e8b9d20912180641u780ef412w9d5f03b228481f01@mail.gmail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <15e8b9d20912180641u780ef412w9d5f03b228481f01@mail.gmail.com> Message-ID: <3dd3f56a0912180657m76566c67t55a83cd2159529f8@mail.gmail.com> Oops - just reread what you said - the answer is it depends on the interface you implement. JavaMethodHandle is intended to look just like a normal Java method. Therefore the arguments you give to the JavaMethodHandle must be assignment compatible with the actual lambda's arguments (but will auto box/unbox) and the return type will be as specified for the actual lambda (again with box/unbox). 2009/12/18 Neal Gafter : > On Fri, Dec 18, 2009 at 2:55 AM, Howard Lovatt > wrote: >> >> I thought the idea from the JSR 292 group was to use JavaMethodHandle >> [1] (which extends MethodHandle). The difference is that the >> JavaMethodHandle retains the type information, needed by Java, and it >> can implement interfaces so you can use a lambda with an existing >> function. > > Do the types representing jsr292's JavaMethodHandle obey subtype > relationships that make them covariant on return type and contravariant on > argument types?? Or, at least, is it possible to use the consistently so > they act that way? > > Cheers, > Neal > > > ______________________________________________________________________ > This email has been scanned by the MessageLabs Email Security System. > For more information please visit http://www.messagelabs.com/email > ______________________________________________________________________ > -- -- Howard. From pdoubleya at gmail.com Fri Dec 18 07:06:39 2009 From: pdoubleya at gmail.com (Patrick Wright) Date: Fri, 18 Dec 2009 16:06:39 +0100 Subject: Extension methods and API evolution In-Reply-To: <212322090912180112k30cfdf51t2b5edfda2e178fb2@mail.gmail.com> References: <64efa1ba0912110302g2aa55447mcd4256618492d2f2@mail.gmail.com> <20091216170011.52F20560@eggemoggin.niobe.net> <64efa1ba0912160931k1867f9d3l58aeae4f329d61a4@mail.gmail.com> <212322090912180112k30cfdf51t2b5edfda2e178fb2@mail.gmail.com> Message-ID: <64efa1ba0912180706w552b84e3q453e051b6401b702@mail.gmail.com> > Very strange that you seem to value fragmentation over centralization. The > "useful" higher order functions have been explored for more than ten years > in languages like haskell, that have no problem with breaking compatibility. > Your solution would be what? Wait for 10 different Collections clones and > choose the "best" for each project? > > I for one am tired of that. There is, as a matter of fact, a difference of opinion on how specific APIs should look and feel, across languages and within a language, as well as across domains, and yes, I do believe experimentation does help determine the "best possible" form that an API should take. The declaration-site approach advocates opening certain interfaces up for surgery, and sewing them up till the next Java release. In particular, it means that there are only a few months to nail that down, which in particular means we won't have much time to experiment with the API before blessing it. And then the API will be a) forever a part of the JDK and b) as a public API, unmodifiable until Java 8. I find that limiting, and thus not likely to lead to the best set of extension methods we could possibly hope for. Regards Patrick From howard.lovatt at iee.org Fri Dec 18 07:06:58 2009 From: howard.lovatt at iee.org (Howard Lovatt) Date: Fri, 18 Dec 2009 16:06:58 +0100 Subject: Lambda and JSR 292 method handle In-Reply-To: <4B2B8C41.2020705@univ-mlv.fr> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <4B2B8C41.2020705@univ-mlv.fr> Message-ID: <3dd3f56a0912180706v383bc710o1ab4f57e24b29afb@mail.gmail.com> I don't get what you are saying, probably just me being slow, so please bare with me. If in compilation unit A I have: void m( #int(int) f ) { out.println( f( 2 ); } and I use MethodHandle then this will get translated into: void m( MethodHandle f ) { out.println( f.invokeGeneric( 2 ) ); } Then in compilation unit B I will see the signature "void m( MethodHandle )", i.e. the actual types have been erased. In compilation unit B I can therefore say: m( #void() ); and the compiler will allow this because in compilation unit B it doesn't know that m really expects a #int(int) because that information was lost when the function type was converted to a MethodHandle which carries only type information at runtime not compiletime. What am I missing? Thanks, -- Howard. 2009/12/18 R?mi Forax : > Le 18/12/2009 11:55, Howard Lovatt a ?crit : >> >> R?mi, >> >> I thought the idea from the JSR 292 group was to use JavaMethodHandle >> [1] (which extends MethodHandle). The difference is that the >> JavaMethodHandle retains the type information, needed by Java, and it >> can implement interfaces so you can use a lambda with an existing >> function. Your example: >> >> class A { >> ? ?public static void main(String[] args) { >> ? ? ?#int(int) f = #(int x) (x+x); >> ? ? ?f(2); >> ? ?} >> } >> > > Here is what I am thinking: > A JavaMethodHandle is a method handle that allow you to implement one or > more interface. > One goal is to use it to implement function conversion, i.e when you want to > use a lambda > as a class implementing an interface like Runnable, Callable, etc to be able > to use legacy code. > Because a JavaMethodHandle is a method handle, you don't need an interface > like CallableInitInt, > you already can invoke it using .invokeLambda(). > > This approach is too heavyweight for being used for 'classical' lambda > because it requires > to create a new class for each lambda. > > Some experts in JSR 292 expert group think that JavaMethodHandle aren't > neccessary. > They complexify the implementation and may disable some optimizations done > by the VM. > So this feature is still under consideration. > > You can notice that function conversion (the one of the strawman proposal > and the one of BGGA) > doesn't require that the resulting object to be a lambda. > > Runnable r = #() { System.out.println("run"); } > #void() f = (#void()) r; ? ?// works with JavaMethodHandle but not required > by the spec > > So function conversion can be implemented without JavaMethodHandle. > > Cheers, > R?mi > >> Would get translated to: >> >> class A { >> ? private static final class Lambda$1 extends JavaMethodHandle >> implements CallableIntInt { >> ? ? private static final Lambda$1 instance = new Lambda$1(); >> ? ? @Override public int call( int x ) { return x + x; } >> ? ? private Lambda$1() { super "CALL"; } >> ? ? private static final MethodHandle CALL = >> MethodHandles.lookup().findVirtual( Lambda$1.class, "call", >> MethodHandles.methodType( int.class, int.class ) ); >> ? } >> ? public static void main(String[] args) { >> ? ? CallableIntInt f = Lambda$1.instance; >> ? ? f.call(2); >> ? } >> } >> >> Where CallableIntInt is either a standard interface, in java.lang say, >> or a synthetic interface (depending on implementation details) and is: >> >> public interface CallableIntInt { int call( int a ); } >> >> If you use a MethodHandle directly then you can't pass it to anything >> because you have lost the type information, i.e. an invokeGeneric on a >> method handle will accept any arguments (though will throw a runtime >> exception). EG if I have a method: >> >> void m( #int(int) f ) { out.println( f( 2 ) ); } >> >> Then if you use MethodHandles directly it would be translated to: >> >> void m( MethodHandle f ) { out.println( f.invokeGeneric( 2 ) ); } >> >> But then I could say: >> >> m( #void() () ); >> >> And the compiler couldn't catch the mistake. Using JavaMethodHandles >> instead, would mean m is translated into: >> >> void m( CallableIntInt f ) { out.println( f.call( 2 ) ); } >> >> And hence retains type safety. >> >> The above JavaMethodHandle version doesn't seem to be that much better >> than using an inner class directly! There was also, at least >> originally, talk of anonymous classes in JSR 292 [2]; these would seem >> to be more useful, are they still part of JSR 292? (I ask because I >> think you are on the expert group.) >> >> ? -- Howard. >> >> PS The above APIs are in a state of flux, I have used the versions (at >> least I tried to without having a compiler to check my code) from the >> paper you can download from [3]. >> >> Ref: >> [1] http://cr.openjdk.java.net/~jrose/pres/indy-javadoc-b59/ >> [2] http://blogs.sun.com/jrose/resource/DVMTest.java.txt >> [3] http://blogs.sun.com/jrose/entry/vmil_paper_on_invokedynamic >> > > > ______________________________________________________________________ > This email has been scanned by the MessageLabs Email Security System. > For more information please visit http://www.messagelabs.com/email > ______________________________________________________________________ > -- -- Howard. From neal at gafter.com Fri Dec 18 07:28:58 2009 From: neal at gafter.com (Neal Gafter) Date: Fri, 18 Dec 2009 07:28:58 -0800 Subject: Lambda and JSR 292 method handle In-Reply-To: <4B2B963C.9080805@univ-mlv.fr> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <15e8b9d20912180641u780ef412w9d5f03b228481f01@mail.gmail.com> <4B2B963C.9080805@univ-mlv.fr> Message-ID: <15e8b9d20912180728p938a098q721ae263713aff32@mail.gmail.com> On Fri, Dec 18, 2009 at 6:48 AM, R?mi Forax wrote: > Le 18/12/2009 15:41, Neal Gafter a ?crit : > > Do the types representing jsr292's JavaMethodHandle obey subtype >> relationships that make them covariant on return type and contravariant on >> argument types? >> > > Yes, if they are invoked using invokeLambda() and no other invoke*. > For the record, even if this could changed, there are two other method > invoke*, > invokeExact that requires the exaxct same signature and invokeGeneric that > is able > to do conversion like boxing/unboxing etc. > This doesn't answer my question. I'm taking about subtyping among values of function type, not about the invocation point. Specifically, it should be the case that, given *#Object(String) f1;* *#String(Object) f2 = ...;* you can assign *f1 = f2;* This needs to be a subtype conversion (e.g. no code should have to be generated for this conversion to occur) for reasons that I can explain if it is not already clear. The ParallelArray APIs take advantage of this kind of subtyping by defining its function types using interfaces and wildcards. If that API is recast using function types, some flexibility will be lost unless function types act this way too. The answer may depend on *how* function types are mapped to JavaMethodHandle. There is no public proposal on the table yet for how that would work. I hope the anonymous experts inside Sun that Mark suggested are devoted to this work are on it. Cheers, Neal From howard.lovatt at iee.org Fri Dec 18 08:03:45 2009 From: howard.lovatt at iee.org (Howard Lovatt) Date: Fri, 18 Dec 2009 17:03:45 +0100 Subject: Lambda and JSR 292 method handle In-Reply-To: <15e8b9d20912180641u780ef412w9d5f03b228481f01@mail.gmail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <15e8b9d20912180641u780ef412w9d5f03b228481f01@mail.gmail.com> Message-ID: <3dd3f56a0912180803v1fe4d12ay42d6c79d6901f67a@mail.gmail.com> My reading of John's paper is that this would be so, e.g.: Ops.Op f1 = Lambda$1.instance; Ops.Op f2 = Lambda$2.instance; f1 = f2; // OK With Ops.Op from the ParallelArray API (return type is the last argument in this API!) and Lambda$1 etc. use the JavaMethodHandle conversion I outlined in an earlier post. -- Howard. 2009/12/18 Neal Gafter : >This doesn't answer my question. I'm taking about subtyping among values of >function type, not about the invocation point. Specifically, it should be >the case that, given > >*#Object(String) f1;* >*#String(Object) f2 = ...;* > >you can assign > >*f1 = f2;* > >This needs to be a subtype conversion (e.g. no code should have to be >generated for this conversion to occur) for reasons that I can explain if it >is not already clear. The ParallelArray APIs take advantage of this kind of >subtyping by defining its function types using interfaces and wildcards. If >that API is recast using function types, some flexibility will be lost >unless function types act this way too. > >The answer may depend on *how* function types are mapped to >JavaMethodHandle. There is no public proposal on the table yet for how that >would work. I hope the anonymous experts inside Sun that Mark suggested are >devoted to this work are on it. > >Cheers, >Neal From forax at univ-mlv.fr Fri Dec 18 09:07:53 2009 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Fri, 18 Dec 2009 18:07:53 +0100 Subject: Lambda and JSR 292 method handle In-Reply-To: <15e8b9d20912180728p938a098q721ae263713aff32@mail.gmail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <15e8b9d20912180641u780ef412w9d5f03b228481f01@mail.gmail.com> <4B2B963C.9080805@univ-mlv.fr> <15e8b9d20912180728p938a098q721ae263713aff32@mail.gmail.com> Message-ID: <4B2BB6E9.6040904@univ-mlv.fr> Le 18/12/2009 16:28, Neal Gafter a ?crit : > On Fri, Dec 18, 2009 at 6:48 AM, R?mi Forax > wrote: > > Le 18/12/2009 15:41, Neal Gafter a ?crit : > > Do the types representing jsr292's JavaMethodHandle obey subtype > relationships that make them covariant on return type and > contravariant on > argument types? > > > Yes, if they are invoked using invokeLambda() and no other invoke*. > For the record, even if this could changed, there are two other > method invoke*, > invokeExact that requires the exaxct same signature and > invokeGeneric that is able > to do conversion like boxing/unboxing etc. > > > This doesn't answer my question. Sorry I was not clear. > I'm taking about subtyping among values of function type, not about > the invocation point. Specifically, it should be the case that, given > > *#Object(String) f1;* > *#String(Object) f2 = ...;* > > you can assign > > *f1 = f2;* #Object(String) and #String(Object) are both erased to java.dyn.MethodHandle, so there is no conversion: * MethodHandle f1; MethodHandle f2 = ... f1 = f2; *Now when you invoke f1 with a String, because subtyping is allowed when invoking, the VM will be able to call f2.* * > > This needs to be a subtype conversion (e.g. no code should have to be > generated for this conversion to occur) for reasons that I can explain > if it is not already clear. The ParallelArray APIs take advantage of > this kind of subtyping by defining its function types using interfaces > and wildcards. If that API is recast using function types, some > flexibility will be lost unless function types act this way too. > > The answer may depend on /how/ function types are mapped to > JavaMethodHandle. Function types are mapped to one unique type: java.dyn.MethodHandle, not JavaMethodHandle. JavaMethodHandle is a special subtype that can be used to translate some lambdas. > There is no public proposal on the table yet for how that would work. > I hope the anonymous experts inside Sun that Mark suggested are > devoted to this work are on it. So am I :) > > Cheers, > Neal > cheers, R?mi From forax at univ-mlv.fr Fri Dec 18 09:25:34 2009 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Fri, 18 Dec 2009 18:25:34 +0100 Subject: Lambda and JSR 292 method handle In-Reply-To: <3dd3f56a0912180706v383bc710o1ab4f57e24b29afb@mail.gmail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <4B2B8C41.2020705@univ-mlv.fr> <3dd3f56a0912180706v383bc710o1ab4f57e24b29afb@mail.gmail.com> Message-ID: <4B2BBB0E.30503@univ-mlv.fr> Le 18/12/2009 16:06, Howard Lovatt a ?crit : > I don't get what you are saying, probably just me being slow, so > please bare with me. If in compilation unit A I have: > > void m( #int(int) f ) { out.println( f( 2 ); } > > and I use MethodHandle then this will get translated into: > > void m( MethodHandle f ) { out.println( f.invokeGeneric( 2 ) ); } > > Then in compilation unit B I will see the signature "void m( > MethodHandle )", i.e. the actual types have been erased. In > compilation unit B I can therefore say: > > m( #void() ); > > and the compiler will allow this because in compilation unit B it > doesn't know that m really expects a #int(int) because that > information was lost when the function type was converted to a > MethodHandle which carries only type information at runtime not > compiletime. > > What am I missing? > #int(int) is kept in the bytecode in the attribute Signature wich is extended to support function type. It works like with the erasure of generics: interface List { boolean add(E element); } the compiler translates the generics code to: interface List { bolean add(Object element); } and insert a special method attribute named Signature to allow separate compilation of generics. In the example, the value of attribute Signature of method add(Object) is (E)Z If you want more info see 4.8.8 of class file format: http://java.sun.com/docs/books/jvms/second_edition/ClassFileFormat-Java5.pdf So void m(#int(int) f) is erased to void m(MethodHandle) but like generics, the attribute Signature will keep the function type, so its value will be something like (#I(I))V > Thanks, > > -- Howard. > Cheers, R?mi > 2009/12/18 R?mi Forax: > >> Le 18/12/2009 11:55, Howard Lovatt a ?crit : >> >>> R?mi, >>> >>> I thought the idea from the JSR 292 group was to use JavaMethodHandle >>> [1] (which extends MethodHandle). The difference is that the >>> JavaMethodHandle retains the type information, needed by Java, and it >>> can implement interfaces so you can use a lambda with an existing >>> function. Your example: >>> >>> class A { >>> public static void main(String[] args) { >>> #int(int) f = #(int x) (x+x); >>> f(2); >>> } >>> } >>> >>> >> Here is what I am thinking: >> A JavaMethodHandle is a method handle that allow you to implement one or >> more interface. >> One goal is to use it to implement function conversion, i.e when you want to >> use a lambda >> as a class implementing an interface like Runnable, Callable, etc to be able >> to use legacy code. >> Because a JavaMethodHandle is a method handle, you don't need an interface >> like CallableInitInt, >> you already can invoke it using .invokeLambda(). >> >> This approach is too heavyweight for being used for 'classical' lambda >> because it requires >> to create a new class for each lambda. >> >> Some experts in JSR 292 expert group think that JavaMethodHandle aren't >> neccessary. >> They complexify the implementation and may disable some optimizations done >> by the VM. >> So this feature is still under consideration. >> >> You can notice that function conversion (the one of the strawman proposal >> and the one of BGGA) >> doesn't require that the resulting object to be a lambda. >> >> Runnable r = #() { System.out.println("run"); } >> #void() f = (#void()) r; // works with JavaMethodHandle but not required >> by the spec >> >> So function conversion can be implemented without JavaMethodHandle. >> >> Cheers, >> R?mi >> >> >>> Would get translated to: >>> >>> class A { >>> private static final class Lambda$1 extends JavaMethodHandle >>> implements CallableIntInt { >>> private static final Lambda$1 instance = new Lambda$1(); >>> @Override public int call( int x ) { return x + x; } >>> private Lambda$1() { super "CALL"; } >>> private static final MethodHandle CALL = >>> MethodHandles.lookup().findVirtual( Lambda$1.class, "call", >>> MethodHandles.methodType( int.class, int.class ) ); >>> } >>> public static void main(String[] args) { >>> CallableIntInt f = Lambda$1.instance; >>> f.call(2); >>> } >>> } >>> >>> Where CallableIntInt is either a standard interface, in java.lang say, >>> or a synthetic interface (depending on implementation details) and is: >>> >>> public interface CallableIntInt { int call( int a ); } >>> >>> If you use a MethodHandle directly then you can't pass it to anything >>> because you have lost the type information, i.e. an invokeGeneric on a >>> method handle will accept any arguments (though will throw a runtime >>> exception). EG if I have a method: >>> >>> void m( #int(int) f ) { out.println( f( 2 ) ); } >>> >>> Then if you use MethodHandles directly it would be translated to: >>> >>> void m( MethodHandle f ) { out.println( f.invokeGeneric( 2 ) ); } >>> >>> But then I could say: >>> >>> m( #void() () ); >>> >>> And the compiler couldn't catch the mistake. Using JavaMethodHandles >>> instead, would mean m is translated into: >>> >>> void m( CallableIntInt f ) { out.println( f.call( 2 ) ); } >>> >>> And hence retains type safety. >>> >>> The above JavaMethodHandle version doesn't seem to be that much better >>> than using an inner class directly! There was also, at least >>> originally, talk of anonymous classes in JSR 292 [2]; these would seem >>> to be more useful, are they still part of JSR 292? (I ask because I >>> think you are on the expert group.) >>> >>> -- Howard. >>> >>> PS The above APIs are in a state of flux, I have used the versions (at >>> least I tried to without having a compiler to check my code) from the >>> paper you can download from [3]. >>> >>> Ref: >>> [1] http://cr.openjdk.java.net/~jrose/pres/indy-javadoc-b59/ >>> [2] http://blogs.sun.com/jrose/resource/DVMTest.java.txt >>> [3] http://blogs.sun.com/jrose/entry/vmil_paper_on_invokedynamic >>> >>> >> >> ______________________________________________________________________ >> This email has been scanned by the MessageLabs Email Security System. >> For more information please visit http://www.messagelabs.com/email >> ______________________________________________________________________ >> >> > > > From scolebourne at joda.org Sat Dec 19 04:12:21 2009 From: scolebourne at joda.org (Stephen Colebourne) Date: Sat, 19 Dec 2009 12:12:21 +0000 Subject: Extension methods and API evolution In-Reply-To: <64efa1ba0912160931k1867f9d3l58aeae4f329d61a4@mail.gmail.com> References: <64efa1ba0912110302g2aa55447mcd4256618492d2f2@mail.gmail.com> <20091216170011.52F20560@eggemoggin.niobe.net> <64efa1ba0912160931k1867f9d3l58aeae4f329d61a4@mail.gmail.com> Message-ID: <4B2CC325.5060405@joda.org> Patrick Wright wrote: > If extension methods are declaration-site, then java.util.List and > friends will have some methods added to them in JDK 7. These will then > be part of the official JDK API, which means, first, you have until > mid-2010 to get them right, second, you will never be able to change > or remove them, and third, we will all have to wait until 201X to have > any new(er) improved extension methods for those interfaces. +1 > I think what no one wants are magic extensions which appear in the > code without any choice on the part of the programmer, and are not > obvious from the source. But if there were some way to (waving hands > vaguely) to declare in the imports "...and extend List with > BetterReduceMethods" then that would not be an issue. > Perhaps I'm missing some way to reconcile this... I wrote one option up in a blog entry at the time of the original discussion - http://www.jroller.com/scolebourne/entry/java_7_extension_methods. The primary concern appears to be the lack of clarity for the reader of the code with use site extension methods, as the method isn't in the interface where you'd expect it to be. My proposed solution was to make the call site explicit that an extension method was being used as opposed to a regular method. Three possile syntaxes, there are many possible: list.do.sort(); list->sort(); list..sort(); In this way, the person reading the call site can see that the method call is unusual, and understand the different location of the underlying code. Its certainly not as pretty as a fully integrated method call simulation, but it does address the concen of clarity. I'm not saying that I'm especially in favou of the idea, as IDE colour coding helps these days, but it does fit your "waving hands vaguely" request fo a solution. Stephen From schulz at the-loom.de Sat Dec 19 04:46:15 2009 From: schulz at the-loom.de (Stefan Schulz) Date: Sat, 19 Dec 2009 13:46:15 +0100 Subject: Extension methods and API evolution In-Reply-To: <4B2CC325.5060405@joda.org> References: <64efa1ba0912110302g2aa55447mcd4256618492d2f2@mail.gmail.com> <20091216170011.52F20560@eggemoggin.niobe.net> <64efa1ba0912160931k1867f9d3l58aeae4f329d61a4@mail.gmail.com> <4B2CC325.5060405@joda.org> Message-ID: <4B2CCB17.4020502@the-loom.de> Stephen Colebourne wrote: > My proposed solution was to make the call site explicit that an > extension method was being used as opposed to a regular method. Three > possile syntaxes, there are many possible: > > list.do.sort(); > list->sort(); > list..sort(); > > In this way, the person reading the call site can see that the method > call is unusual, and understand the different location of the underlying > code. Firstly, I second that the transparent use of extension methods introduce complications especially on the reading site. And I am still unconvinced about the benefit of extension methods, but maybe I missed the win over static utility methods, except for being able to write list.sort() instead of sort(list). About two years ago I wrote a blog post [1] about extension methods vs. method currying (or rather partial application, as I learned recently), where the latter would also play nicely with function-typed variables. What I see with server-side extension methods, is that not only you have to wait for a library provider to update, fix, or extend, but that suddenly implementation details are going into an interface, one could not care less about when using the interface. To me, this seems as unfortunate as nested classes in interfaces. Stefan [1] http://jroller.com/jadda/entry/extension_methods_vs_method_currying From i30817 at gmail.com Sat Dec 19 04:54:45 2009 From: i30817 at gmail.com (Paulo Levi) Date: Sat, 19 Dec 2009 12:54:45 +0000 Subject: Extension methods and API evolution In-Reply-To: <4B2CCB17.4020502@the-loom.de> References: <64efa1ba0912110302g2aa55447mcd4256618492d2f2@mail.gmail.com> <20091216170011.52F20560@eggemoggin.niobe.net> <64efa1ba0912160931k1867f9d3l58aeae4f329d61a4@mail.gmail.com> <4B2CC325.5060405@joda.org> <4B2CCB17.4020502@the-loom.de> Message-ID: <212322090912190454n116b1b15h5fc5777a72043cf1@mail.gmail.com> I think mr. Ahe is right and callee site extension methods are best. In fact if they can be hidden or only usable by the jdk people, i would like them to be unusable by others, since traits appear to be the general solution (nigh on replacing the concept of interface), and can be added later, fully replacing this compiler trick. I believe this is fundamental to allow the jdk libraries to evolve, code in the interfaces non-withstanding, unless you want to go the .Net path with breaking binary compatibility. Otherwise you invite extreme fragmentation, and more so that you're going to add closures. I for one would convert my projects in a snap for a collections library that had reduce or map, if the readable possibility for that was there, and the jdk didn't add them. I don't think i'm alone in this. From grev at miginfocom.com Sat Dec 19 04:58:16 2009 From: grev at miginfocom.com (Mikael Grev) Date: Sat, 19 Dec 2009 13:58:16 +0100 Subject: Extension methods and API evolution In-Reply-To: <4B2CCB17.4020502@the-loom.de> References: <64efa1ba0912110302g2aa55447mcd4256618492d2f2@mail.gmail.com> <20091216170011.52F20560@eggemoggin.niobe.net> <64efa1ba0912160931k1867f9d3l58aeae4f329d61a4@mail.gmail.com> <4B2CC325.5060405@joda.org> <4B2CCB17.4020502@the-loom.de> Message-ID: On Dec 19, 2009, at 13:46 PM, Stefan Schulz wrote: > And I am still > unconvinced about the benefit of extension methods, but maybe I missed > the win over static utility methods, except for being able to write > list.sort() instead of sort(list) Having a utility method in another class breaks the logical path the developer has to the method. The developer has the list object and want to do a sort on it. There is no logical link between static utility methods in say Collections and the objects that they can handle. The developer must know this beforehand since it can't be explored with code completion or similar IDE aids. One can help a bit by putting "soft" references to classes containing utility methods in the JavaDoc, but those are not read by most once you've learnt the API. So chances that developers familiar with the List API will go back and read that soft link in Java 7 are not very good. So, having a method on the object itself is beneficial as it lowers the bar for finding out that it exist. Of course one can have the static method on List itself, but that isn't very clean, is it? Also, I'm no big fan of static imports everywhere so I would always type: List.sort(list) or Collections.sort(list) and never just sort(list) I know many that do the same. Many, as I, only import static for enums and maybe Math. Cheers, Mikael From john at milsson.nu Sat Dec 19 07:10:33 2009 From: john at milsson.nu (John Nilsson) Date: Sat, 19 Dec 2009 16:10:33 +0100 Subject: Extension methods and API evolution In-Reply-To: References: <64efa1ba0912110302g2aa55447mcd4256618492d2f2@mail.gmail.com> <20091216170011.52F20560@eggemoggin.niobe.net> <64efa1ba0912160931k1867f9d3l58aeae4f329d61a4@mail.gmail.com> <4B2CC325.5060405@joda.org> <4B2CCB17.4020502@the-loom.de> Message-ID: On Sat, Dec 19, 2009 at 1:58 PM, Mikael Grev wrote: > So, having a method on the object itself is beneficial as it lowers the bar > for finding out that it exist. > You could add better search features to the IDE to address this. But why would you? There's probably millions of methods taking i.e. List as argument that has no value for the context you are in. Why would I be more interested in List.sort than say, List.persist, or List.sumInvoiceAmt for that matter if I have a list of File objects in my current context? Also, I'm no big fan of static imports everywhere so I would always type: > Might one ask why? I know I had one issue with them being that the IDE didn't automatically add them to the import list when needed. However in Eclipse it's possible to configure it to search predefined classes for static methods to import. Which address both your autocomplete discoverability and my automatic import problem. BR, John From grev at miginfocom.com Sat Dec 19 07:22:40 2009 From: grev at miginfocom.com (Mikael Grev) Date: Sat, 19 Dec 2009 16:22:40 +0100 Subject: Extension methods and API evolution In-Reply-To: References: <64efa1ba0912110302g2aa55447mcd4256618492d2f2@mail.gmail.com> <20091216170011.52F20560@eggemoggin.niobe.net> <64efa1ba0912160931k1867f9d3l58aeae4f329d61a4@mail.gmail.com> <4B2CC325.5060405@joda.org> <4B2CCB17.4020502@the-loom.de> Message-ID: <300807EA-2C2F-43D3-8F20-89356F83C4A7@miginfocom.com> On Dec 19, 2009, at 16:10 PM, John Nilsson wrote: > On Sat, Dec 19, 2009 at 1:58 PM, Mikael Grev wrote: > So, having a method on the object itself is beneficial as it lowers the bar for finding out that it exist. > You could add better search features to the IDE to address this. But why would you? There's probably millions of methods taking i.e. List as argument that has no value for the context you are in. Why would I be more interested in List.sort than say, List.persist, or List.sumInvoiceAmt for that matter if I have a list of File objects in my current context? Exactly, that's why it's better to have methods that are generic in the List interface (i.e. sort with a closure as logic) and methods that are for a certain domain in classes, i.e. Persist#doPersistyStuff > > Also, I'm no big fan of static imports everywhere so I would always type: > Might one ask why? I know I had one issue with them being that the IDE didn't automatically add them to the import list when needed. However in Eclipse it's possible to configure it to search predefined classes for static methods to import. Which address both your autocomplete discoverability and my automatic import problem. Writing the characters isn't what takes time so I write Collections. and the press ctrl+space to get the methods. After selecting the correct method I see no need to have the IDE remove the reference to Collections. It only takes additional time and makes it less clear. This is no biggie for me, I just think it's wrong to always show examples with static imports in place since that doesn't tell the whole picture. There are other code in that file that needs to be typed or generated by the IDE. Cheers, Mikael > > BR, > John From schulz at the-loom.de Sat Dec 19 08:16:41 2009 From: schulz at the-loom.de (Stefan Schulz) Date: Sat, 19 Dec 2009 17:16:41 +0100 Subject: Extension methods and API evolution In-Reply-To: <300807EA-2C2F-43D3-8F20-89356F83C4A7@miginfocom.com> References: <64efa1ba0912110302g2aa55447mcd4256618492d2f2@mail.gmail.com> <20091216170011.52F20560@eggemoggin.niobe.net> <64efa1ba0912160931k1867f9d3l58aeae4f329d61a4@mail.gmail.com> <4B2CC325.5060405@joda.org> <4B2CCB17.4020502@the-loom.de> <300807EA-2C2F-43D3-8F20-89356F83C4A7@miginfocom.com> Message-ID: <4B2CFC69.30408@the-loom.de> Mikael Grev wrote: > On Dec 19, 2009, at 16:10 PM, John Nilsson wrote: >> On Sat, Dec 19, 2009 at 1:58 PM, Mikael Grev > > wrote: >> >> So, having a method on the object itself is beneficial as it >> lowers the bar for finding out that it exist. >> >> You could add better search features to the IDE to address this. But >> why would you? There's probably millions of methods taking i.e. List >> as argument that has no value for the context you are in. Why would I >> be more interested in List.sort than say, List.persist, or >> List.sumInvoiceAmt for that matter if I have a list of File objects in >> my current context? > > Exactly, that's why it's better to have methods that are generic in the > List interface (i.e. sort with a closure as logic) and methods that are > for a certain domain in classes, i.e. Persist#doPersistyStuff Finding some generic methods quickly to me, as John mentioned, sounds like an IDE topic. For example, by indexing and providing static methods whose first parameter matches the variable's type. I do not see quick finding of (few selected) methods a real benefit wrt. all the problems you have with class hierarchy compatibility and such. And I don't think that Traits would provide a better ratio on benefit and trouble. Declaration-site extensions or traits only allow the class developer to add useful methods, which is quite limited. I do not favour transparent use-site extensions, either, as they bear even more trouble. Colouring by IDEs might helpt to see the difference, but relying on IDEs to be able to read code properly to me is no good idea (while it is not that troublesome when writing code). As written in my blog, I am missing the more generic approach and gain, explicit partial application would give (and not only for the first parameter of a method) especially in conjunction with function-typing and method references. > Writing the characters isn't what takes time so I write Collections. and > the press ctrl+space to get the methods. After selecting the correct > method I see no need to have the IDE remove the reference to > Collections. It only takes additional time and makes it less clear. This > is no biggie for me, I just think it's wrong to always show examples > with static imports in place since that doesn't tell the whole picture. > There are other code in that file that needs to be typed or generated by > the IDE. I rarely use static imports. As you say, it's really not a matter of characters or typing, and it makes code more readable in my eyes to say Collections.sort() instead of sort() only. I even don't use it on enums, especially with nested enums belonging to a specific outer class that makes the semantic clear, keeps the enum name short, and binds the enum to that class. So, yes, static import of extension methods would add to hard to read code. Cheers, Stefan From peter.levart at gmail.com Sat Dec 19 08:47:56 2009 From: peter.levart at gmail.com (Peter Levart) Date: Sat, 19 Dec 2009 17:47:56 +0100 Subject: Extension methods and API evolution In-Reply-To: References: <64efa1ba0912110302g2aa55447mcd4256618492d2f2@mail.gmail.com> <4B2CCB17.4020502@the-loom.de> Message-ID: <200912191747.56696.peter.levart@gmail.com> On Saturday 19 December 2009 13:58:16 Mikael Grev wrote: > On Dec 19, 2009, at 13:46 PM, Stefan Schulz wrote: > > And I am still > > unconvinced about the benefit of extension methods, but maybe I missed > > the win over static utility methods, except for being able to write > > list.sort() instead of sort(list) > > Having a utility method in another class breaks the logical path the > developer has to the method. The developer has the list object and want to > do a sort on it. There is no logical link between static utility methods > in say Collections and the objects that they can handle. The developer > must know this beforehand since it can't be explored with code completion > or similar IDE aids. One can help a bit by putting "soft" references to > classes containing utility methods in the JavaDoc, but those are not read > by most once you've learnt the API. So chances that developers familiar > with the List API will go back and read that soft link in Java 7 are not > very good. > > So, having a method on the object itself is beneficial as it lowers the bar > for finding out that it exist. A no-language-change alternative of that might be standardizing an annotation in the JDK platform that every IDE would add support for. For example: package java.util; @UtilityMethods({ "java.util.Collections#binarySearch", "java.util.Collections#checkedList", "java.util.Collections#fill", "java.util.Collections#indexOfSubList", "java.util.Collections#lastIndexOfSubList", "java.util.Collections#replaceAll", "java.util.Collections#reverse", "java.util.Collections#rotate", "java.util.Collections#shuffle", "java.util.Collections#sort", "java.util.Collections#swap", "java.util.Collections#synchronizedList", "java.util.Collections#unmodifiableList" }) public interface List extends Collection { ... This way you give the author of the interface the opportunity to enumerate utility static methods he/she finds most appropriate. I know that this would satisfy me. Peter From pbenedict at apache.org Sat Dec 19 09:39:31 2009 From: pbenedict at apache.org (Paul Benedict) Date: Sat, 19 Dec 2009 11:39:31 -0600 Subject: Extension methods and API evolution In-Reply-To: <200912191747.56696.peter.levart@gmail.com> References: <64efa1ba0912110302g2aa55447mcd4256618492d2f2@mail.gmail.com> <4B2CCB17.4020502@the-loom.de> <200912191747.56696.peter.levart@gmail.com> Message-ID: As far as I am concerned, the only sensible use of extension methods are use-site extensions. If only the author of a class can dictate which methods can be extended (declaration-site style), the whole idea is defeated. I wouldn't mind discussing other declaration-site options, but the current proposal requires wild augmentation to the interface mechanism that I don't support. Paul On Sat, Dec 19, 2009 at 10:47 AM, Peter Levart wrote: > On Saturday 19 December 2009 13:58:16 Mikael Grev wrote: >> On Dec 19, 2009, at 13:46 PM, Stefan Schulz wrote: >> > ?And I am still >> > unconvinced about the benefit of extension methods, but maybe I missed >> > the win over static utility methods, except for being able to write >> > list.sort() instead of sort(list) >> Paul From grev at miginfocom.com Sat Dec 19 10:54:34 2009 From: grev at miginfocom.com (Mikael Grev) Date: Sat, 19 Dec 2009 19:54:34 +0100 Subject: Extension methods and API evolution In-Reply-To: <200912191747.56696.peter.levart@gmail.com> References: <64efa1ba0912110302g2aa55447mcd4256618492d2f2@mail.gmail.com> <4B2CCB17.4020502@the-loom.de> <200912191747.56696.peter.levart@gmail.com> Message-ID: Yes, I think if utility style methods are the chosen path this is a must and a good idea. It makes the learning curve less steep. It would be a good idea anyway, even if closures wasn't on the table. There's some things to work out though, like how to denote the context of the utility methods. I doubt this is something that will be considered in the scope of this spec though. Cheers, Mikael On Dec 19, 2009, at 17:47 PM, Peter Levart wrote: > On Saturday 19 December 2009 13:58:16 Mikael Grev wrote: >> On Dec 19, 2009, at 13:46 PM, Stefan Schulz wrote: >>> And I am still >>> unconvinced about the benefit of extension methods, but maybe I missed >>> the win over static utility methods, except for being able to write >>> list.sort() instead of sort(list) >> >> Having a utility method in another class breaks the logical path the >> developer has to the method. The developer has the list object and want to >> do a sort on it. There is no logical link between static utility methods >> in say Collections and the objects that they can handle. The developer >> must know this beforehand since it can't be explored with code completion >> or similar IDE aids. One can help a bit by putting "soft" references to >> classes containing utility methods in the JavaDoc, but those are not read >> by most once you've learnt the API. So chances that developers familiar >> with the List API will go back and read that soft link in Java 7 are not >> very good. >> >> So, having a method on the object itself is beneficial as it lowers the bar >> for finding out that it exist. > > A no-language-change alternative of that might be standardizing an annotation in the JDK > platform that every IDE would add support for. For example: > > package java.util; > > @UtilityMethods({ > "java.util.Collections#binarySearch", > "java.util.Collections#checkedList", > "java.util.Collections#fill", > "java.util.Collections#indexOfSubList", > "java.util.Collections#lastIndexOfSubList", > "java.util.Collections#replaceAll", > "java.util.Collections#reverse", > "java.util.Collections#rotate", > "java.util.Collections#shuffle", > "java.util.Collections#sort", > "java.util.Collections#swap", > "java.util.Collections#synchronizedList", > "java.util.Collections#unmodifiableList" > }) > public interface List extends Collection { > ... > > > This way you give the author of the interface the opportunity to enumerate utility static > methods he/she finds most appropriate. > > I know that this would satisfy me. > > Peter From schulz at the-loom.de Sat Dec 19 11:37:30 2009 From: schulz at the-loom.de (Stefan Schulz) Date: Sat, 19 Dec 2009 20:37:30 +0100 Subject: Extension methods and API evolution In-Reply-To: <200912191747.56696.peter.levart@gmail.com> References: <64efa1ba0912110302g2aa55447mcd4256618492d2f2@mail.gmail.com> <4B2CCB17.4020502@the-loom.de> <200912191747.56696.peter.levart@gmail.com> Message-ID: <4B2D2B7A.9040909@the-loom.de> Peter Levart wrote: > A no-language-change alternative of that might be standardizing an annotation in the JDK > platform that every IDE would add support for. For example: > > package java.util; > > @UtilityMethods({ > "java.util.Collections#binarySearch", > "java.util.Collections#checkedList", > "java.util.Collections#fill", > "java.util.Collections#indexOfSubList", > "java.util.Collections#lastIndexOfSubList", > "java.util.Collections#replaceAll", > "java.util.Collections#reverse", > "java.util.Collections#rotate", > "java.util.Collections#shuffle", > "java.util.Collections#sort", > "java.util.Collections#swap", > "java.util.Collections#synchronizedList", > "java.util.Collections#unmodifiableList" > }) > public interface List extends Collection { > ... While this is on declaration-site extension methods, I could think of this working for use-site extension methods as well. As IDEs need to scan and index classes anyway, this would help in finding matching use-site extensions a lot. Even better, as no String-matching is needed. For example: package java.util; public class Collections { @ExtensionMethod(List.class) public static > void sort(List list) {...} ... } Stefan From grev at miginfocom.com Sat Dec 19 12:10:30 2009 From: grev at miginfocom.com (Mikael Grev) Date: Sat, 19 Dec 2009 21:10:30 +0100 Subject: Extension methods and API evolution In-Reply-To: <4B2D2B7A.9040909@the-loom.de> References: <64efa1ba0912110302g2aa55447mcd4256618492d2f2@mail.gmail.com> <4B2CCB17.4020502@the-loom.de> <200912191747.56696.peter.levart@gmail.com> <4B2D2B7A.9040909@the-loom.de> Message-ID: This works for me as well. As long as there is a way to declare it that's ok. On Dec 19, 2009, at 20:37 PM, Stefan Schulz wrote: > Peter Levart wrote: >> A no-language-change alternative of that might be standardizing an annotation in the JDK >> platform that every IDE would add support for. For example: >> >> package java.util; >> >> @UtilityMethods({ >> "java.util.Collections#binarySearch", >> "java.util.Collections#checkedList", >> "java.util.Collections#fill", >> "java.util.Collections#indexOfSubList", >> "java.util.Collections#lastIndexOfSubList", >> "java.util.Collections#replaceAll", >> "java.util.Collections#reverse", >> "java.util.Collections#rotate", >> "java.util.Collections#shuffle", >> "java.util.Collections#sort", >> "java.util.Collections#swap", >> "java.util.Collections#synchronizedList", >> "java.util.Collections#unmodifiableList" >> }) >> public interface List extends Collection { >> ... > > While this is on declaration-site extension methods, I could think of this working for use-site extension methods as well. As IDEs need to scan and index classes anyway, this would help in finding matching use-site extensions a lot. Even better, as no String-matching is needed. For example: > > package java.util; > > public class Collections { > > @ExtensionMethod(List.class) > public static > > void sort(List list) {...} > ... > } > > Stefan From forax at univ-mlv.fr Sat Dec 19 12:34:25 2009 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Sat, 19 Dec 2009 21:34:25 +0100 Subject: Extension methods and API evolution In-Reply-To: References: <64efa1ba0912110302g2aa55447mcd4256618492d2f2@mail.gmail.com> <4B2CCB17.4020502@the-loom.de> <200912191747.56696.peter.levart@gmail.com> <4B2D2B7A.9040909@the-loom.de> Message-ID: <4B2D38D1.9080707@univ-mlv.fr> Le 19/12/2009 21:10, Mikael Grev a ?crit : > This works for me as well. As long as there is a way to declare it that's ok. > And the compiler is supposed to crawle the workspace (and the universe) to find such annotation ? cheers, R?mi > On Dec 19, 2009, at 20:37 PM, Stefan Schulz wrote: > > >> Peter Levart wrote: >> >>> A no-language-change alternative of that might be standardizing an annotation in the JDK >>> platform that every IDE would add support for. For example: >>> >>> package java.util; >>> >>> @UtilityMethods({ >>> "java.util.Collections#binarySearch", >>> "java.util.Collections#checkedList", >>> "java.util.Collections#fill", >>> "java.util.Collections#indexOfSubList", >>> "java.util.Collections#lastIndexOfSubList", >>> "java.util.Collections#replaceAll", >>> "java.util.Collections#reverse", >>> "java.util.Collections#rotate", >>> "java.util.Collections#shuffle", >>> "java.util.Collections#sort", >>> "java.util.Collections#swap", >>> "java.util.Collections#synchronizedList", >>> "java.util.Collections#unmodifiableList" >>> }) >>> public interface List extends Collection { >>> ... >>> >> While this is on declaration-site extension methods, I could think of this working for use-site extension methods as well. As IDEs need to scan and index classes anyway, this would help in finding matching use-site extensions a lot. Even better, as no String-matching is needed. For example: >> >> package java.util; >> >> public class Collections { >> >> @ExtensionMethod(List.class) >> public static> >> void sort(List list) {...} >> ... >> } >> >> Stefan >> > > From schulz at the-loom.de Sat Dec 19 12:37:33 2009 From: schulz at the-loom.de (Stefan Schulz) Date: Sat, 19 Dec 2009 21:37:33 +0100 Subject: Extension methods and API evolution In-Reply-To: <4B2D38D1.9080707@univ-mlv.fr> References: <64efa1ba0912110302g2aa55447mcd4256618492d2f2@mail.gmail.com> <4B2CCB17.4020502@the-loom.de> <200912191747.56696.peter.levart@gmail.com> <4B2D2B7A.9040909@the-loom.de> <4B2D38D1.9080707@univ-mlv.fr> Message-ID: <4B2D398D.5000002@the-loom.de> R?mi Forax wrote: > Le 19/12/2009 21:10, Mikael Grev a ?crit : >> This works for me as well. As long as there is a way to declare it that's ok. >> > > And the compiler is supposed to crawle the workspace (and the universe) > to find such annotation ? No. Why should it? It's for supporting IDEs to find extension methods and offer them for completion (including the usual auto-import stuff on selection). Stefan From grev at miginfocom.com Sun Dec 20 02:19:14 2009 From: grev at miginfocom.com (Mikael Grev) Date: Sun, 20 Dec 2009 11:19:14 +0100 Subject: Extension methods and API evolution In-Reply-To: <4B2D398D.5000002@the-loom.de> References: <64efa1ba0912110302g2aa55447mcd4256618492d2f2@mail.gmail.com> <4B2CCB17.4020502@the-loom.de> <200912191747.56696.peter.levart@gmail.com> <4B2D2B7A.9040909@the-loom.de> <4B2D38D1.9080707@univ-mlv.fr> <4B2D398D.5000002@the-loom.de> Message-ID: <8E2C1535-2897-4C59-BEA7-04C00932FF0E@miginfocom.com> > R?mi Forax wrote: >> Le 19/12/2009 21:10, Mikael Grev a ?crit : >>> This works for me as well. As long as there is a way to declare it that's ok. >>> >> >> And the compiler is supposed to crawle the workspace (and the universe) >> to find such annotation ? > > No. Why should it? It's for supporting IDEs to find extension methods > and offer them for completion (including the usual auto-import stuff on > selection). > > Stefan Exactly. As long as the bridge between the object and methods that operate on it is there I think the problem is solved. If not, there's a problem with learning curve. This solution also mean that the user of an object type can write their own utility methods which will be picked up by the IDE. Cheers, Mikael From mr at sun.com Sun Dec 20 20:30:45 2009 From: mr at sun.com (Mark Reinhold) Date: Sun, 20 Dec 2009 20:30:45 -0800 Subject: Where's the Sun Java team? Message-ID: <20091221043045.6A967484@eggemoggin.niobe.net> FYI, most of the Sun Java team is on vacation from now until 4 January. Don't mistake our silence for lack of interest -- we'll catch up in the new year. - Mark From pcj at roundroom.net Mon Dec 21 06:07:35 2009 From: pcj at roundroom.net (Peter Jones) Date: Mon, 21 Dec 2009 09:07:35 -0500 Subject: Serialization In-Reply-To: <4B295899.8080308@sun.com> References: <17b2302a0912152217mf1feac0ld5a9ed17cda82be1@mail.gmail.com> <200912161323.22403.peter.levart@marand.si> <4B28D368.5010106@optrak.co.uk> <200912161409.02274.peter.levart@marand.si> <17b2302a0912160746o49ca8dfx97427314e4c0bc3a@mail.gmail.com> <636fd28e0912161306h72104706scce3e7d4d4aeb52e@mail.gmail.com> <4B295899.8080308@sun.com> Message-ID: On Dec 16, 2009, at 5:00 PM, Tom Hawtin wrote: > > However, from a security point of view automatically serialisable > lambdas scares the hell out of me. Tom is of course quite right that automatic serializability of the classes synthesized for lambda expressions could be dreadful security- wise. This was, after all, one of the primary motivations for the requirement to implement the Serializable interface (wish it were an annotation...). People will naturally assume that these classes can only be instantiated by the enclosing class (where the lambda expression is evaluated), but keep in mind that any serializable class effectively has a public constructor (to which data from a hand-crafted stream can be passed). Expecting people to be wary of privileged code getting exposed this way seems unreasonable. So I think that serializability must require an explicit opt-in for that reason alone-- not that I have a specific suggestion for how to express it (and I would still have plenty of other concerns). -- Peter From pcj at roundroom.net Mon Dec 21 06:11:15 2009 From: pcj at roundroom.net (Peter Jones) Date: Mon, 21 Dec 2009 09:11:15 -0500 Subject: Serialization In-Reply-To: <17b2302a0912152217mf1feac0ld5a9ed17cda82be1@mail.gmail.com> References: <20091216052651.823364A0@eggemoggin.niobe.net> <17b2302a0912152217mf1feac0ld5a9ed17cda82be1@mail.gmail.com> Message-ID: Josh, I appreciate the desire-- but as you say, it's a hard problem. I suspect that the way that the serializability of a class defines, albeit obliquely, a sort of wire protocol, and the considerations for good wire protocol design (something that serialization already makes too easy to skimp on!), are somewhat fundamentally at odds with the conciseness that motivates the lambda syntax for SAM implementations. I'm not sure that this cake can be had and eaten too. I'd be happy to be shown otherwise. Cheers, -- Peter On Dec 16, 2009, at 1:17 AM, Joshua Bloch wrote: > Mark and Peter, > > This is a moderately important decision. In Google's Java MapReduce > API, we use SAM interfaces to represent Mapper and Reducer. > Instances must be serializable, as they're serialized to pass them > from the node that starts the MapReduce to the worker nodes (which > do the actual mapping and reduction). That means we won't be able to > use closure syntax for MapReduce, which seems like a shame. > > This is no worse than what we do with SAM types today, but it's no > better, either. Can we do better? > > Josh > > On Tue, Dec 15, 2009 at 9:26 PM, Mark Reinhold wrote: > > Date: Mon, 14 Dec 2009 01:23:54 -0500 > > From: Peter Jones > > > I expect that there would be the issue that is also a problem with > serializing > > instances of anonymous classes today: that the binary names of > the classes are > > neither JLS-determined nor very stable across edits/recompiles. > Serialization > > represents an object's code by its class's binary name, but these > things won't > > have overt names. Moreover, the set of a closure's serializable > fields seems > > likely to be less stable in practice compared to a normally- > declared class. > > And I don't see how you could specify any of the usual > customizations to > > serialized form or behavior (transient, readObject, etc.). What > these issues > > suggest to me is that in cases where the writing and the reading > code are from > > the exact same compilation of sources, then perhaps serialization > of closures > > could work and be useful-- but I don't see it working in the more > general case > > of communication across an API contract. > > Like I said -- serialization is tricky. Thanks Peter. > > Taken together these are good reasons not to make closures > serializable, > at least not at the outset. If there turn out to be compelling use > cases > then we could look in to making them serializable later on. > > - Mark > > From jjb at google.com Tue Dec 22 10:00:48 2009 From: jjb at google.com (Joshua Bloch) Date: Tue, 22 Dec 2009 10:00:48 -0800 Subject: Serialization In-Reply-To: References: <20091216052651.823364A0@eggemoggin.niobe.net> <17b2302a0912152217mf1feac0ld5a9ed17cda82be1@mail.gmail.com> Message-ID: <17b2302a0912221000o538a1426r55d279856482de16@mail.gmail.com> Peter, I agree with everything you way. I just wanted to point out a specific case where we do serialize function objects to show that this has practical consequences. Josh On Mon, Dec 21, 2009 at 6:11 AM, Peter Jones wrote: > Josh, > > I appreciate the desire-- but as you say, it's a hard problem. > > I suspect that the way that the serializability of a class defines, albeit > obliquely, a sort of wire protocol, and the considerations for good wire > protocol design (something that serialization already makes too easy to > skimp on!), are somewhat fundamentally at odds with the conciseness that > motivates the lambda syntax for SAM implementations. I'm not sure that this > cake can be had and eaten too. I'd be happy to be shown otherwise. > > Cheers, > -- Peter > > > > On Dec 16, 2009, at 1:17 AM, Joshua Bloch wrote: > > Mark and Peter, >> >> This is a moderately important decision. In Google's Java MapReduce API, >> we use SAM interfaces to represent Mapper and Reducer. Instances must be >> serializable, as they're serialized to pass them from the node that starts >> the MapReduce to the worker nodes (which do the actual mapping and >> reduction). That means we won't be able to use closure syntax for MapReduce, >> which seems like a shame. >> >> This is no worse than what we do with SAM types today, but it's no better, >> either. Can we do better? >> >> Josh >> >> On Tue, Dec 15, 2009 at 9:26 PM, Mark Reinhold wrote: >> > Date: Mon, 14 Dec 2009 01:23:54 -0500 >> > From: Peter Jones >> >> > I expect that there would be the issue that is also a problem with >> serializing >> > instances of anonymous classes today: that the binary names of the >> classes are >> > neither JLS-determined nor very stable across edits/recompiles. >> Serialization >> > represents an object's code by its class's binary name, but these >> things won't >> > have overt names. Moreover, the set of a closure's serializable fields >> seems >> > likely to be less stable in practice compared to a normally-declared >> class. >> > And I don't see how you could specify any of the usual customizations >> to >> > serialized form or behavior (transient, readObject, etc.). What these >> issues >> > suggest to me is that in cases where the writing and the reading code >> are from >> > the exact same compilation of sources, then perhaps serialization of >> closures >> > could work and be useful-- but I don't see it working in the more >> general case >> > of communication across an API contract. >> >> Like I said -- serialization is tricky. Thanks Peter. >> >> Taken together these are good reasons not to make closures serializable, >> at least not at the outset. If there turn out to be compelling use cases >> then we could look in to making them serializable later on. >> >> - Mark >> >> >> > From howard.lovatt at iee.org Wed Dec 23 13:06:59 2009 From: howard.lovatt at iee.org (Howard Lovatt) Date: Wed, 23 Dec 2009 21:06:59 +0000 Subject: Lambda and JSR 292 method handle In-Reply-To: <4B2BBB0E.30503@univ-mlv.fr> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <4B2B8C41.2020705@univ-mlv.fr> <3dd3f56a0912180706v383bc710o1ab4f57e24b29afb@mail.gmail.com> <4B2BBB0E.30503@univ-mlv.fr> Message-ID: <3dd3f56a0912231306m4917cd47w2d82436087f8b704@mail.gmail.com> R?mi, Sorry for not replying sooner (Christmas). Presumably the problems with using generic style annotations and erasing the actual type include: 1. Can't have two methods of the same name only distinguished by lambda type, e.g. filter( #boolean(int) ) and filter( #boolean(float) ) 2. Can't have arrays of lambdas that are type safe, e.g. new #(int)()[ n ]; // Illegal 3. Can't have instanceof tests (this might be possible since type information is carried at runtime) 4. Can't have primitive types (this might be fixable with an extension to the signature attribute) 5. Can't have static fields that are lambdas (this might be fixable with an extension to the signature attribute) Are these limitations too great? Are anonymous classes still part of 292? Merry Christmas, -- Howard. 2009/12/18 R?mi Forax : > Le 18/12/2009 16:06, Howard Lovatt a ?crit : >> >> I don't get what you are saying, probably just me being slow, so >> please bare with me. If in compilation unit A I have: >> >> void m( #int(int) f ) { out.println( f( 2 ); } >> >> and I use MethodHandle then this will get translated into: >> >> void m( MethodHandle f ) { out.println( f.invokeGeneric( 2 ) ); } >> >> Then in compilation unit B I will see the signature "void m( >> MethodHandle )", i.e. the actual types have been erased. In >> compilation unit B I can therefore say: >> >> m( #void() ); >> >> and the compiler will allow this because in compilation unit B it >> doesn't know that m really expects a #int(int) because that >> information was lost when the function type was converted to a >> MethodHandle which carries only type information at runtime not >> compiletime. >> >> What am I missing? >> > > #int(int) is kept in the bytecode in the attribute Signature > wich is extended to support function type. > > It works like with the erasure of generics: > > interface List { > boolean add(E element); > } > > the compiler translates the generics code to: > > interface List { > bolean add(Object element); > } > > and insert a special method attribute named Signature to allow > separate compilation of generics. > In the example, the value of attribute Signature of > method add(Object) is (E)Z > > If you want more info see 4.8.8 of class file format: > http://java.sun.com/docs/books/jvms/second_edition/ClassFileFormat-Java5.pdf > > So void m(#int(int) f) is erased to void m(MethodHandle) but like generics, > the attribute Signature will keep the function type, so its value will be > something like (#I(I))V > >> Thanks, >> >> -- Howard. >> > > Cheers, > R?mi > >> 2009/12/18 R?mi Forax: >> >>> >>> Le 18/12/2009 11:55, Howard Lovatt a ?crit : >>> >>>> >>>> R?mi, >>>> >>>> I thought the idea from the JSR 292 group was to use JavaMethodHandle >>>> [1] (which extends MethodHandle). The difference is that the >>>> JavaMethodHandle retains the type information, needed by Java, and it >>>> can implement interfaces so you can use a lambda with an existing >>>> function. Your example: >>>> >>>> class A { >>>> public static void main(String[] args) { >>>> #int(int) f = #(int x) (x+x); >>>> f(2); >>>> } >>>> } >>>> >>>> >>> >>> Here is what I am thinking: >>> A JavaMethodHandle is a method handle that allow you to implement one or >>> more interface. >>> One goal is to use it to implement function conversion, i.e when you want >>> to >>> use a lambda >>> as a class implementing an interface like Runnable, Callable, etc to be >>> able >>> to use legacy code. >>> Because a JavaMethodHandle is a method handle, you don't need an >>> interface >>> like CallableInitInt, >>> you already can invoke it using .invokeLambda(). >>> >>> This approach is too heavyweight for being used for 'classical' lambda >>> because it requires >>> to create a new class for each lambda. >>> >>> Some experts in JSR 292 expert group think that JavaMethodHandle aren't >>> neccessary. >>> They complexify the implementation and may disable some optimizations >>> done >>> by the VM. >>> So this feature is still under consideration. >>> >>> You can notice that function conversion (the one of the strawman proposal >>> and the one of BGGA) >>> doesn't require that the resulting object to be a lambda. >>> >>> Runnable r = #() { System.out.println("run"); } >>> #void() f = (#void()) r; // works with JavaMethodHandle but not >>> required >>> by the spec >>> >>> So function conversion can be implemented without JavaMethodHandle. >>> >>> Cheers, >>> R?mi >>> >>> >>>> >>>> Would get translated to: >>>> >>>> class A { >>>> private static final class Lambda$1 extends JavaMethodHandle >>>> implements CallableIntInt { >>>> private static final Lambda$1 instance = new Lambda$1(); >>>> @Override public int call( int x ) { return x + x; } >>>> private Lambda$1() { super "CALL"; } >>>> private static final MethodHandle CALL = >>>> MethodHandles.lookup().findVirtual( Lambda$1.class, "call", >>>> MethodHandles.methodType( int.class, int.class ) ); >>>> } >>>> public static void main(String[] args) { >>>> CallableIntInt f = Lambda$1.instance; >>>> f.call(2); >>>> } >>>> } >>>> >>>> Where CallableIntInt is either a standard interface, in java.lang say, >>>> or a synthetic interface (depending on implementation details) and is: >>>> >>>> public interface CallableIntInt { int call( int a ); } >>>> >>>> If you use a MethodHandle directly then you can't pass it to anything >>>> because you have lost the type information, i.e. an invokeGeneric on a >>>> method handle will accept any arguments (though will throw a runtime >>>> exception). EG if I have a method: >>>> >>>> void m( #int(int) f ) { out.println( f( 2 ) ); } >>>> >>>> Then if you use MethodHandles directly it would be translated to: >>>> >>>> void m( MethodHandle f ) { out.println( f.invokeGeneric( 2 ) ); } >>>> >>>> But then I could say: >>>> >>>> m( #void() () ); >>>> >>>> And the compiler couldn't catch the mistake. Using JavaMethodHandles >>>> instead, would mean m is translated into: >>>> >>>> void m( CallableIntInt f ) { out.println( f.call( 2 ) ); } >>>> >>>> And hence retains type safety. >>>> >>>> The above JavaMethodHandle version doesn't seem to be that much better >>>> than using an inner class directly! There was also, at least >>>> originally, talk of anonymous classes in JSR 292 [2]; these would seem >>>> to be more useful, are they still part of JSR 292? (I ask because I >>>> think you are on the expert group.) >>>> >>>> -- Howard. >>>> >>>> PS The above APIs are in a state of flux, I have used the versions (at >>>> least I tried to without having a compiler to check my code) from the >>>> paper you can download from [3]. >>>> >>>> Ref: >>>> [1] http://cr.openjdk.java.net/~jrose/pres/indy-javadoc-b59/ >>>> [2] http://blogs.sun.com/jrose/resource/DVMTest.java.txt >>>> [3] http://blogs.sun.com/jrose/entry/vmil_paper_on_invokedynamic >>>> >>>> >>> >>> ______________________________________________________________________ >>> This email has been scanned by the MessageLabs Email Security System. >>> For more information please visit http://www.messagelabs.com/email >>> ______________________________________________________________________ >>> >>> >> >> >> > > > ______________________________________________________________________ > This email has been scanned by the MessageLabs Email Security System. > For more information please visit http://www.messagelabs.com/email > ______________________________________________________________________ > -- -- Howard. From neal at gafter.com Wed Dec 23 13:36:11 2009 From: neal at gafter.com (Neal Gafter) Date: Wed, 23 Dec 2009 13:36:11 -0800 Subject: Lambda and JSR 292 method handle In-Reply-To: <3dd3f56a0912231306m4917cd47w2d82436087f8b704@mail.gmail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <4B2B8C41.2020705@univ-mlv.fr> <3dd3f56a0912180706v383bc710o1ab4f57e24b29afb@mail.gmail.com> <4B2BBB0E.30503@univ-mlv.fr> <3dd3f56a0912231306m4917cd47w2d82436087f8b704@mail.gmail.com> Message-ID: <15e8b9d20912231336x7aabdee1y8819973d60ff35c7@mail.gmail.com> I don't think there is an option to reify function types. That's because generics are already non-reified. In this code * #T() constant(T t) { return #() t; } * the returned lambda cannot, in principle, be reified if generics are not reified. This is independent of whether function types are mapped to interfaces, method handles, or something else. There may be issues with it, but they aren't "disadvantages" except by comparison to a scheme that does not have these issues, and no such scheme has been proposed. On Wed, Dec 23, 2009 at 1:06 PM, Howard Lovatt wrote: > Presumably the problems with using generic style annotations and erasing > the > actual type include: > > 1. Can't have two methods of the same name only distinguished by lambda > type, e.g. filter( #boolean(int) ) and filter( #boolean(float) ) > These are distinguished in CfJ, but not in a hypothetical erasure to MethodHandle. > 2. Can't have arrays of lambdas that are type safe, e.g. new #(int)()[ n > ]; // Illegal > Right. > 3. Can't have instanceof tests (this might be possible since type > information is carried at runtime) > No, type information cannot, in principle, be guaranteed to be available at runtime unless generics are reified. > 4. Can't have primitive types (this might be fixable with an extension to > the signature attribute) > 5. Can't have static fields that are lambdas (this might be fixable with > an extension to the signature attribute) > Right: the signature attributes would be extended to express function types, addressing these two issues. From mario.fusco at gmail.com Fri Dec 25 04:02:37 2009 From: mario.fusco at gmail.com (Mario Fusco) Date: Fri, 25 Dec 2009 13:02:37 +0100 Subject: Extension methods and API evolution Message-ID: <47bdb3f70912250402o3d4431do8d628d28193e4e4c@mail.gmail.com> I read that, based on the suggestions of Mark Reinhold, you already discussed (and probably excluded) the possibility to implement this feature through traits. Said that I'd find this feature really useful, even for purposes unrelated to lambda expression, I admit that it could be really hard to be implemented. Anyway I believe there is another Scala feature that could help to reach this goal in a more elegant way: implicit type conversion. I am not expert enough of the internal behaviors of the JVM to say if this feature could be easily added or not. I suppose it should be a smaller change than traits. Moreover it could be a feature more strictly related to lambda expression because the presence of both implicit type conversion and lambda expression could make the creation of internal DSLs in Java a straightforward task. I am not following this discussion from the very beginning, so I apologize if you already evaluated this option. Cheers Mario Fusco From forax at univ-mlv.fr Sun Dec 27 08:31:14 2009 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Sun, 27 Dec 2009 17:31:14 +0100 Subject: Lambda and JSR 292 method handle (a prototype) In-Reply-To: <15e8b9d20912231336x7aabdee1y8819973d60ff35c7@mail.gmail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <4B2B8C41.2020705@univ-mlv.fr> <3dd3f56a0912180706v383bc710o1ab4f57e24b29afb@mail.gmail.com> <4B2BBB0E.30503@univ-mlv.fr> <3dd3f56a0912231306m4917cd47w2d82436087f8b704@mail.gmail.com> <15e8b9d20912231336x7aabdee1y8819973d60ff35c7@mail.gmail.com> Message-ID: <4B378BD2.4060701@univ-mlv.fr> I've sketch a prototype of lambdas on top of method handle. http://weblogs.java.net/blog/forax/archive/2009/12/27/chistmas-gift The patches are here: http://cr.openjdk.java.net/~forax/lambda/ R?mi From markmahieu at googlemail.com Sun Dec 27 08:44:15 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Sun, 27 Dec 2009 16:44:15 +0000 Subject: Lambda and JSR 292 method handle (a prototype) In-Reply-To: <4B378BD2.4060701@univ-mlv.fr> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <4B2B8C41.2020705@univ-mlv.fr> <3dd3f56a0912180706v383bc710o1ab4f57e24b29afb@mail.gmail.com> <4B2BBB0E.30503@univ-mlv.fr> <3dd3f56a0912231306m4917cd47w2d82436087f8b704@mail.gmail.com> <15e8b9d20912231336x7aabdee1y8819973d60ff35c7@mail.gmail.com> <4B378BD2.4060701@univ-mlv.fr> Message-ID: <5C3A2E7B-08ED-4CB9-9C6E-35E3040DD06C@googlemail.com> Cool, but... is the patch complete? There seem to be some types missing (such as FunctionTypeTree, LambdaTree...) Cheers, Mark On 27 Dec 2009, at 16:31, R?mi Forax wrote: > I've sketch a prototype of lambdas on top of method handle. > http://weblogs.java.net/blog/forax/archive/2009/12/27/chistmas-gift > > The patches are here: > http://cr.openjdk.java.net/~forax/lambda/ > > R?mi > From neal at gafter.com Sun Dec 27 09:57:33 2009 From: neal at gafter.com (Neal Gafter) Date: Sun, 27 Dec 2009 09:57:33 -0800 Subject: Lambda and JSR 292 method handle (a prototype) In-Reply-To: <4B378BD2.4060701@univ-mlv.fr> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <4B2B8C41.2020705@univ-mlv.fr> <3dd3f56a0912180706v383bc710o1ab4f57e24b29afb@mail.gmail.com> <4B2BBB0E.30503@univ-mlv.fr> <3dd3f56a0912231306m4917cd47w2d82436087f8b704@mail.gmail.com> <15e8b9d20912231336x7aabdee1y8819973d60ff35c7@mail.gmail.com> <4B378BD2.4060701@univ-mlv.fr> Message-ID: <15e8b9d20912270957v600f49fdh439e096ea222f7ca@mail.gmail.com> R?mi- In Types.java, you seem to mark most function types as reifiable, but your mapping (erasure) does not in fact reify them. Am I missing something? Also, your selected syntax for lambda expressions would be ambiguous with shorthand invocation. The expression "lambda()(2)" can either be a lambda expression of no arguments whose result is 2, or an invocation of a method named lambda with no arguments, and then applying the resulting function value to the single argument 2. Cheers, Neal On Sun, Dec 27, 2009 at 8:31 AM, R?mi Forax wrote: > I've sketch a prototype of lambdas on top of method handle. > http://weblogs.java.net/blog/forax/archive/2009/12/27/chistmas-gift > > The patches are here: > http://cr.openjdk.java.net/~forax/lambda/ > > R?mi > > From john at milsson.nu Sun Dec 27 10:28:52 2009 From: john at milsson.nu (John Nilsson) Date: Sun, 27 Dec 2009 19:28:52 +0100 Subject: Short syntax Message-ID: In most discussions so far the syntax regarding lambdas has all been explicit. I.e. #int(int) fun = lambda(int x) (x); from R?mis proposal. Can we discuss the possibility of a short syntax, using "lifting" and inferens to produce lambads. The example above could then be something like #int(int) fun = x; or #T(T) id = x; In this example x would be treated as a free variable and thus be converted into an argument to a lambda returning its argument. I imagine that this particular example might leave to much room for error, but I'm assuming equally terse, but safer, alternatives could be designed. Another example #int(int,int) fun = +; Here the expression has no free variables but is structurally of the same type so a simple lifting to a lambda can be performed. So what do people think is this something worth aiming for? A more practical use case might be in order. Lets say you need to declare a projection of some object collection for presentation List invoices = ... theObjects.project( .getInvoiceDate(), .getCustomer().getName(), .getInvoiceNo(), .getInvoiceAmt()) Here I'm using a List project(#Object(T)...projections) letting the absent object reference signify an argument to the lifted lambdas. BR, John From peter.levart at gmail.com Sun Dec 27 10:54:49 2009 From: peter.levart at gmail.com (Peter Levart) Date: Sun, 27 Dec 2009 19:54:49 +0100 Subject: transparent lambda In-Reply-To: <5C3A2E7B-08ED-4CB9-9C6E-35E3040DD06C@googlemail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <4B378BD2.4060701@univ-mlv.fr> <5C3A2E7B-08ED-4CB9-9C6E-35E3040DD06C@googlemail.com> Message-ID: <200912271954.49628.peter.levart@gmail.com> Currently the straw-man proposal does not propose transparent lambdas. The "expression" form: #() ( expression ) is transparent but limited. It does not allow "continue, break, return" to be specified as part of expression and the "statement" form: #() { statements...; } is not transparent since it does not allow "continue, break" to transfer the control of execution out of the lambda and "return" is specified to be local (returning control to the invoker of the lambda). The "expression" lambda form can be viewed as a shorthand for: #() { return expression; } So what straw-man actually proposes is a form that is not much different from anonymous inner implementations of SAM interfaces with shorter syntax. The question is: Are we settling for less? Will we regret it in the future? The answer in my opinion is: Yes, if we use the syntax now for non-transparent form, Java will never get real transparent lambdas. On the other hand, there is Neal's CfJ proposal that in essence (0.6a) is not much different (though much more complete) to straw-man. It has the "expression lambda" form: #() expression // note the absence of parentheses and the "statement lambda" form: #() { statements...; } The "expression lambda" form is specified to be transparent. The extended proposal (0.6b) specifies the so called "block expression" that allows statements to precede final expression. Statements in block expression can contain "break, continue, return" that, when used in "expression lambda" transfer control transparently to non-local locations out of the lambda. But the "statement lambda" form is still specified as non-transparent form. So we have two forms, using two syntax variations and two different behaviors. If we have two forms, the transparent and non-transparent one, why do we need the non- transparent at all? Is it because non-transparent form allows early local returns, so the code can be structured more naturally like inside the method? I don't see any other reason. (BGGA specification allowed APIs to specify that they only accept "restricted" (non-transparent) closures. Current specifications don't have any provision for that. My opinion is that this was a complication that was not needed.) If the only reason for non-transparent forms is that they allow local returns, then maybe, instead of having two lambda forms, we only keep the transparent one (expression lambda) and add something like the following: (see attached HTML) Please note that there may be errors in the attached document. If you spot some, please report them. Regards, Peter From forax at univ-mlv.fr Sun Dec 27 11:05:03 2009 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Sun, 27 Dec 2009 20:05:03 +0100 Subject: Lambda and JSR 292 method handle (a prototype) In-Reply-To: <5C3A2E7B-08ED-4CB9-9C6E-35E3040DD06C@googlemail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <4B2B8C41.2020705@univ-mlv.fr> <3dd3f56a0912180706v383bc710o1ab4f57e24b29afb@mail.gmail.com> <4B2BBB0E.30503@univ-mlv.fr> <3dd3f56a0912231306m4917cd47w2d82436087f8b704@mail.gmail.com> <15e8b9d20912231336x7aabdee1y8819973d60ff35c7@mail.gmail.com> <4B378BD2.4060701@univ-mlv.fr> <5C3A2E7B-08ED-4CB9-9C6E-35E3040DD06C@googlemail.com> Message-ID: <4B37AFDF.2040206@univ-mlv.fr> Le 27/12/2009 17:44, Mark Mahieu a ?crit : > Cool, but... is the patch complete? There seem to be some types missing (such as FunctionTypeTree, LambdaTree...) > > Cheers, > > Mark > > oups, Should be better now. R?mi > On 27 Dec 2009, at 16:31, R?mi Forax wrote: > > >> I've sketch a prototype of lambdas on top of method handle. >> http://weblogs.java.net/blog/forax/archive/2009/12/27/chistmas-gift >> >> The patches are here: >> http://cr.openjdk.java.net/~forax/lambda/ >> >> R?mi >> >> > From peter.levart at gmail.com Sun Dec 27 11:14:45 2009 From: peter.levart at gmail.com (Peter Levart) Date: Sun, 27 Dec 2009 20:14:45 +0100 Subject: transparent lambda In-Reply-To: <200912271954.49628.peter.levart@gmail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <5C3A2E7B-08ED-4CB9-9C6E-35E3040DD06C@googlemail.com> <200912271954.49628.peter.levart@gmail.com> Message-ID: <200912272014.45257.peter.levart@gmail.com> On Sunday 27 December 2009 19:54:49 Peter Levart wrote: > (see attached HTML) > I see that listprocessor ate my HTML attachment. I'm including it here in-line: BlockExpression A block expression is one of Primary (15.8) expressions. It is syntactically equivalent to Block (14.2) but appears in expression contexts. BlockExpression: Block Block: { BlockStatementsopt } BlockStatements: BlockStatement BlockStatements BlockStatement BlockStatement: LocalVariableDeclarationStatement ClassDeclaration Statement A block consists of Statements (14.5). One class of statements is a StatementWithoutTrailingSubstatement. We extend it's definition to include another form of statement called LocalYieldStatement: StatementWithoutTrailingSubstatement: Block EmptyStatement ExpressionStatement AssertStatement SwitchStatement DoStatement BreakStatement ContinueStatement ReturnStatement SynchronizedStatement ThrowStatement TryStatement LocalYieldStatement LocalYieldStatement: = Expressionopt ; Local yield statement is only valid if the innermost containing syntactical construct of the following constructs: ClassDeclaration ClassBody (of the ClassInstanceCreationExpression) BlockExpression is a BlockExpression. It's a compile-timer error if it appears anywhere else. Any local yield statement is said to belong to the innermost block expression in which it appears. All local yield statements that belong to a particular block expression constitute the block expression's set of local yield statements. It is a compile-time error if there are both local yield statements with Expression and local yield statements with no Expression present in the block expression's set of local yield statements. It is a compile-time error if there are any local yield statements with Expression present in the block expression's set of local yield statements and last block statement can complete normally. A local yield statement with no Expression attempts to transfer control to the evaluator of the block expression that contains it. To be precise, a local yield statement with no Expression always completes abruptly, the reason being a local yield with value null. A local yield statement with an Expression attempts to transfer control to the evaluator of the block expression that contains it; the value of the Expression becomes the value of the block expression. More precisely, execution of such a local yield statement first evaluates the Expression. If the evaluation of the Expression completes abruptly for some reason, then the local yield statement completes abruptly for that reason. If evaluation of the Expression completes normally, producing a value V, then the local yield statement completes abruptly, the reason being a local yield with value V. A block expression is evaluated by executing each of the block statements in order from first to last (left to right). If any of block statements complete abruptly for any reason except for a local yield, then no further actions are performed and the block expression completes abruptly for the same reason. If any block statements complete abruptly and the reason is a local yield with value V, then no further actions are performed and the block expression attempts to complete normally, producing value V converted to the type of block expression (see below). If last block expression statement completes normally then block expression completes normally, producing the value null. The type of block expression is: Nothing if there are no reachable local yield statements in the block expression's set of local yield statements and the last block statement can not complete normally; otherwise Void if there are no local yield statements with Expression present in the block expression's set of local yield statements; otherwise A reduction of the types of all Expressions of local yield statements in the block expression's set of local yield statements using the reduction function defined as follows: Let T1 and T2 be two types. The reduction of types T1 and T2 is the type of ConditionalExpression defined by JLS (15.25) where T1 and T2 represent the types of second and third operands of conditional operator ? : The preceding descriptions of local yield statement say "attempts to transfer control" rather than just "transfers control" because if there are any try statements (14.20) within the block expression whose try blocks contain the local yield statement, then any finally clauses of those try statements will be executed, in order, innermost to outermost, before control is transferred to the evaluator of block expression. Abrupt completion of a finally clause can disrupt the transfer of control initiated by a local yield statement. ... Examples: String s = ...; char c = ...; int firstIndex = { for (int i = 0; i < s.length(); i++) if (s.charAt(i) == c) =i; =-1; }; From peter.levart at gmail.com Sun Dec 27 11:22:30 2009 From: peter.levart at gmail.com (Peter Levart) Date: Sun, 27 Dec 2009 20:22:30 +0100 Subject: transparent lambda In-Reply-To: <200912271954.49628.peter.levart@gmail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <5C3A2E7B-08ED-4CB9-9C6E-35E3040DD06C@googlemail.com> <200912271954.49628.peter.levart@gmail.com> Message-ID: <200912272022.30180.peter.levart@gmail.com> On Sunday 27 December 2009 19:54:49 Peter Levart wrote: > (see attached HTML) > Please disregard the attempted-to-be-in-line-HTML message posted previously, and rather navigate this link: http://docs.google.com/View?id=df7j62rs_42zrcz5g6 I hope now the form is correct. But do read my 1st message (without the attachment) since it provides the context. Regards, Peter From neal at gafter.com Sun Dec 27 12:28:51 2009 From: neal at gafter.com (Neal Gafter) Date: Sun, 27 Dec 2009 12:28:51 -0800 Subject: transparent lambda In-Reply-To: <200912272022.30180.peter.levart@gmail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <5C3A2E7B-08ED-4CB9-9C6E-35E3040DD06C@googlemail.com> <200912271954.49628.peter.levart@gmail.com> <200912272022.30180.peter.levart@gmail.com> Message-ID: <15e8b9d20912271228v2aa01918nc9786a1fdf68fff5@mail.gmail.com> Your block expression is syntactically ambiguous with an array initializer, and probably also ambiguous with Coin's proposed collection literals. The yield syntax does not look good to me. I think it would be hard to notice, scanning the code, that there is an early termination, and the target of the early termination is also hard to notice. Instead of writing this * * *#int(int,int) zeroesComeFirst = #(int x, int y) {* * if (x == y) return 0;* * if (x == 0) return -1;* * if (y == 0) return 1;* * return (x < y) ? -1 : 1; }* one would write *#int(int,int) zeroesComeFirst = #(int x, int y) {* * if (x == y) =0;* * if (x == 0) =-1;* * if (y == 0) =1;* * =(x < y) ? -1 : 1; }* Worse, your proposal breaks transparency. That is explained in detail in < http://gafter.blogspot.com/2006/08/tennents-correspondence-principle-and.html>, but to spell it out, one would like the specification for a lambda to be defined such that taking a statement *stmt* and wrapping it in a lambda an then executing it *(#() { stmt }).invoke();* have the same meaning, no matter what the context. However, under your specification they do not. Consider the code *#() { =3; }* this is a lambda expression that returns an integer (3). Now take the statement =3; and wrap it in a lambda, executing it immediately: * #() { (#() { =3; }).invoke(); }* This has changed the enclosing expression from a lambda that returns an integer (3) into a lambda expression that returns no result. Cheers, Neal On Sun, Dec 27, 2009 at 11:22 AM, Peter Levart wrote: > On Sunday 27 December 2009 19:54:49 Peter Levart wrote: > > (see attached HTML) > > > > Please disregard the attempted-to-be-in-line-HTML message posted > previously, and rather navigate > this link: > > http://docs.google.com/View?id=df7j62rs_42zrcz5g6 > > I hope now the form is correct. > > But do read my 1st message (without the attachment) since it provides the > context. > > Regards, Peter > > From forax at univ-mlv.fr Sun Dec 27 12:33:27 2009 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Sun, 27 Dec 2009 21:33:27 +0100 Subject: Lambda and JSR 292 method handle (a prototype) In-Reply-To: <15e8b9d20912270957v600f49fdh439e096ea222f7ca@mail.gmail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <4B2B8C41.2020705@univ-mlv.fr> <3dd3f56a0912180706v383bc710o1ab4f57e24b29afb@mail.gmail.com> <4B2BBB0E.30503@univ-mlv.fr> <3dd3f56a0912231306m4917cd47w2d82436087f8b704@mail.gmail.com> <15e8b9d20912231336x7aabdee1y8819973d60ff35c7@mail.gmail.com> <4B378BD2.4060701@univ-mlv.fr> <15e8b9d20912270957v600f49fdh439e096ea222f7ca@mail.gmail.com> Message-ID: <4B37C497.1010109@univ-mlv.fr> Le 27/12/2009 18:57, Neal Gafter a ?crit : > R?mi- > > In Types.java, you seem to mark most function types as reifiable, but > your mapping (erasure) does not in fact reify them. Am I missing > something? It's a prototype. What I would like is to implement instantiation of generics in function type as a conversion that will create a new reified lambda from a generic non refied lambda. But I haven't yet implement it. I think there is also a problem with array of function types because they should not be reifiable. > > Also, your selected syntax for lambda expressions would be ambiguous > with shorthand invocation. The expression "lambda()(2)" can either be > a lambda expression of no arguments whose result is 2, or an > invocation of a method named lambda with no arguments, and then > applying the resulting function value to the single argument 2. No, because the prototype use .invoke() to call a function type. lambda()(2) is a lambda expression that return 2. An invocation of a method named lambda with no argument that return a function type should use invoke: private static #void(int) lambda() { return lambda(int x) { System.out.println(x); }; } lambda().invoke(2); > > Cheers, > Neal Cheers, R?mi > > On Sun, Dec 27, 2009 at 8:31 AM, R?mi Forax > wrote: > > I've sketch a prototype of lambdas on top of method handle. > http://weblogs.java.net/blog/forax/archive/2009/12/27/chistmas-gift > > The patches are here: > http://cr.openjdk.java.net/~forax/lambda/ > > > R?mi > > From peter.levart at gmail.com Mon Dec 28 03:38:30 2009 From: peter.levart at gmail.com (Peter Levart) Date: Mon, 28 Dec 2009 12:38:30 +0100 Subject: transparent lambda In-Reply-To: <15e8b9d20912271228v2aa01918nc9786a1fdf68fff5@mail.gmail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <5C3A2E7B-08ED-4CB9-9C6E-35E3040DD06C@googlemail.com> <200912271954.49628.peter.levart@gmail.com> <200912272022.30180.peter.levart@gmail.com> <15e8b9d20912271228v2aa01918nc9786a1fdf68fff5@mail.gmail.com> Message-ID: On Sun, Dec 27, 2009 at 9:28 PM, Neal Gafter wrote: > Your block expression is syntactically ambiguous with an array initializer, > and probably also ambiguous with Coin's proposed collection literals. > Oh yes, array initializer. But only if *Block*Expression vs. * ArrayInitializer* is empty, isn't it? Since empty BlockExpression is meaningless, the syntax could be fixed from this: *BlockExpression**:* * Block* * Block:* {* BlockStatements**opt* } to something like this: *BlockExpression**:* {* BlockStatements* } The yield syntax does not look good to me. I think it would be hard to > notice, scanning the code, that there is an early termination, and the > target of the early termination is also hard to notice. Instead of writing > this > * > * > *#int(int,int) zeroesComeFirst = #(int x, int y) {* > * if (x == y) return 0;* > * if (x == 0) return -1;* > * if (y == 0) return 1;* > * return (x < y) ? -1 : 1; }* > > one would write > > *#int(int,int) zeroesComeFirst = #(int x, int y) {* > * if (x == y) =0;* > * if (x == 0) =-1;* > * if (y == 0) =1;* > * =(x < y) ? -1 : 1; }* > I agree about the hard to notice objection (vivid colouring in IDE would help here). That was an attempt to not introduce a new keyword. With a keyword like "yield" it would be no different from "return" - for the price of new keyword, of course. But what did you mean with: "and the target of the early termination is also hard to notice"? Did you mean in situations when BlockExpression was used as part of other expressions - not as the expression in "expression lambda"? When used in expression lambda, the target of early termination has the same notice-ability as the target of early termination (return) in CfJ's statement lambdas. In other situations, nesting normal statement blocks and expression blocks would lower notice-ability of early termination target - to a much lesser extent that same is true for nesting CfJ's statement lambdas. Maybe BlockExpression, as suggested, doesn't have that much value in itself - only in company with expression lambdas. Maybe there should be two forms of lambdas: expression lambda and statement lambda. But: > > Worse, your proposal breaks transparency. That is explained in detail in < > http://gafter.blogspot.com/2006/08/tennents-correspondence-principle-and.html>, > ... Being able to return early from a lambda has inherent conflicts with lambda transparency since it targets lambda's bounds - lambda becomes visible. In spite of that, I think (but I may be persuaded to think otherwise) that it is possible to combine transparency to other constructs and "additional features" like early return (that break Tennent's principle) in one form, provided that those additional features use unique statement forms - re-usage of same statements (return, break, continue) among different kinds of constructs is not allowed. That single lambda form is mostly transparent. Non-transparency is obvious only when you nest same kind of constructs - features that target those kinds then select the innermost one. That's true with loops and methods in Java today - they are not transparent to their own kind. I have read your blog (above link) where you say: "while *existing* code doesn't use this new statement form, once we introduce it into the language we should expect people to start using it in *new* code. And once they do, any code that includes this statement cannot be wrapped in a closure without changing its meaning. Once we identified the bad smell this way, it wasn't hard to come up with realistic examples where it gets in the way of using the language." What realistic example did you have in mind? Does it get in the way of using the language any more than when you try to use nested loops with unlabeled break/continue? Regards, Peter From neal at gafter.com Mon Dec 28 08:25:13 2009 From: neal at gafter.com (Neal Gafter) Date: Mon, 28 Dec 2009 08:25:13 -0800 Subject: transparent lambda In-Reply-To: References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <5C3A2E7B-08ED-4CB9-9C6E-35E3040DD06C@googlemail.com> <200912271954.49628.peter.levart@gmail.com> <200912272022.30180.peter.levart@gmail.com> <15e8b9d20912271228v2aa01918nc9786a1fdf68fff5@mail.gmail.com> Message-ID: <15e8b9d20912280825j51f5f272s504f776d02cd2c2b@mail.gmail.com> I'm moving this conversation to the closures-dev mailing list. From alex.blewitt at gmail.com Mon Dec 28 08:50:20 2009 From: alex.blewitt at gmail.com (Alex Blewitt) Date: Mon, 28 Dec 2009 16:50:20 +0000 Subject: transparent lambda In-Reply-To: <15e8b9d20912280825j51f5f272s504f776d02cd2c2b@mail.gmail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <5C3A2E7B-08ED-4CB9-9C6E-35E3040DD06C@googlemail.com> <200912271954.49628.peter.levart@gmail.com> <200912272022.30180.peter.levart@gmail.com> <15e8b9d20912271228v2aa01918nc9786a1fdf68fff5@mail.gmail.com> <15e8b9d20912280825j51f5f272s504f776d02cd2c2b@mail.gmail.com> Message-ID: What/where's the closures-dev mailing list? Sent from my (new) iPhone On 28 Dec 2009, at 16:25, Neal Gafter wrote: > I'm moving this conversation to the closures-dev mailing list. > From neal at gafter.com Mon Dec 28 09:13:03 2009 From: neal at gafter.com (Neal Gafter) Date: Mon, 28 Dec 2009 09:13:03 -0800 Subject: transparent lambda In-Reply-To: References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <5C3A2E7B-08ED-4CB9-9C6E-35E3040DD06C@googlemail.com> <200912271954.49628.peter.levart@gmail.com> <200912272022.30180.peter.levart@gmail.com> <15e8b9d20912271228v2aa01918nc9786a1fdf68fff5@mail.gmail.com> <15e8b9d20912280825j51f5f272s504f776d02cd2c2b@mail.gmail.com> Message-ID: <15e8b9d20912280913l2dffbc71s14ab06db9cab3cde@mail.gmail.com> On Mon, Dec 28, 2009 at 8:50 AM, Alex Blewitt wrote: > What/where's the closures-dev mailing list? > See the openjdk closures project page: http://openjdk.java.net/projects/closures/ You can subscribe here: http://mail.openjdk.java.net/mailman/listinfo/closures-dev The closures-dev mailing list is being used to discuss the specifications found at http://www.javac.info/, the latest iteration of which corresponds to the Lambda strawman, but includes transparent lambdas and constrol abstraction. Cheers, Neal From howard.lovatt at iee.org Tue Dec 29 14:50:04 2009 From: howard.lovatt at iee.org (Howard Lovatt) Date: Tue, 29 Dec 2009 22:50:04 +0000 Subject: Lambda and JSR 292 method handle In-Reply-To: <15e8b9d20912231336x7aabdee1y8819973d60ff35c7@mail.gmail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <4B2B8C41.2020705@univ-mlv.fr> <3dd3f56a0912180706v383bc710o1ab4f57e24b29afb@mail.gmail.com> <4B2BBB0E.30503@univ-mlv.fr> <3dd3f56a0912231306m4917cd47w2d82436087f8b704@mail.gmail.com> <15e8b9d20912231336x7aabdee1y8819973d60ff35c7@mail.gmail.com> Message-ID: <3dd3f56a0912291450s770c5e42wfc2aca6855dc39cf@mail.gmail.com> You could reify lambda's, see: http://www.artima.com/weblogs/viewpost.jsp?thread=277879 for details. This would solve many of the erasure 'issues'. But as Neal's example shows, not in all cases. 2009/12/23 Neal Gafter > I don't think there is an option to reify function types. That's because > generics are already non-reified. In this code > > * #T() constant(T t) { > return #() t; > } > * > > the returned lambda cannot, in principle, be reified if generics are not > reified. This is independent of whether function types are mapped to > interfaces, method handles, or something else. There may be issues with it, > but they aren't "disadvantages" except by comparison to a scheme that does > not have these issues, and no such scheme has been proposed. > > > On Wed, Dec 23, 2009 at 1:06 PM, Howard Lovatt wrote: > >> Presumably the problems with using generic style annotations and erasing >> the >> actual type include: >> >> 1. Can't have two methods of the same name only distinguished by lambda >> >> type, e.g. filter( #boolean(int) ) and filter( #boolean(float) ) >> > > These are distinguished in CfJ, but not in a hypothetical erasure to > MethodHandle. > > >> 2. Can't have arrays of lambdas that are type safe, e.g. new #(int)()[ n >> ]; // Illegal >> > > Right. > > >> 3. Can't have instanceof tests (this might be possible since type >> >> information is carried at runtime) >> > > No, type information cannot, in principle, be guaranteed to be available at > runtime unless generics are reified. > > >> 4. Can't have primitive types (this might be fixable with an extension >> to >> the signature attribute) >> 5. Can't have static fields that are lambdas (this might be fixable with >> >> an extension to the signature attribute) >> > > Right: the signature attributes would be extended to express function > types, addressing these two issues. > > > ______________________________________________________________________ > This email has been scanned by the MessageLabs Email Security System. > For more information please visit http://www.messagelabs.com/email > ______________________________________________________________________ > -- -- Howard. From neal at gafter.com Tue Dec 29 15:19:50 2009 From: neal at gafter.com (Neal Gafter) Date: Tue, 29 Dec 2009 15:19:50 -0800 Subject: Lambda and JSR 292 method handle In-Reply-To: <3dd3f56a0912291450s770c5e42wfc2aca6855dc39cf@mail.gmail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <4B2B8C41.2020705@univ-mlv.fr> <3dd3f56a0912180706v383bc710o1ab4f57e24b29afb@mail.gmail.com> <4B2BBB0E.30503@univ-mlv.fr> <3dd3f56a0912231306m4917cd47w2d82436087f8b704@mail.gmail.com> <15e8b9d20912231336x7aabdee1y8819973d60ff35c7@mail.gmail.com> <3dd3f56a0912291450s770c5e42wfc2aca6855dc39cf@mail.gmail.com> Message-ID: <15e8b9d20912291519l4c51c26bg93352bcfc76cca71@mail.gmail.com> There are a number of fatal problems with this approach. The worst is that you can't use any explicit code to implement subtype conversions because they don't work through generics. For example, your scheme does not provide any way to convert a value of type *List* to a value of type *List* This conversion is just as important as the conversion on the underlying function types. Also, there need to be subtype relations in both directions between your * Callable$0* and *Callable$String* but that is impossible because they are distinct interfaces. If you try to provide the subtype relations in just one direction, things quicky get out of hand (i.e. an exponential explosion in direct superinterfaces of the generated interfaces) when there are multiple lambda arguments. Cheers, Neal On Tue, Dec 29, 2009 at 2:50 PM, Howard Lovatt wrote: > You could reify lambda's, see: > > http://www.artima.com/weblogs/viewpost.jsp?thread=277879 > > for details. This would solve many of the erasure 'issues'. But as Neal's > example shows, not in all cases. > > 2009/12/23 Neal Gafter > >> I don't think there is an option to reify function types. That's >> because generics are already non-reified. In this code >> >> * #T() constant(T t) { >> return #() t; >> } >> * >> >> the returned lambda cannot, in principle, be reified if generics are not >> reified. This is independent of whether function types are mapped to >> interfaces, method handles, or something else. There may be issues with it, >> but they aren't "disadvantages" except by comparison to a scheme that does >> not have these issues, and no such scheme has been proposed. >> >> >> On Wed, Dec 23, 2009 at 1:06 PM, Howard Lovatt wrote: >> >>> Presumably the problems with using generic style annotations and erasing >>> the >>> actual type include: >>> >>> 1. Can't have two methods of the same name only distinguished by lambda >>> >>> type, e.g. filter( #boolean(int) ) and filter( #boolean(float) ) >>> >> >> These are distinguished in CfJ, but not in a hypothetical erasure to >> MethodHandle. >> >> >>> 2. Can't have arrays of lambdas that are type safe, e.g. new #(int)()[ >>> n >>> ]; // Illegal >>> >> >> Right. >> >> >>> 3. Can't have instanceof tests (this might be possible since type >>> >>> information is carried at runtime) >>> >> >> No, type information cannot, in principle, be guaranteed to be available >> at runtime unless generics are reified. >> >> >>> 4. Can't have primitive types (this might be fixable with an extension >>> to >>> the signature attribute) >>> 5. Can't have static fields that are lambdas (this might be fixable >>> with >>> >>> an extension to the signature attribute) >>> >> >> Right: the signature attributes would be extended to express function >> types, addressing these two issues. >> >> >> ______________________________________________________________________ >> This email has been scanned by the MessageLabs Email Security System. >> For more information please visit http://www.messagelabs.com/email >> ______________________________________________________________________ >> > > > > -- > -- Howard. > From howard.lovatt at iee.org Tue Dec 29 23:32:08 2009 From: howard.lovatt at iee.org (Howard Lovatt) Date: Wed, 30 Dec 2009 07:32:08 +0000 Subject: Lambda and JSR 292 method handle In-Reply-To: <15e8b9d20912291519l4c51c26bg93352bcfc76cca71@mail.gmail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <4B2B8C41.2020705@univ-mlv.fr> <3dd3f56a0912180706v383bc710o1ab4f57e24b29afb@mail.gmail.com> <4B2BBB0E.30503@univ-mlv.fr> <3dd3f56a0912231306m4917cd47w2d82436087f8b704@mail.gmail.com> <15e8b9d20912231336x7aabdee1y8819973d60ff35c7@mail.gmail.com> <3dd3f56a0912291450s770c5e42wfc2aca6855dc39cf@mail.gmail.com> <15e8b9d20912291519l4c51c26bg93352bcfc76cca71@mail.gmail.com> Message-ID: <3dd3f56a0912292332rd7be44br3f072a7d48d937f2@mail.gmail.com> Neal, Good points, the first: > > List > > to a value of type > > List > Is easily fixable by having the reified versions extend the generic versions with a special case for primitives, i.e.: *public* *abstract* *class* Callable$Int *implements* Callable$0 { *public* *abstract* *int* callInt(); @Override *public* *final* Integer call() { *return* callInt(); }} > Also, there need to be subtype relations in both > directions between your Callable$0 and > Callable$String but that is impossible because they are > distinct interfaces. If you try to provide the subtype > relations in just one direction, things quicky get out of > hand (i.e. an exponential explosion in direct > superinterfaces of the generated interfaces) when there > are multiple lambda arguments. The above modification to implement Callable$... solves this problem in one direction and the other is via 'cast' methods. The idea was that the 'cast' methods are loader generated, though re-reading my post I didn't make this clear (sorry). I am making the assumption that these 'casts' are rare and therefore in practice you won't get an explosion of 'cast' methods. -- Howard. 2009/12/29 Neal Gafter > There are a number of fatal problems with this approach. The worst is that > you can't use any explicit code to implement subtype conversions because > they don't work through generics. For example, your scheme does not provide > any way to convert a value of type > > *List* > > to a value of type > > *List* > > This conversion is just as important as the conversion on the underlying > function types. > > Also, there need to be subtype relations in both directions between your * > Callable$0* and *Callable$String* but that is impossible because > they are distinct interfaces. If you try to provide the subtype relations > in just one direction, things quicky get out of hand (i.e. an exponential > explosion in direct superinterfaces of the generated interfaces) when there > are multiple lambda arguments. > > Cheers, > Neal > > > On Tue, Dec 29, 2009 at 2:50 PM, Howard Lovatt wrote: > >> You could reify lambda's, see: >> >> http://www.artima.com/weblogs/viewpost.jsp?thread=277879 >> >> for details. This would solve many of the erasure 'issues'. But as Neal's >> example shows, not in all cases. >> >> 2009/12/23 Neal Gafter >> >>> I don't think there is an option to reify function types. That's >>> because generics are already non-reified. In this code >>> >>> * #T() constant(T t) { >>> return #() t; >>> } >>> * >>> >>> the returned lambda cannot, in principle, be reified if generics are not >>> reified. This is independent of whether function types are mapped to >>> interfaces, method handles, or something else. There may be issues with it, >>> but they aren't "disadvantages" except by comparison to a scheme that does >>> not have these issues, and no such scheme has been proposed. >>> >>> >>> On Wed, Dec 23, 2009 at 1:06 PM, Howard Lovatt wrote: >>> >>>> Presumably the problems with using generic style annotations and >>>> erasing the >>>> actual type include: >>>> >>>> 1. Can't have two methods of the same name only distinguished by >>>> lambda >>>> >>>> type, e.g. filter( #boolean(int) ) and filter( #boolean(float) ) >>>> >>> >>> These are distinguished in CfJ, but not in a hypothetical erasure to >>> MethodHandle. >>> >>> >>>> 2. Can't have arrays of lambdas that are type safe, e.g. new #(int)()[ >>>> n >>>> ]; // Illegal >>>> >>> >>> Right. >>> >>> >>>> 3. Can't have instanceof tests (this might be possible since type >>>> >>>> information is carried at runtime) >>>> >>> >>> No, type information cannot, in principle, be guaranteed to be available >>> at runtime unless generics are reified. >>> >>> >>>> 4. Can't have primitive types (this might be fixable with an extension >>>> to >>>> the signature attribute) >>>> 5. Can't have static fields that are lambdas (this might be fixable >>>> with >>>> >>>> an extension to the signature attribute) >>>> >>> >>> Right: the signature attributes would be extended to express function >>> types, addressing these two issues. >>> >>> >>> ______________________________________________________________________ >>> This email has been scanned by the MessageLabs Email Security System. >>> For more information please visit http://www.messagelabs.com/email >>> ______________________________________________________________________ >>> >> >> >> >> -- >> -- Howard. >> > > > ______________________________________________________________________ > This email has been scanned by the MessageLabs Email Security System. > For more information please visit http://www.messagelabs.com/email > ______________________________________________________________________ > -- -- Howard. From tronicek at fit.cvut.cz Wed Dec 30 00:12:40 2009 From: tronicek at fit.cvut.cz (tronicek at fit.cvut.cz) Date: Wed, 30 Dec 2009 09:12:40 +0100 Subject: Lambda and JSR 292 method handle In-Reply-To: <3dd3f56a0912292332rd7be44br3f072a7d48d937f2@mail.gmail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <4B2B8C41.2020705@univ-mlv.fr> <3dd3f56a0912180706v383bc710o1ab4f57e24b29afb@mail.gmail.com> <4B2BBB0E.30503@univ-mlv.fr> <3dd3f56a0912231306m4917cd47w2d82436087f8b704@mail.gmail.com> <15e8b9d20912231336x7aabdee1y8819973d60ff35c7@mail.gmail.com> <3dd3f56a0912291450s770c5e42wfc2aca6855dc39cf@mail.gmail.com> <15e8b9d20912291519l4c51c26bg93352bcfc76cca71@mail.gmail.com> <3dd3f56a0912292332rd7be44br3f072a7d48d937f2@mail.gmail.com> Message-ID: Howard, could you elaborate this a bit? I can imagine the types which extend the parameterized types. But I do not see how you want the compiler to use them to check the relation between >> List and >> List Concerning the 'cast' method, it is useful at runtime. But how do you want to check the relation between Callable$0 and Callable$String in compiler? Z. -- Zdenek Tronicek FIT CTU in Prague Howard Lovatt napsal(a): > Neal, > > Good points, the first: > >> > >> List >> > > >> to a value of type >> > >> List >> > > > > Is easily fixable by having the reified versions extend the generic > versions > with a special case for primitives, i.e.: > > *public* *abstract* *class* Callable$Int *implements* Callable$0 > { > *public* *abstract* *int* callInt(); > @Override *public* *final* Integer call() { *return* callInt(); }} > > > >> Also, there need to be subtype relations in both >> directions between your Callable$0 and >> Callable$String but that is impossible because they are >> distinct interfaces. If you try to provide the subtype >> relations in just one direction, things quicky get out of >> hand (i.e. an exponential explosion in direct >> superinterfaces of the generated interfaces) when there >> are multiple lambda arguments. > > The above modification to implement Callable$... solves this problem in > one > direction and the other is via 'cast' methods. The idea was that the > 'cast' > methods are loader generated, though re-reading my post I didn't make this > clear (sorry). > > I am making the assumption that these 'casts' are rare and therefore in > practice you won't get an explosion of 'cast' methods. > > -- Howard. > > 2009/12/29 Neal Gafter > >> There are a number of fatal problems with this approach. The worst is >> that >> you can't use any explicit code to implement subtype conversions because >> they don't work through generics. For example, your scheme does not >> provide >> any way to convert a value of type >> >> *List* >> >> to a value of type >> >> *List* >> >> This conversion is just as important as the conversion on the underlying >> function types. >> >> Also, there need to be subtype relations in both directions between your >> * >> Callable$0* and *Callable$String* but that is impossible because >> they are distinct interfaces. If you try to provide the subtype >> relations >> in just one direction, things quicky get out of hand (i.e. an >> exponential >> explosion in direct superinterfaces of the generated interfaces) when >> there >> are multiple lambda arguments. >> >> Cheers, >> Neal >> >> >> On Tue, Dec 29, 2009 at 2:50 PM, Howard Lovatt >> wrote: >> >>> You could reify lambda's, see: >>> >>> http://www.artima.com/weblogs/viewpost.jsp?thread=277879 >>> >>> for details. This would solve many of the erasure 'issues'. But as >>> Neal's >>> example shows, not in all cases. >>> >>> 2009/12/23 Neal Gafter >>> >>>> I don't think there is an option to reify function types. That's >>>> because generics are already non-reified. In this code >>>> >>>> * #T() constant(T t) { >>>> return #() t; >>>> } >>>> * >>>> >>>> the returned lambda cannot, in principle, be reified if generics are >>>> not >>>> reified. This is independent of whether function types are mapped to >>>> interfaces, method handles, or something else. There may be issues >>>> with it, >>>> but they aren't "disadvantages" except by comparison to a scheme that >>>> does >>>> not have these issues, and no such scheme has been proposed. >>>> >>>> >>>> On Wed, Dec 23, 2009 at 1:06 PM, Howard Lovatt >>>> wrote: >>>> >>>>> Presumably the problems with using generic style annotations and >>>>> erasing the >>>>> actual type include: >>>>> >>>>> 1. Can't have two methods of the same name only distinguished by >>>>> lambda >>>>> >>>>> type, e.g. filter( #boolean(int) ) and filter( #boolean(float) ) >>>>> >>>> >>>> These are distinguished in CfJ, but not in a hypothetical erasure to >>>> MethodHandle. >>>> >>>> >>>>> 2. Can't have arrays of lambdas that are type safe, e.g. new >>>>> #(int)()[ >>>>> n >>>>> ]; // Illegal >>>>> >>>> >>>> Right. >>>> >>>> >>>>> 3. Can't have instanceof tests (this might be possible since type >>>>> >>>>> information is carried at runtime) >>>>> >>>> >>>> No, type information cannot, in principle, be guaranteed to be >>>> available >>>> at runtime unless generics are reified. >>>> >>>> >>>>> 4. Can't have primitive types (this might be fixable with an >>>>> extension >>>>> to >>>>> the signature attribute) >>>>> 5. Can't have static fields that are lambdas (this might be fixable >>>>> with >>>>> >>>>> an extension to the signature attribute) >>>>> >>>> >>>> Right: the signature attributes would be extended to express function >>>> types, addressing these two issues. >>>> >>>> >>>> ______________________________________________________________________ >>>> This email has been scanned by the MessageLabs Email Security System. >>>> For more information please visit http://www.messagelabs.com/email >>>> ______________________________________________________________________ >>>> >>> >>> >>> >>> -- >>> -- Howard. >>> >> >> >> ______________________________________________________________________ >> This email has been scanned by the MessageLabs Email Security System. >> For more information please visit http://www.messagelabs.com/email >> ______________________________________________________________________ >> > > > > -- > -- Howard. > > From neal at gafter.com Wed Dec 30 07:58:13 2009 From: neal at gafter.com (Neal Gafter) Date: Wed, 30 Dec 2009 07:58:13 -0800 Subject: Lambda and JSR 292 method handle In-Reply-To: <3dd3f56a0912292332rd7be44br3f072a7d48d937f2@mail.gmail.com> References: <3dd3f56a0912180255r4e88dd25k1bed48cb3a41901e@mail.gmail.com> <4B2B8C41.2020705@univ-mlv.fr> <3dd3f56a0912180706v383bc710o1ab4f57e24b29afb@mail.gmail.com> <4B2BBB0E.30503@univ-mlv.fr> <3dd3f56a0912231306m4917cd47w2d82436087f8b704@mail.gmail.com> <15e8b9d20912231336x7aabdee1y8819973d60ff35c7@mail.gmail.com> <3dd3f56a0912291450s770c5e42wfc2aca6855dc39cf@mail.gmail.com> <15e8b9d20912291519l4c51c26bg93352bcfc76cca71@mail.gmail.com> <3dd3f56a0912292332rd7be44br3f072a7d48d937f2@mail.gmail.com> Message-ID: <15e8b9d20912300758t2ed429b9v83e8080f24c543d9@mail.gmail.com> On Tue, Dec 29, 2009 at 11:32 PM, Howard Lovatt wrote: > Neal, > > Good points, the first: > > > > > > > List > > > > > > to a value of type > > > > > List > > > > > > Is easily fixable by having the reified versions extend the generic > versions with a special case for primitives, i.e.: > > *public* *abstract* *class* Callable$Int *implements* Callable$0 { > *public* *abstract* *int* callInt(); > @Override *public* *final* Integer call() { *return* callInt(); }} > > That answer is nonresponsive to my question. > > Also, there need to be subtype relations in both > > directions between your Callable$0 and > > Callable$String but that is impossible because they are > > distinct interfaces. If you try to provide the subtype > > relations in just one direction, things quicky get out of > > hand (i.e. an exponential explosion in direct > > superinterfaces of the generated interfaces) when there > > are multiple lambda arguments. > > The above modification to implement Callable$... solves this problem in > one direction and the other is via 'cast' methods. The idea was that the > 'cast' methods are loader generated, though re-reading my post I didn't make > this clear (sorry). > My point is that the subtypes in one direction generate an inheritance hierarchy that gets out of hand, and the cast methods in the other direction don't actually work. To take a specific simple example of the latter issue, consider a method that returns a generic list of functions: * List<#T()> lazify(List data) { List<#T()> result = new ArrayList<#T()>(); for (T t : data) result.add(#()t); // adds element of type Callable$0 return result; } * the list that is returned contains lambdas of type Callable$0. Then we call it on some data *List<#String()> alphabet() { return lazify(**Arrays.asList("a", "b", "c")**); } List<#String()> **alphabet **= **alphabet**();* now alphabet contains a List whose elements are of type Callable$0 (but the compiler probably thinks those elements are of type Callable$String). So we pull a datum out of it. *#String() firstLetter = **alphabet**.get(0); * Now we've assigned something of type Callable$0 to something of type Callable$String. Where in the execution of this code did the "cast" occur? I am making the assumption that these 'casts' are rare and therefore in > practice you won't get an explosion of 'cast' methods. > As much as I take issue with your assumption, I am more concerned about correctness than performance. -Neal