From sebastien.deries at gmail.com Tue Feb 10 16:53:04 2015 From: sebastien.deries at gmail.com (sebastien deries) Date: Tue, 10 Feb 2015 17:53:04 +0100 Subject: listeners and lambda method reference Message-ID: Hi all, While working on memory leak issues in my application, I discovered that I had a problem with the way I use lambda reference method. Here is the problem: public class Lambda { private final Property property; public Lambda() { property = new SimpleBooleanProperty(); property.addListener(this::propertyChanged); property.removeListener(this::propertyChanged); property.setValue(true); } private void propertyChanged(ObservableValue notifier, Boolean previous, Boolean next) { System.out.println(" hello !"); } public static void main(String[] args) { new Lambda(); } } In this example, I have a property and want to listen to the property changes. When I run this example, the console output says ?hello!? whereas I removed the listener. I thought that the syntax this::propertyChanged was giving me a single instance of ChangeListener, but I was apparently wrong. Is this normal? Regards Seb From maurizio.cimadamore at oracle.com Tue Feb 10 17:18:53 2015 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Tue, 10 Feb 2015 17:18:53 +0000 Subject: listeners and lambda method reference In-Reply-To: References: Message-ID: <54DA3D7D.3080207@oracle.com> Hi Sebastien, the identity of an instance obtained through capture is 'unreliable'. In case of method references is not unthinkable considering adding an equals() implementation which takes into account all the parameters to the bootstrap method used to forge a new instance of the functional interface, but that's not how things work now. An alternative way to express the idiom now is: Listener l = this::propertyChanged; ... property.addListener(l); ... property.removeListener(l); Which will do what you expect (as there's only one capture there). Maurizio On 10/02/15 16:53, sebastien deries wrote: > Hi all, > > > > While working on memory leak issues in my application, I discovered that I > had a problem with the way I use lambda reference method. > > Here is the problem: > > > > public class Lambda { > > private final Property property; > > > > public Lambda() { > > > > property = new SimpleBooleanProperty(); > > > > property.addListener(this::propertyChanged); > > property.removeListener(this::propertyChanged); > > > > property.setValue(true); > > > > } > > > > private void propertyChanged(ObservableValue > notifier, Boolean previous, Boolean next) { > > System.out.println(" hello !"); > > > > } > > > > public static void main(String[] args) { > > new Lambda(); > > } > > > > } > > > > In this example, I have a property and want to listen to the property > changes. When I run this example, the console output says ?hello!? whereas > I removed the listener. I thought that the syntax this::propertyChanged was > giving me a single instance of ChangeListener, but I was apparently wrong. > > > > Is this normal? > > > > Regards > > > > Seb > From forax at univ-mlv.fr Tue Feb 10 18:19:46 2015 From: forax at univ-mlv.fr (Remi Forax) Date: Tue, 10 Feb 2015 19:19:46 +0100 Subject: listeners and lambda method reference In-Reply-To: <54DA3D7D.3080207@oracle.com> References: <54DA3D7D.3080207@oracle.com> Message-ID: <54DA4BC2.4000707@univ-mlv.fr> Hi Sebastian, Hi Maurizio, On 02/10/2015 06:18 PM, Maurizio Cimadamore wrote: > Hi Sebastien, > the identity of an instance obtained through capture is 'unreliable'. > In case of method references is not unthinkable considering adding an > equals() implementation which takes into account all the parameters to > the bootstrap method used to forge a new instance of the functional > interface, but that's not how things work now. changing a lambda to an equivalent method ref and vice versa should be possible without thinking too much, captured values can be not accessible to the lambda proxy (if they are inserted into the method handle), and debugging auto-generated equals/hashCode is not fun at all ... > An alternative way to express the idiom now is: > > Listener l = this::propertyChanged; > > ... > > property.addListener(l); > ... > > property.removeListener(l); > > Which will do what you expect (as there's only one capture there). yes, > > Maurizio R?mi From Sebastian.Millies at softwareag.com Mon Feb 23 17:31:56 2015 From: Sebastian.Millies at softwareag.com (Millies, Sebastian) Date: Mon, 23 Feb 2015 17:31:56 +0000 Subject: Converting between structurally compatible function types Message-ID: <32F15738E8E5524DA4F01A0FA4A8E490FDD82DA0@HQMBX5.eur.ad.sag> Hello there, I have a very basic question: why does the following not compile: Function f = s -> 1; Function g = f; After all, I would expect that anywhere where a function from String to arbitrary objects is required, I can supply a function to integers in particular. I guess Java just sees the names are different, and that?s it? How do I best convert between the two types? n Sebastian Software AG ? Sitz/Registered office: Uhlandstra?e 12, 64297 Darmstadt, Germany ? Registergericht/Commercial register: Darmstadt HRB 1562 - Vorstand/Management Board: Karl-Heinz Streibich (Vorsitzender/Chairman), Eric Duffaut, Dr. Wolfram Jost, Arnd Zinnhardt; - Aufsichtsratsvorsitzender/Chairman of the Supervisory Board: Dr. Andreas Bereczky - http://www.softwareag.com From Sebastian.Millies at softwareag.com Mon Feb 23 17:36:27 2015 From: Sebastian.Millies at softwareag.com (Millies, Sebastian) Date: Mon, 23 Feb 2015 17:36:27 +0000 Subject: Converting between structurally compatible function types In-Reply-To: <32F15738E8E5524DA4F01A0FA4A8E490FDD82DA0@HQMBX5.eur.ad.sag> References: <32F15738E8E5524DA4F01A0FA4A8E490FDD82DA0@HQMBX5.eur.ad.sag> Message-ID: <32F15738E8E5524DA4F01A0FA4A8E490FDD82DBA@HQMBX5.eur.ad.sag> sorry for the noise, figured out how to use the identity function for this: Function id = n -> n g = id.compose(f); -- Sebastian -----Original Message----- From: lambda-dev [mailto:lambda-dev-bounces at openjdk.java.net] On Behalf Of Millies, Sebastian Sent: Monday, February 23, 2015 6:32 PM To: lambda-dev at openjdk.java.net Subject: Converting between structurally compatible function types Hello there, I have a very basic question: why does the following not compile: Function f = s -> 1; Function g = f; After all, I would expect that anywhere where a function from String to arbitrary objects is required, I can supply a function to integers in particular. I guess Java just sees the names are different, and that?s it? How do I best convert between the two types? n Sebastian Software AG ? Sitz/Registered office: Uhlandstra?e 12, 64297 Darmstadt, Germany ? Registergericht/Commercial register: Darmstadt HRB 1562 - Vorstand/Management Board: Karl-Heinz Streibich (Vorsitzender/Chairman), Eric Duffaut, Dr. Wolfram Jost, Arnd Zinnhardt; - Aufsichtsratsvorsitzender/Chairman of the Supervisory Board: Dr. Andreas Bereczky - http://www.softwareag.com From boaznahum at gmail.com Mon Feb 23 17:38:43 2015 From: boaznahum at gmail.com (Boaz Nahum) Date: Mon, 23 Feb 2015 17:38:43 +0000 Subject: Converting between structurally compatible function types References: <32F15738E8E5524DA4F01A0FA4A8E490FDD82DA0@HQMBX5.eur.ad.sag> Message-ID: Yes, but what if Function has method that accepts R instead of returning one? Try Function instead. Boaz On Mon, Feb 23, 2015 at 7:32 PM Millies, Sebastian < Sebastian.Millies at softwareag.com> wrote: > Hello there, > > I have a very basic question: why does the following not compile: > > Function f = s -> 1; > Function g = f; > > After all, I would expect that anywhere where a function from String to > arbitrary objects is required, I can supply a function to integers in > particular. > I guess Java just sees the names are different, and that?s it? > > How do I best convert between the two types? > > > n Sebastian > > > Software AG ? Sitz/Registered office: Uhlandstra?e 12, 64297 Darmstadt, > Germany ? Registergericht/Commercial register: Darmstadt HRB 1562 - > Vorstand/Management Board: Karl-Heinz Streibich (Vorsitzender/Chairman), > Eric Duffaut, Dr. Wolfram Jost, Arnd Zinnhardt; - Aufsichtsratsvorsitzender/Chairman > of the Supervisory Board: Dr. Andreas Bereczky - http://www.softwareag.com > > > From samir at noodlesandwich.com Mon Feb 23 21:17:13 2015 From: samir at noodlesandwich.com (Samir Talwar) Date: Mon, 23 Feb 2015 21:17:13 +0000 Subject: Converting between structurally compatible function types In-Reply-To: <32F15738E8E5524DA4F01A0FA4A8E490FDD82DBA@HQMBX5.eur.ad.sag> References: <32F15738E8E5524DA4F01A0FA4A8E490FDD82DA0@HQMBX5.eur.ad.sag> <32F15738E8E5524DA4F01A0FA4A8E490FDD82DBA@HQMBX5.eur.ad.sag> Message-ID: Java can't, in general, assign a value to another of the same type with different generic parameters. Just like there's no implicit conversion from List to List, you can't convert Function objects either. My preferred way of doing this would be to use the fact that Function is really a class with the method `apply` and assign a method reference instead: Function g = f::apply; Cheers, ? Samir. On Mon, Feb 23, 2015 at 5:36 PM, Millies, Sebastian < Sebastian.Millies at softwareag.com> wrote: > sorry for the noise, figured out how to use the identity function for this: > > Function id = n -> n > g = id.compose(f); > > -- Sebastian > > -----Original Message----- > From: lambda-dev [mailto:lambda-dev-bounces at openjdk.java.net] On Behalf > Of Millies, Sebastian > Sent: Monday, February 23, 2015 6:32 PM > To: lambda-dev at openjdk.java.net > Subject: Converting between structurally compatible function types > > Hello there, > > I have a very basic question: why does the following not compile: > > Function f = s -> 1; > Function g = f; > > After all, I would expect that anywhere where a function from String to > arbitrary objects is required, I can supply a function to integers in > particular. > I guess Java just sees the names are different, and that?s it? > > How do I best convert between the two types? > > > n Sebastian > > > Software AG ? Sitz/Registered office: Uhlandstra?e 12, 64297 Darmstadt, > Germany ? Registergericht/Commercial register: Darmstadt HRB 1562 - > Vorstand/Management Board: Karl-Heinz Streibich (Vorsitzender/Chairman), > Eric Duffaut, Dr. Wolfram Jost, Arnd Zinnhardt; - > Aufsichtsratsvorsitzender/Chairman of the Supervisory Board: Dr. Andreas > Bereczky - http://www.softwareag.com > > > > From jed at wesleysmith.io Tue Feb 24 02:19:25 2015 From: jed at wesleysmith.io (Jed Wesley-Smith) Date: Tue, 24 Feb 2015 13:19:25 +1100 Subject: Converting between structurally compatible function types In-Reply-To: <32F15738E8E5524DA4F01A0FA4A8E490FDD82DA0@HQMBX5.eur.ad.sag> References: <32F15738E8E5524DA4F01A0FA4A8E490FDD82DA0@HQMBX5.eur.ad.sag> Message-ID: You are asking javac to know that the second type parameter is only used covariantly (ie. only as a return type), but the compiler cannot know this unless it goes and inspects every place it is used. This is because Java has use-site variance, rather than declaration-site variance. Consider that while a Functionis absolutely acceptable where you need a Function, a Function is not acceptable when a Function is required. This is because the first parameter is exclusively used as an input parameter. Inputs are contravariant, and again you can only know this by inspecting the use-sites, and nothing would prevent someone from casually using the first type parameter in return position, or vice versa. Contrast this with Scala that has declaration site variance, using '+' for covariance and '-' for contravariance. The function definition is actually Function1[-A, +B], and the compiler bars you from using these incorrectly. Java can only really support what you want via helper methods that hide the ugliness, eg: public Function covariant(Function f) { @SuppressWarnings("unchecked") Function fb = (Function ) f; return fb; } public Function contravariant(Function f) { @SuppressWarnings("unchecked") Function fb = (Function ) f; return fb; } cheers, jed On 24 February 2015 at 04:31, Millies, Sebastian < Sebastian.Millies at softwareag.com> wrote: > Hello there, > > I have a very basic question: why does the following not compile: > > Function f = s -> 1; > Function g = f; > > After all, I would expect that anywhere where a function from String to > arbitrary objects is required, I can supply a function to integers in > particular. > I guess Java just sees the names are different, and that?s it? > > How do I best convert between the two types? > > > n Sebastian > > > Software AG ? Sitz/Registered office: Uhlandstra?e 12, 64297 Darmstadt, > Germany ? Registergericht/Commercial register: Darmstadt HRB 1562 - > Vorstand/Management Board: Karl-Heinz Streibich (Vorsitzender/Chairman), > Eric Duffaut, Dr. Wolfram Jost, Arnd Zinnhardt; - > Aufsichtsratsvorsitzender/Chairman of the Supervisory Board: Dr. Andreas > Bereczky - http://www.softwareag.com > > >