From maurizio.cimadamore at oracle.com Fri Sep 2 04:44:31 2011 From: maurizio.cimadamore at oracle.com (maurizio.cimadamore at oracle.com) Date: Fri, 02 Sep 2011 11:44:31 +0000 Subject: hg: lambda/lambda/langtools: Bug: reference to super leads to compiler crash when 292 translation scheme is enabled Message-ID: <20110902114438.34D56472F0@hg.openjdk.java.net> Changeset: 1b669fe38c5d Author: mcimadamore Date: 2011-09-02 12:43 +0100 URL: http://hg.openjdk.java.net/lambda/lambda/langtools/rev/1b669fe38c5d Bug: reference to super leads to compiler crash when 292 translation scheme is enabled The compiler should emit instance (not static) bridge methods when bridging member references whose qualifier is super/this. ! src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java + test/tools/javac/lambda/MethodReference29.java From forax at univ-mlv.fr Sat Sep 3 08:06:24 2011 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Sat, 03 Sep 2011 17:06:24 +0200 Subject: lambda inference bug Message-ID: <4E624270.2030806@univ-mlv.fr> Hi Maurizio, hi all, The code below doesn't compile but I think it should. [lambda.javac] ReducerBug.java:17: error: bad operand types for binary operator '+' [lambda.javac] int result = reduce(l, 0, #{ e, v -> e + v}); [lambda.javac] ^ [lambda.javac] first type: Integer [lambda.javac] second type: V [lambda.javac] where V is a type-variable: [lambda.javac] V extends Object declared in interface Reducer [lambda.javac] 1 error I don't understand why V (which is a type variable of the interface) can be propagated in the body of the lambda thus I think it's a bug. R?mi public class ReducerBug { interface Reducer { public V reduce(E element, V value); } private static int reduce(Iterable iterable, int initialValue, Reducer reducer) { int value = initialValue; for(E e: iterable) { value = reducer.reduce(e, value); } return value; } public static void main(String[] args) { java.util.List l = java.util.Arrays.asList(1, 2, 3); int result = reduce(l, 0, #{ e, v -> e + v}); System.out.println(result); } } From maurizio.cimadamore at oracle.com Mon Sep 5 01:20:55 2011 From: maurizio.cimadamore at oracle.com (maurizio cimadamore) Date: Mon, 05 Sep 2011 09:20:55 +0100 Subject: lambda inference bug In-Reply-To: <4E624270.2030806@univ-mlv.fr> References: <4E624270.2030806@univ-mlv.fr> Message-ID: <4E648667.2030805@oracle.com> Hi, this looks like a type-substitution bug - however, I don't think this should compile (w/ or w/o the bug), given that there's no lower bound on E the parameter types of the lambda body cannot be instantiated (therefore the lambda expression cannot be attributed). This should be a cyclic inference error (as inference is stuck in this case). The experimental option -XDcomplexinference should help unstuck this (but will infer Object for E). Maurizio On 03/09/2011 16:06, R?mi Forax wrote: > Hi Maurizio, hi all, > The code below doesn't compile but I think it should. > > [lambda.javac] ReducerBug.java:17: error: bad operand types for binary > operator '+' > [lambda.javac] int result = reduce(l, 0, #{ e, v -> e + v}); > [lambda.javac] ^ > [lambda.javac] first type: Integer > [lambda.javac] second type: V > [lambda.javac] where V is a type-variable: > [lambda.javac] V extends Object declared in interface Reducer > [lambda.javac] 1 error > > I don't understand why V (which is a type variable of the interface) > can be propagated > in the body of the lambda thus I think it's a bug. > > R?mi > > public class ReducerBug { > interface Reducer { > public V reduce(E element, V value); > } > > private static int reduce(Iterable iterable, int > initialValue, Reducer reducer) { > int value = initialValue; > for(E e: iterable) { > value = reducer.reduce(e, value); > } > return value; > } > > public static void main(String[] args) { > java.util.List l = java.util.Arrays.asList(1, 2, 3); > int result = reduce(l, 0, #{ e, v -> e + v}); > System.out.println(result); > } > } From maurizio.cimadamore at oracle.com Mon Sep 5 03:53:36 2011 From: maurizio.cimadamore at oracle.com (maurizio.cimadamore at oracle.com) Date: Mon, 05 Sep 2011 10:53:36 +0000 Subject: hg: lambda/lambda/langtools: Bug: wrong type-variable substitution leads to spurious inference error Message-ID: <20110905105342.7EAD5473AC@hg.openjdk.java.net> Changeset: 37f50cc161c6 Author: mcimadamore Date: 2011-09-05 11:52 +0100 URL: http://hg.openjdk.java.net/lambda/lambda/langtools/rev/37f50cc161c6 Bug: wrong type-variable substitution leads to spurious inference error ! src/share/classes/com/sun/tools/javac/comp/Infer.java + test/tools/javac/lambda/TargetType29.java From maurizio.cimadamore at oracle.com Mon Sep 5 04:11:13 2011 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Mon, 05 Sep 2011 12:11:13 +0100 Subject: lambda inference bug In-Reply-To: <4E648667.2030805@oracle.com> References: <4E624270.2030806@univ-mlv.fr> <4E648667.2030805@oracle.com> Message-ID: <4E64AE51.1000304@oracle.com> Hi, forget my earlier comment (I misread your example) - this should indeed compile, as E gets a lower bound from the first actual argument. This has been now fixed in the lambda-repo. Maurizio On 05/09/11 09:20, maurizio cimadamore wrote: >> public class ReducerBug { >> > interface Reducer { >> > public V reduce(E element, V value); >> > } >> > >> > private static int reduce(Iterable iterable, int >> > initialValue, Reducer reducer) { >> > int value = initialValue; >> > for(E e: iterable) { >> > value = reducer.reduce(e, value); >> > } >> > return value; >> > } >> > >> > public static void main(String[] args) { >> > java.util.List l = java.util.Arrays.asList(1, 2, 3); >> > int result = reduce(l, 0, #{ e, v -> e + v}); >> > System.out.println(result); >> > } >> > } From maurizio.cimadamore at oracle.com Mon Sep 5 04:11:26 2011 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Mon, 05 Sep 2011 12:11:26 +0100 Subject: lambda inference bug In-Reply-To: <4E648667.2030805@oracle.com> References: <4E624270.2030806@univ-mlv.fr> <4E648667.2030805@oracle.com> Message-ID: <4E64AE5E.1070605@oracle.com> Hi, forget my earlier comment (I misread your example) - this should indeed compile, as E gets a lower bound from the first actual argument. This has been now fixed in the lambda-repo. Maurizio On 05/09/11 09:20, maurizio cimadamore wrote: >> public class ReducerBug { >> > interface Reducer { >> > public V reduce(E element, V value); >> > } >> > >> > private static int reduce(Iterable iterable, int >> > initialValue, Reducer reducer) { >> > int value = initialValue; >> > for(E e: iterable) { >> > value = reducer.reduce(e, value); >> > } >> > return value; >> > } >> > >> > public static void main(String[] args) { >> > java.util.List l = java.util.Arrays.asList(1, 2, 3); >> > int result = reduce(l, 0, #{ e, v -> e + v}); >> > System.out.println(result); >> > } >> > } From forax at univ-mlv.fr Mon Sep 5 06:11:31 2011 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Mon, 05 Sep 2011 15:11:31 +0200 Subject: lambda inference bug In-Reply-To: <4E64AE5E.1070605@oracle.com> References: <4E624270.2030806@univ-mlv.fr> <4E648667.2030805@oracle.com> <4E64AE5E.1070605@oracle.com> Message-ID: <4E64CA83.8050609@univ-mlv.fr> On 09/05/2011 01:11 PM, Maurizio Cimadamore wrote: > Hi, > forget my earlier comment (I misread your example) - this should > indeed compile, as E gets a lower bound from the first actual > argument. This has been now fixed in the lambda-repo. > > Maurizio Hi Maurizio, thank you for the fast fix. Could you explain me the difference between the inference used by default by javac and the complex inference ? R?mi > > On 05/09/11 09:20, maurizio cimadamore wrote: >>> public class ReducerBug { >>> > interface Reducer { >>> > public V reduce(E element, V value); >>> > } >>> > >>> > private static int reduce(Iterable iterable, >>> int >>> > initialValue, Reducer reducer) { >>> > int value = initialValue; >>> > for(E e: iterable) { >>> > value = reducer.reduce(e, value); >>> > } >>> > return value; >>> > } >>> > >>> > public static void main(String[] args) { >>> > java.util.List l = java.util.Arrays.asList(1, 2, 3); >>> > int result = reduce(l, 0, #{ e, v -> e + v}); >>> > System.out.println(result); >>> > } >>> > } > From maurizio.cimadamore at oracle.com Mon Sep 5 06:30:47 2011 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Mon, 05 Sep 2011 14:30:47 +0100 Subject: lambda inference bug In-Reply-To: <4E64CA83.8050609@univ-mlv.fr> References: <4E624270.2030806@univ-mlv.fr> <4E648667.2030805@oracle.com> <4E64AE5E.1070605@oracle.com> <4E64CA83.8050609@univ-mlv.fr> Message-ID: <4E64CF07.6070104@oracle.com> On 05/09/11 14:11, R?mi Forax wrote: > On 09/05/2011 01:11 PM, Maurizio Cimadamore wrote: >> Hi, >> forget my earlier comment (I misread your example) - this should >> indeed compile, as E gets a lower bound from the first actual >> argument. This has been now fixed in the lambda-repo. >> >> Maurizio > > Hi Maurizio, > thank you for the fast fix. > > Could you explain me the difference between the inference used by > default by javac > and the complex inference ? Leaving lambda aside for a moment (simpler) - suppose you have the following method declaration: void m(List ls) { ... } and that you want to call 'm' as follows; m(new ArrayList<>); in a perfect world where inference in method context would work as expected (;-)) there is a problem with the above source: we are supposed to infer the type-variable S from the type of the actual argument applied to the method; however, the actual type itself needs some inference to be performed. The standard javac policy is to issue an inference error in such cases (cyclic inference - see example below with lambdas). However, I've been working at a more aggressive inference scheme that tries to 'unstuck' the inference process in a backward compatible way: *) first, the type of the actual argument is inferred w/o the expected type (i.e. using Object). Thus, the actual is first inferred to be ArrayList *) then, the newly instantiated actual is used to carry on the inference of the formal (thus, S == Object). Note that, while the result is not as specific as we would like it to be, on the other hand the compiler would be able to compile this example, and to have an answer that would be compatible with what the compiler inferred in JDK 7. With inference of lambda formals, it is sometimes possible to end up with a situation that is morally equivalent to the one illustrated above - an example is: interface SAM { List m(); } class Test { void m(SAM sz) { } { m(#{ -> new ArrayList<>() }); } } The above doesn't compile by default - however it can be made to compile by enabling the -XDcomplexinference flag. We still have to decide as to whether this 'aggressive' mode will be the default behavior for the javac compiler in JDK 8. We believe this could be an advantage esp. if the scope of target type-inference is expanded to support inference in method context. Maurizio > > R?mi > >> >> On 05/09/11 09:20, maurizio cimadamore wrote: >>>> public class ReducerBug { >>>> > interface Reducer { >>>> > public V reduce(E element, V value); >>>> > } >>>> > >>>> > private static int reduce(Iterable >>>> iterable, int >>>> > initialValue, Reducer reducer) { >>>> > int value = initialValue; >>>> > for(E e: iterable) { >>>> > value = reducer.reduce(e, value); >>>> > } >>>> > return value; >>>> > } >>>> > >>>> > public static void main(String[] args) { >>>> > java.util.List l = java.util.Arrays.asList(1, 2, 3); >>>> > int result = reduce(l, 0, #{ e, v -> e + v}); >>>> > System.out.println(result); >>>> > } >>>> > } >> > From forax at univ-mlv.fr Mon Sep 5 09:38:17 2011 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Mon, 05 Sep 2011 18:38:17 +0200 Subject: lambda inference bug In-Reply-To: <4E64CF07.6070104@oracle.com> References: <4E624270.2030806@univ-mlv.fr> <4E648667.2030805@oracle.com> <4E64AE5E.1070605@oracle.com> <4E64CA83.8050609@univ-mlv.fr> <4E64CF07.6070104@oracle.com> Message-ID: <4E64FAF9.1050103@univ-mlv.fr> On 09/05/2011 03:30 PM, Maurizio Cimadamore wrote: > On 05/09/11 14:11, R?mi Forax wrote: >> On 09/05/2011 01:11 PM, Maurizio Cimadamore wrote: >>> Hi, >>> forget my earlier comment (I misread your example) - this should >>> indeed compile, as E gets a lower bound from the first actual >>> argument. This has been now fixed in the lambda-repo. >>> >>> Maurizio >> >> Hi Maurizio, >> thank you for the fast fix. >> >> Could you explain me the difference between the inference used by >> default by javac >> and the complex inference ? > Leaving lambda aside for a moment (simpler) - suppose you have the > following method declaration: > > void m(List ls) { ... } > > and that you want to call 'm' as follows; > > m(new ArrayList<>()); > > in a perfect world where inference in method context would work as > expected (;-)) there is a problem with the above source: we are > supposed to infer the type-variable S from the type of the actual > argument applied to the method; however, the actual type itself needs > some inference to be performed. > > The standard javac policy is to issue an inference error in such cases > (cyclic inference - see example below with lambdas). I was thinking to understand until I test. The code above works, with javac and with eclipse (+java7 patch), it's infered as ArrayList, I think it's because when the inference fails, the algorithm returns Object (as specified in the JLS). By example, if S as a bound, it doesn't compile: void m(List ls) { ... } ... m(new ArrayList<>()); > However, I've been working at a more aggressive inference scheme that > tries to 'unstuck' the inference process in a backward compatible way: > > *) first, the type of the actual argument is inferred w/o the expected > type (i.e. using Object). Thus, the actual is first inferred to be > ArrayList I think, you should use the bound of the type variable here, but there is still a problem with recursive bound. > > *) then, the newly instantiated actual is used to carry on the > inference of the formal (thus, S == Object). > > Note that, while the result is not as specific as we would like it to > be, on the other hand the compiler would be able to compile this > example, and to have an answer that would be compatible with what the > compiler inferred in JDK 7. > > With inference of lambda formals, it is sometimes possible to end up > with a situation that is morally equivalent to the one illustrated > above - an example is: > > interface SAM { > List m(); > } > > class Test { > void m(SAM sz) { } > > { m(#{ -> new ArrayList<>() }); } > } > > The above doesn't compile by default - however it can be made to > compile by enabling the -XDcomplexinference flag. > > We still have to decide as to whether this 'aggressive' mode will be > the default behavior for the javac compiler in JDK 8. We believe this > could be an advantage esp. if the scope of target type-inference is > expanded to support inference in method context. > > Maurizio R?mi From maurizio.cimadamore at oracle.com Tue Sep 6 03:35:17 2011 From: maurizio.cimadamore at oracle.com (maurizio.cimadamore at oracle.com) Date: Tue, 06 Sep 2011 10:35:17 +0000 Subject: hg: lambda/lambda/langtools: Stricter bridge logic generation for lambda/method reference translation. Message-ID: <20110906103523.7DA49473E2@hg.openjdk.java.net> Changeset: a2d6528a494d Author: mcimadamore Date: 2011-09-06 11:34 +0100 URL: http://hg.openjdk.java.net/lambda/lambda/langtools/rev/a2d6528a494d Stricter bridge logic generation for lambda/method reference translation. Bridges are generated if: *) signature of lambda does not match signature of erased SAM descriptor declaration *) signature of member reference does not match signature of erased SAM descriptor declaration ! src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java From brian.goetz at oracle.com Thu Sep 8 13:07:03 2011 From: brian.goetz at oracle.com (Brian Goetz) Date: Thu, 08 Sep 2011 16:07:03 -0400 Subject: Syntax decision Message-ID: <4E692067.1080509@oracle.com> This just in: the EG has (mostly) made a decision on syntax. After considering a number of alternatives, we decided to essentially adopt the C# syntax. We may still deliberate further on the fine points (e.g., thin arrow vs fat arrow, special nilary form, etc), and have not yet come to a decision on method reference syntax. The C# syntax is: lambda = ArgList Arrow Body ArgList = Identifier | "(" Identifier [ "," Identifier ]* ")" | "(" Type Identifier [ "," Type Identifier ]* ")" Body = Expression | "{" [ Statement ";" ]+ "}" Here are some examples of lambda expressions using this syntax: x => x + 1 (x) => x + 1 (int x) => x + 1 (int x, int y) => x + y (x, y) => x + y (x, y) => { System.out.printf("%d + %d = %d%n", x, y, x+y); } () => { System.out.println("I am a Runnable"); } The decision to choose this syntax was twofold: - The syntax scores "pretty well" on most subjective measures (though has cases where it looks bad, just like all the others do). In particular, it does well with "small" lambdas that are used as method arguments (a common case), and also does well with large (multi-statement) lambdas. - Despite extensive searching, there was no clear winner among the alternatives (each form had some good aspects and some really not very good aspects, and there was no form that was clearly better than the others). So, we felt that it was better to choose something that has already been shown to work well in the two languages that are most like Java -- C# and Scala -- rather than to invent something new. A compiler implementation should be available soon. From peter.levart at marand.si Thu Sep 8 23:55:31 2011 From: peter.levart at marand.si (Peter Levart) Date: Fri, 9 Sep 2011 08:55:31 +0200 Subject: Syntax decision In-Reply-To: <4E692067.1080509@oracle.com> References: <4E692067.1080509@oracle.com> Message-ID: <201109090855.31779.peter.levart@marand.si> On 09/08/11, Brian Goetz wrote: > Here are some examples of lambda expressions using this syntax: > > x => x + 1 > (x) => x + 1 > (int x) => x + 1 > (int x, int y) => x + y > (x, y) => x + y > (x, y) => { System.out.printf("%d + %d = %d%n", x, y, x+y); } > () => { System.out.println("I am a Runnable"); } Hurray! From pbenedict at apache.org Fri Sep 9 06:17:55 2011 From: pbenedict at apache.org (Paul Benedict) Date: Fri, 9 Sep 2011 08:17:55 -0500 Subject: Syntax decision In-Reply-To: <4E692067.1080509@oracle.com> References: <4E692067.1080509@oracle.com> Message-ID: Glad you guys chose to go with a syntax that C# and Scala broadly share. That will ease the comprehension weight for those learning/converting to Java. On Thu, Sep 8, 2011 at 3:07 PM, Brian Goetz wrote: > This just in: the EG has (mostly) made a decision on syntax. > > After considering a number of alternatives, we decided to essentially > adopt the C# syntax. ?We may still deliberate further on the fine points > (e.g., thin arrow vs fat arrow, special nilary form, etc), and have not > yet come to a decision on method reference syntax. > > The C# syntax is: > > ? lambda = ArgList Arrow Body > ? ArgList = Identifier > ? ? ? ? ? ? | "(" Identifier [ "," Identifier ]* ")" > ? ? ? ? ? ? | "(" Type Identifier [ "," Type Identifier ]* ")" > ? Body = Expression > ? ? ? ? ? ? | "{" [ Statement ";" ]+ "}" > > Here are some examples of lambda expressions using this syntax: > > ? x => x + 1 > ? (x) => x + 1 > ? (int x) => x + 1 > ? (int x, int y) => x + y > ? (x, y) => x + y > ? (x, y) => { System.out.printf("%d + %d = %d%n", x, y, x+y); } > ? () => { System.out.println("I am a Runnable"); } > > The decision to choose this syntax was twofold: > ?- The syntax scores "pretty well" on most subjective measures (though > has cases where it looks bad, just like all the others do). ?In > particular, it does well with "small" lambdas that are used as method > arguments (a common case), and also does well with large > (multi-statement) lambdas. > > ?- Despite extensive searching, there was no clear winner among the > alternatives (each form had some good aspects and some really not very > good aspects, and there was no form that was clearly better than the > others). ?So, we felt that it was better to choose something that has > already been shown to work well in the two languages that are most like > Java -- C# and Scala -- rather than to invent something new. > > A compiler implementation should be available soon. > > > > From maurizio.cimadamore at oracle.com Fri Sep 9 06:21:26 2011 From: maurizio.cimadamore at oracle.com (maurizio.cimadamore at oracle.com) Date: Fri, 09 Sep 2011 13:21:26 +0000 Subject: hg: lambda/lambda/langtools: Implement parser changes to support C#-like syntax for lambda expressions. Message-ID: <20110909132130.47A8F474DC@hg.openjdk.java.net> Changeset: a4fc85ec18eb Author: mcimadamore Date: 2011-09-09 14:19 +0100 URL: http://hg.openjdk.java.net/lambda/lambda/langtools/rev/a4fc85ec18eb Implement parser changes to support C#-like syntax for lambda expressions. Examples: x -> x + 1 (x) -> x + 1 (int x) -> x + 1 (int x, int y) -> x + y (x, y) -> x + y (x, y) -> { System.out.printf("%d + %d = %d%n", x, y, x+y); } () -> { System.out.println("I am a Runnable"); } Note: 'thin' arrow is still used (instead of 'fat' (=>) arrow a la C#). This will be a topic for further refinement. ! src/share/classes/com/sun/tools/javac/parser/JavacParser.java ! src/share/classes/com/sun/tools/javac/parser/Scanner.java ! src/share/classes/com/sun/tools/javac/parser/Token.java ! src/share/classes/com/sun/tools/javac/resources/compiler.properties ! test/tools/javac/api/TestJavacTaskScanner.java ! test/tools/javac/defender/Pos01.java ! test/tools/javac/diags/examples.not-yet.txt ! test/tools/javac/lambda/BadAccess.java ! test/tools/javac/lambda/BadAccess.out ! test/tools/javac/lambda/BadAccess02.java ! test/tools/javac/lambda/BadAccess02.out ! test/tools/javac/lambda/BadAccess03.java ! test/tools/javac/lambda/BadAccess03.out ! test/tools/javac/lambda/BadBreakContinue.java ! test/tools/javac/lambda/BadBreakContinue.out ! test/tools/javac/lambda/BadConv03.java ! test/tools/javac/lambda/BadConv04.java ! test/tools/javac/lambda/BadLambdaPos.java - test/tools/javac/lambda/BadLambdaToken.java - test/tools/javac/lambda/BadLambdaToken.out ! test/tools/javac/lambda/BadReturn.java ! test/tools/javac/lambda/BadReturn.out ! test/tools/javac/lambda/BadStatementInLambda.java ! test/tools/javac/lambda/BadStatementInLambda.out ! test/tools/javac/lambda/BadStatementInLambda02.java ! test/tools/javac/lambda/BadStatementInLambda02.out ! test/tools/javac/lambda/BadTargetType.java ! test/tools/javac/lambda/Conformance01.java ! test/tools/javac/lambda/Defender01.java ! test/tools/javac/lambda/ExceptionTransparency01.java ! test/tools/javac/lambda/ExceptionTransparency02.java ! test/tools/javac/lambda/ExceptionTransparency03.java ! test/tools/javac/lambda/ExceptionTransparency04.java ! test/tools/javac/lambda/LambdaCapture01.java ! test/tools/javac/lambda/LambdaCapture02.java ! test/tools/javac/lambda/LambdaCapture03.java ! test/tools/javac/lambda/LambdaCapture04.java ! test/tools/javac/lambda/LambdaCapture05.java ! test/tools/javac/lambda/LambdaConv01.java ! test/tools/javac/lambda/LambdaConv03.java ! test/tools/javac/lambda/LambdaConv05.java ! test/tools/javac/lambda/LambdaConv06.java ! test/tools/javac/lambda/LambdaConv08.java ! test/tools/javac/lambda/LambdaConv09.java ! test/tools/javac/lambda/LambdaConv10.java ! test/tools/javac/lambda/LambdaConv11.java ! test/tools/javac/lambda/LambdaConv12.java ! test/tools/javac/lambda/LambdaConv13.java ! test/tools/javac/lambda/LambdaConv16.java ! test/tools/javac/lambda/LambdaConv17.java ! test/tools/javac/lambda/LambdaConv19.java ! test/tools/javac/lambda/LambdaConversionTest.java ! test/tools/javac/lambda/LambdaExpr01.java ! test/tools/javac/lambda/LambdaExpr02.java ! test/tools/javac/lambda/LambdaExpr04.java ! test/tools/javac/lambda/LambdaExpr05.java ! test/tools/javac/lambda/LambdaExpr06.java ! test/tools/javac/lambda/LambdaExpr07.java ! test/tools/javac/lambda/LambdaExpr08.java ! test/tools/javac/lambda/LambdaExpr09.java ! test/tools/javac/lambda/LambdaExpr10.java ! test/tools/javac/lambda/LambdaExprNotVoid.java ! test/tools/javac/lambda/LambdaScope01.java ! test/tools/javac/lambda/LambdaScope02.java ! test/tools/javac/lambda/LambdaScope03.java ! test/tools/javac/lambda/LocalBreakAndContinue.java ! test/tools/javac/lambda/MethodReference12.java ! test/tools/javac/lambda/NakedThis.java ! test/tools/javac/lambda/SourceLevelTest.java ! test/tools/javac/lambda/TargetType01.java ! test/tools/javac/lambda/TargetType02.java ! test/tools/javac/lambda/TargetType03.java ! test/tools/javac/lambda/TargetType04.java ! test/tools/javac/lambda/TargetType05.java ! test/tools/javac/lambda/TargetType06.java ! test/tools/javac/lambda/TargetType07.java ! test/tools/javac/lambda/TargetType08.java ! test/tools/javac/lambda/TargetType10.java ! test/tools/javac/lambda/TargetType11.java ! test/tools/javac/lambda/TargetType12.java ! test/tools/javac/lambda/TargetType13.java ! test/tools/javac/lambda/TargetType14.java ! test/tools/javac/lambda/TargetType15.java ! test/tools/javac/lambda/TargetType16.java ! test/tools/javac/lambda/TargetType17.java ! test/tools/javac/lambda/TargetType18.java ! test/tools/javac/lambda/TargetType19.java ! test/tools/javac/lambda/TargetType20.java ! test/tools/javac/lambda/TargetType21.java ! test/tools/javac/lambda/TargetType22.java ! test/tools/javac/lambda/TargetType23.java ! test/tools/javac/lambda/TargetType24.java ! test/tools/javac/lambda/TargetType24.out ! test/tools/javac/lambda/TargetType25.java ! test/tools/javac/lambda/TargetType26.java ! test/tools/javac/lambda/TargetType27.java ! test/tools/javac/lambda/TargetType28.java ! test/tools/javac/lambda/TargetType29.java ! test/tools/javac/lambda/sqe/SAM_types/LambdaTest1.java ! test/tools/javac/lambda/sqe/SAM_types/LambdaTest1_neg1.java ! test/tools/javac/lambda/sqe/SAM_types/LambdaTest1_neg1.out ! test/tools/javac/lambda/sqe/SAM_types/LambdaTest1_neg2.java ! test/tools/javac/lambda/sqe/SAM_types/LambdaTest1_neg3.java ! test/tools/javac/lambda/sqe/SAM_types/LambdaTest2_SAM1.java ! test/tools/javac/lambda/sqe/SAM_types/LambdaTest2_SAM2.java ! test/tools/javac/lambda/sqe/SAM_types/LambdaTest2_neg1.java ! test/tools/javac/lambda/sqe/SAM_types/NonSAM1.java ! test/tools/javac/lambda/sqe/SAM_types/NonSAM3.java ! test/tools/javac/lambda/sqe/lambdaExpression/AbstractClass_neg.java ! test/tools/javac/lambda/sqe/lambdaExpression/AccessNonStatic_neg.java ! test/tools/javac/lambda/sqe/lambdaExpression/AccessNonStatic_neg.out ! test/tools/javac/lambda/sqe/lambdaExpression/EffectivelyFinal_neg.java ! test/tools/javac/lambda/sqe/lambdaExpression/InvalidExpression1.java ! test/tools/javac/lambda/sqe/lambdaExpression/InvalidExpression3.java ! test/tools/javac/lambda/sqe/lambdaExpression/InvalidExpression4.java ! test/tools/javac/lambda/sqe/lambdaExpression/InvalidExpression5.java ! test/tools/javac/lambda/sqe/lambdaExpression/InvalidExpression6.java ! test/tools/javac/lambda/sqe/lambdaExpression/InvalidExpression6.out ! test/tools/javac/lambda/sqe/lambdaExpression/LambdaTest1.java ! test/tools/javac/lambda/sqe/lambdaExpression/LambdaTest2.java ! test/tools/javac/lambda/sqe/lambdaExpression/LambdaTest3.java ! test/tools/javac/lambda/sqe/lambdaExpression/LambdaTest4.java ! test/tools/javac/lambda/sqe/lambdaExpression/LambdaTest5.java ! test/tools/javac/lambda/sqe/lambdaExpression/LambdaTest6.java From maurizio.cimadamore at oracle.com Fri Sep 9 06:58:08 2011 From: maurizio.cimadamore at oracle.com (maurizio.cimadamore at oracle.com) Date: Fri, 09 Sep 2011 13:58:08 +0000 Subject: hg: lambda/lambda/langtools: Parser confused when lambda expression surrounded by parenthesis Message-ID: <20110909135810.71FDA474E0@hg.openjdk.java.net> Changeset: c2ce16bef6f9 Author: mcimadamore Date: 2011-09-09 14:57 +0100 URL: http://hg.openjdk.java.net/lambda/lambda/langtools/rev/c2ce16bef6f9 Parser confused when lambda expression surrounded by parenthesis ! src/share/classes/com/sun/tools/javac/parser/JavacParser.java + test/tools/javac/lambda/TargetType30.java From maurizio.cimadamore at oracle.com Fri Sep 9 09:56:54 2011 From: maurizio.cimadamore at oracle.com (maurizio.cimadamore at oracle.com) Date: Fri, 09 Sep 2011 16:56:54 +0000 Subject: hg: lambda/lambda/langtools: Parser confused when parenthesized lambda expression occurs in a cast conversion context Message-ID: <20110909165656.82907474EB@hg.openjdk.java.net> Changeset: f2e7fad12285 Author: mcimadamore Date: 2011-09-09 17:56 +0100 URL: http://hg.openjdk.java.net/lambda/lambda/langtools/rev/f2e7fad12285 Parser confused when parenthesized lambda expression occurs in a cast conversion context ! src/share/classes/com/sun/tools/javac/comp/Attr.java + test/tools/javac/lambda/TargetType31.java From stuart.marks at oracle.com Fri Sep 9 18:49:14 2011 From: stuart.marks at oracle.com (stuart.marks at oracle.com) Date: Sat, 10 Sep 2011 01:49:14 +0000 Subject: hg: lambda/lambda/jdk: Update initial lambda APIs and tests to use new syntax. Message-ID: <20110910015030.3ED284750C@hg.openjdk.java.net> Changeset: d9e4e3c106a7 Author: smarks Date: 2011-09-09 18:48 -0700 URL: http://hg.openjdk.java.net/lambda/lambda/jdk/rev/d9e4e3c106a7 Update initial lambda APIs and tests to use new syntax. ! src/share/classes/java/util/functions/Blocks.java ! src/share/classes/java/util/functions/Mappers.java ! src/share/classes/java/util/functions/Predicates.java ! src/share/classes/java/util/functions/Reducers.java ! test/java/util/Collection/Extensions.java ! test/java/util/Collection/MOAT.java ! test/java/util/List/Extensions.java ! test/java/util/functions/Block/BlocksTest.java ! test/java/util/functions/Mapper/MappersTest.java ! test/java/util/functions/Predicate/PredicatesTest.java ! test/java/util/functions/Reducer/ReducersTest.java From forax at univ-mlv.fr Sun Sep 11 04:52:59 2011 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Sun, 11 Sep 2011 13:52:59 +0200 Subject: hg: lambda/lambda/jdk: Update initial lambda APIs and tests to use new syntax. In-Reply-To: <20110910015030.3ED284750C@hg.openjdk.java.net> References: <20110910015030.3ED284750C@hg.openjdk.java.net> Message-ID: <4E6CA11B.9040603@univ-mlv.fr> Hi all, I've tried to fix some bugs of the current implementation of java.util.functions. - some constants are still public (BTW, when the compiler will be able to generate the correct bytecode for a lambda, these constants will be not needed any more because constant lambda will be constant by default) - a lot of generic signature aren't right and there is inconsistency between the files. - some casts are wrong, you can't cast a Predicate to a Predicate, it's not safe. - some methods return a Predicate instead of a Predicate so it will not work if the predicate is used by example in a ?: - some short cuts in the implementation are wrong (by example, testing if there is an element in an iterable before creating the lambda is wrong because the iterable can be populated before the lambda is called. - fix some implementations, BTW I think the methods xor should be removed for the same reason there is no ^^ in C (nobody use xor in test between booleans) cheers, R?mi On 09/10/2011 03:49 AM, stuart.marks at oracle.com wrote: > Changeset: d9e4e3c106a7 > Author: smarks > Date: 2011-09-09 18:48 -0700 > URL: http://hg.openjdk.java.net/lambda/lambda/jdk/rev/d9e4e3c106a7 > > Update initial lambda APIs and tests to use new syntax. > > ! src/share/classes/java/util/functions/Blocks.java > ! src/share/classes/java/util/functions/Mappers.java > ! src/share/classes/java/util/functions/Predicates.java > ! src/share/classes/java/util/functions/Reducers.java > ! test/java/util/Collection/Extensions.java > ! test/java/util/Collection/MOAT.java > ! test/java/util/List/Extensions.java > ! test/java/util/functions/Block/BlocksTest.java > ! test/java/util/functions/Mapper/MappersTest.java > ! test/java/util/functions/Predicate/PredicatesTest.java > ! test/java/util/functions/Reducer/ReducersTest.java > > From forax at univ-mlv.fr Sun Sep 11 04:59:21 2011 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Sun, 11 Sep 2011 13:59:21 +0200 Subject: hg: lambda/lambda/jdk: Update initial lambda APIs and tests to use new syntax. In-Reply-To: <4E6CA11B.9040603@univ-mlv.fr> References: <20110910015030.3ED284750C@hg.openjdk.java.net> <4E6CA11B.9040603@univ-mlv.fr> Message-ID: <4E6CA299.6020709@univ-mlv.fr> better with the patch :) R?mi On 09/11/2011 01:52 PM, R?mi Forax wrote: > Hi all, > I've tried to fix some bugs of the current implementation of > java.util.functions. > > - some constants are still public > (BTW, when the compiler will be able to generate the correct bytecode > for a lambda, these constants will be not needed any more > because constant lambda will be constant by default) > - a lot of generic signature aren't right and there is inconsistency > between the files. > - some casts are wrong, you can't cast a Predicate to > a Predicate, it's not safe. > - some methods return a Predicate instead of a > Predicate so it will not work if the predicate is used by example > in a ?: > - some short cuts in the implementation are wrong (by example, > testing if there is an element in an iterable before creating > the lambda is wrong because the iterable can be populated > before the lambda is called. > - fix some implementations, BTW I think the methods xor should be removed > for the same reason there is no ^^ in C > (nobody use xor in test between booleans) > > cheers, > R?mi > > On 09/10/2011 03:49 AM, stuart.marks at oracle.com wrote: >> Changeset: d9e4e3c106a7 >> Author: smarks >> Date: 2011-09-09 18:48 -0700 >> URL: http://hg.openjdk.java.net/lambda/lambda/jdk/rev/d9e4e3c106a7 >> >> Update initial lambda APIs and tests to use new syntax. >> >> ! src/share/classes/java/util/functions/Blocks.java >> ! src/share/classes/java/util/functions/Mappers.java >> ! src/share/classes/java/util/functions/Predicates.java >> ! src/share/classes/java/util/functions/Reducers.java >> ! test/java/util/Collection/Extensions.java >> ! test/java/util/Collection/MOAT.java >> ! test/java/util/List/Extensions.java >> ! test/java/util/functions/Block/BlocksTest.java >> ! test/java/util/functions/Mapper/MappersTest.java >> ! test/java/util/functions/Predicate/PredicatesTest.java >> ! test/java/util/functions/Reducer/ReducersTest.java >> >> > From forax at univ-mlv.fr Sun Sep 11 07:47:43 2011 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Sun, 11 Sep 2011 16:47:43 +0200 Subject: hg: lambda/lambda/jdk: Update initial lambda APIs and tests to use new syntax. In-Reply-To: <4E6CB1C7.2060904@oracle.com> References: <20110910015030.3ED284750C@hg.openjdk.java.net> <4E6CA11B.9040603@univ-mlv.fr> <4E6CA299.6020709@univ-mlv.fr> <4E6CB1C7.2060904@oracle.com> Message-ID: <4E6CCA0F.4050007@univ-mlv.fr> On 09/11/2011 03:04 PM, Brian Goetz wrote: > Patch eaten by mailing list :( ok, patch inlined R?mi diff --git a/src/share/classes/java/util/functions/Block.java b/src/share/classes/java/util/functions/Block.java --- a/src/share/classes/java/util/functions/Block.java +++ b/src/share/classes/java/util/functions/Block.java @@ -56,7 +56,7 @@ * @return a Block which performs in sequence the {@code apply} method of * this Block and the {@code apply} method of the specified Block operation */ - > Block chain(B second) default Blocks.chain; + Block chain(Block second) default Blocks.chain; /** * Returns a Block which performs in sequence the {@code apply} methods of @@ -68,7 +68,7 @@ * this Block and the {@code apply} methods of the specified Block * operations */ - > Block chain(B... sequence) default Blocks.chain; + Block chain(Block... sequence) default Blocks.chain; /** * Returns a Block which performs in sequence the {@code apply} methods of @@ -80,7 +80,7 @@ * this Block and the {@code apply} methods of the specified Block * operations */ - > Block chain(Iterable sequence) default Blocks.chain; + Block chain(Iterable> sequence) default Blocks.chain; /** * Returns a Block which repeatedly performs the {@code apply} method of diff --git a/src/share/classes/java/util/functions/Blocks.java b/src/share/classes/java/util/functions/Blocks.java --- a/src/share/classes/java/util/functions/Blocks.java +++ b/src/share/classes/java/util/functions/Blocks.java @@ -87,8 +87,8 @@ * @return a Block which performs in sequence the {@code first} and * {@code second} Blocks */ - public static , T> Block chain( - B first, B second) { + public static Block chain( + Block first, Block second) { Objects.requireNonNull(first); Objects.requireNonNull(second); @@ -112,7 +112,7 @@ * operations */ @SafeVarargs - public static , T> Block chain(B... sequence) { + public static Block chain(Block... sequence) { Objects.requireNonNull(sequence); if(0 == sequence.length) { return nop(); @@ -133,17 +133,14 @@ * @param sequence additional Blocks to be chained after the first Block. A * copy is made of the sequence * @return a block that when applied to a {@code t} applies all of the - * specified blocks in sequential oder + * specified blocks in sequential order */ @SafeVarargs - public static , T> Block chain( - B first, B... sequence) { + public static Block chain( + Block first, Block... sequence) { Objects.requireNonNull(first); Objects.requireNonNull(sequence); - if(0 == sequence.length) { - return (Block) first; - } - + return t -> { first.apply(t); for (B block : sequence) @@ -159,14 +156,11 @@ * @param components The blocks to be executed. A copy is made of the * components. * @return a block that when applied to a {@code t} applies all of the - * specified blocks in sequential oder. + * specified blocks in sequential order. */ - public static , T> Block chain( - Iterable sequence) { + public static Block chain( + Iterable> sequence) { Objects.requireNonNull(sequence); - if(!sequence.iterator().hasNext()) { - return nop(); - } return t -> { for (B block : sequence) @@ -183,10 +177,10 @@ * @param components The blocks to be executed. A copy is made of the * components. * @return a block that when applied to a {@code t} applies all of the - * specified blocks in sequential oder. + * specified blocks in sequential order. */ - public static , T> Block chain( - Block first, Iterable sequence) { + public static Block chain( + Block first, Iterable> sequence) { Objects.requireNonNull(first); Objects.requireNonNull(sequence); if(!sequence.iterator().hasNext()) { @@ -214,8 +208,9 @@ if(times < 0) { throw new IllegalArgumentException("negative times");} return t -> { - for (int i = 0; i < times; i++) + for (int i = 0; i < times; i++) { block.apply(t); + } }; } @@ -230,13 +225,14 @@ * @return a Block which repeatedly performs the {@code apply} method of * this Block. */ - public static Block whileRepeat(Block block, Predicate decider) { + public static Block whileRepeat(Block block, Predicate decider) { Objects.requireNonNull(block); Objects.requireNonNull(decider); return t -> { - while (decider.eval(t)) + while (decider.eval(t)) { block.apply(t); + } }; } @@ -251,7 +247,7 @@ * @return a Block which repeatedly performs the {@code apply} method of * this Block. */ - public static Block repeatUntil(Block block, Predicate decider) { + public static Block repeatUntil(Block block, Predicate decider) { Objects.requireNonNull(block); Objects.requireNonNull(decider); diff --git a/src/share/classes/java/util/functions/Mappers.java b/src/share/classes/java/util/functions/Mappers.java --- a/src/share/classes/java/util/functions/Mappers.java +++ b/src/share/classes/java/util/functions/Mappers.java @@ -41,13 +41,13 @@ * A mapper which who's {@code map} method returns the provided * input. */ - public static final Mapper IDENTITY = t -> t; + private static final Mapper IDENTITY = t -> t; /** * A mapper which performs a mapping from an object to it's * string representation. */ - public static final Mapper STRING = + private static final Mapper STRING = t -> String.valueOf(t); /** @@ -150,11 +150,11 @@ * @throws NoSuchMethodException when {@code } has no constructor which * takes a {@code } as a parameter. */ - public static Mapper instantiate(final Class clazzT, final Class clazzU) { + public static Mapper instantiate(Class clazzT, Class clazzU) { Objects.requireNonNull(clazzT); Objects.requireNonNull(clazzU); - final Constructor constructor; + Constructor constructor; try { constructor = clazzU.getConstructor(clazzT); } catch(NoSuchMethodException noConstructor) { @@ -184,7 +184,7 @@ * @throws IllegalArgumentException for all values of {@code } not * present in the map */ - public static Mapper forMap(final Map map) { + public static Mapper forMap(Map map) { Objects.requireNonNull(map); return t -> { @@ -208,13 +208,9 @@ * @param defaultValue the value returned by {@code map} method for * {code } values not contained in the provided map */ - public static Mapper forMap(final Map map, final U defaultValue) { + public static Mapper forMap(Map map, U defaultValue) { Objects.requireNonNull(map); - if(map.isEmpty()) { - return constant(defaultValue); - } - return t -> map.containsKey(t) ? map.get(t) : defaultValue; } diff --git a/src/share/classes/java/util/functions/Predicates.java b/src/share/classes/java/util/functions/Predicates.java --- a/src/share/classes/java/util/functions/Predicates.java +++ b/src/share/classes/java/util/functions/Predicates.java @@ -40,24 +40,24 @@ * a predicate that evaluates to {@code true} if the reference * being tested is {@code null}. */ - public static final Predicate IS_NULL = t -> t == null; + private static final Predicate IS_NULL = t -> t == null; /** * a predicate that evaluates to {@code true} if the reference * being tested is not {@code null}. */ - public static final Predicate NON_NULL = t -> t != null; + private static final Predicate NON_NULL = t -> t != null; /** * a predicate who's result is always {@code false}. */ - public static final Predicate FALSE = t -> false; + private static final Predicate FALSE = t -> false; /** * a predicate who's result is always {@code true}. */ - public static final Predicate TRUE = t -> true; + private static final Predicate TRUE = t -> true; /** * singleton utils @@ -73,8 +73,8 @@ * @return a predicate that evaluates to {@code true} if the reference * being tested is {@code null} */ - public static Predicate isNull() { - return IS_NULL; + public static Predicate isNull() { + return (Predicate)IS_NULL; } /** @@ -84,8 +84,8 @@ * @return a predicate that evaluates to {@code true} if the reference * being tested is is non-{@code null} */ - public static Predicate nonNull() { - return NON_NULL; + public static Predicate nonNull() { + return (Predicate)NON_NULL; } /** @@ -93,8 +93,8 @@ * * @return a predicate that always evaluates to {@code false}. */ - public static Predicate alwaysFalse() { - return FALSE; + public static Predicate alwaysFalse() { + return (Predicate)FALSE; } /** @@ -102,8 +102,8 @@ * * @return a predicate that always evaluates to {@code true}. */ - public static Predicate alwaysTrue() { - return TRUE; + public static Predicate alwaysTrue() { + return (Predicate)TRUE; } /** @@ -115,7 +115,7 @@ * @return a predicate that evaluates to {@code true} if the object being * tested is an instance of the provided class */ - public static Predicate instanceOf(Class clazz) { + public static Predicate instanceOf(Class clazz) { return o -> clazz.isInstance(o); } @@ -125,7 +125,7 @@ * @param target The target value to be compared for identity equality. * @return a predicate that who's result is {@code target == object}. */ - public static Predicate isSame(Object target) { + public static Predicate isSame(Object target) { return obj -> obj == target; } @@ -136,7 +136,7 @@ * @param t The target value to be compared for equality. * @return a predicate who's result matches {@code Objects.equals(target, t)} */ - public static Predicate isEqual(Object target) { + public static Predicate isEqual(Object target) { if (null == target) return Predicates.isNull(); else @@ -155,7 +155,7 @@ * is a member of the provided collection. The collection is not defensively * copied so changes to it will alter the behavior of the predicate. */ - public static Predicate contains(Collection target) { + public static Predicate contains(Collection target) { return t -> target.contains(t); } @@ -166,7 +166,7 @@ * @return the composition of the provided mapper and predicate */ public static Predicate compose( - Predicate predicate, Mapper mapper) { + Predicate predicate, Mapper mapper) { return t -> predicate.eval(mapper.map(t)); } @@ -180,8 +180,8 @@ * @return A predicate who's result is the logical inverse of the provided * predicate. */ - public static > Predicate negate( - P predicate) { + public static Predicate negate( + Predicate predicate) { return t -> !predicate.eval(t); } @@ -198,12 +198,8 @@ * @return A predicate who's result is {@code true} iff all component * predicates are {@code true}. */ - public static > Predicate and( - Predicate first, P second) { - if((null != first) && (first == second)) { - return (Predicate) first; - } - + public static Predicate and( + Predicate first, Predicate second) { Objects.requireNonNull(first); Objects.requireNonNull(second); @@ -222,13 +218,10 @@ * @return A predicate who's result is {@code true} iff all component * predicates are {@code true}. */ - public static > Predicate and( - Iterable

predicates) { + public static Predicate and( + Iterable> predicates) { Objects.requireNonNull(predicates); - if (!predicates.iterator().hasNext()) { - throw new IllegalArgumentException("no predicates"); - } - + return t -> { for (P predicate : predicates) { if (!predicate.eval(t)) { @@ -252,13 +245,10 @@ * @return A predicate who's result is {@code true} iff all component * predicates are {@code true}. */ - static > Predicate and( - P first, Iterable

predicates) { + static Predicate and( + P first, Iterable> predicates) { Objects.requireNonNull(first); Objects.requireNonNull(predicates); - if(!predicates.iterator().hasNext()) { - return (Predicate) first; - } return t -> { if (!first.eval(t)) { @@ -286,8 +276,8 @@ * predicates are {@code true}. */ @SafeVarargs - public static > Predicate and( - P... predicates) { + public static Predicate and( + Predicate... predicates) { return and(Arrays.asList(predicates)); } /** @@ -304,8 +294,8 @@ * predicates are {@code true}. */ @SafeVarargs - static > Predicate and( - P first, P... predicates) { + static Predicate and( + Predicate first, Predicate... predicates) { return and(first, Arrays.asList(predicates)); } @@ -322,12 +312,8 @@ * @return A predicate who's result is {@code true} if any component * predicate's result is {@code true}. */ - public static > Predicate or( - Predicate first, P second) { - if((null != first) && (first == second)) { - return (Predicate) first; - } - + public static Predicate or( + Predicate first, Predicate second) { Objects.requireNonNull(first); Objects.requireNonNull(second); @@ -346,13 +332,10 @@ * @return A predicate who's result is {@code true} if any component * predicate's result is {@code true}. */ - public static > Predicate or( - Iterable

predicates) { + public static Predicate or( + Iterable> predicates) { Objects.requireNonNull(predicates); - if (!predicates.iterator().hasNext()) { - throw new IllegalArgumentException("no predicates"); - } - + return t -> { for (P predicate : predicates) { if (predicate.eval(t)) { @@ -375,14 +358,11 @@ * @return A predicate who's result is {@code true} if any component * predicate's result is {@code true}. */ - static > Predicate or( - P first, Iterable

predicates) { + static Predicate or( + Predicate first, Iterable> predicates) { Objects.requireNonNull(first); Objects.requireNonNull(predicates); - if (!predicates.iterator().hasNext()) { - return (Predicate) first; - } - + return t -> { if (first.eval(t)) { return true; @@ -409,8 +389,8 @@ * predicate's result is {@code true}. */ @SafeVarargs - public static > Predicate or( - P... predicates) { + public static Predicate or( + Predicate... predicates) { return or(Arrays.asList(predicates)); } @@ -426,8 +406,8 @@ * predicate's result is {@code true}. */ @SafeVarargs - static > Predicate or( - P first, P... predicates) { + static Predicate or( + Predicate first, Predicate... predicates) { return or(first, Arrays.asList(predicates)); } @@ -444,12 +424,8 @@ * @return a predicate that evaluates to {@code false} if all or none of * the component predicates evaluate to {@code true} */ - public static > Predicate xor( - Predicate first, P second) { - if((null != first) && (first == second)) { - return (Predicate) alwaysFalse(); - } - + public static Predicate xor( + Predicate first, Predicate second) { Objects.requireNonNull(first); Objects.requireNonNull(second); @@ -468,25 +444,23 @@ * @return a predicate that evaluates to {@code false} if all or none of * the component predicates evaluate to {@code true} */ - public static > Predicate xor( - Iterable

predicates) { + public static Predicate xor( + Iterable> predicates) { Objects.requireNonNull(predicates); - if(!predicates.iterator().hasNext()) { - throw new IllegalArgumentException("no predicates"); - } + return t -> { - Boolean initial = null; - for (P predicate : predicates) { - if (null == initial) { - initial = predicate.eval(t); - } else { - if (!(initial ^ predicate.eval(t))) { - return true; - } + Iterator iterator = predicates.iterator(); + if (!iterator.hasNext()) { + return false; + } + boolean initial = iterator.next().eval(t); + while(iterator.hasNext()) { + if (!(initial ^ iterator.next().eval(t))) { + return true; } } - return false; + return value; }; } @@ -502,8 +476,8 @@ * @return a predicate that evaluates to {@code false} if all or none of the * component predicates evaluate to {@code true} */ - static > Predicate xor( - P first, Iterable

predicates) { + static Predicate xor( + P first, Iterable> predicates) { Objects.requireNonNull(first); Objects.requireNonNull(predicates); @@ -531,7 +505,7 @@ * component predicates evaluate to {@code true} */ @SafeVarargs - public static > Predicate xor(P... predicates) { + public static Predicate xor(Predicate... predicates) { return xor(Arrays.asList(predicates)); } @@ -548,8 +522,8 @@ * component predicates evaluate to {@code true} */ @SafeVarargs - static > Predicate xor( - P first, P... predicates) { + static Predicate xor( + P first, Predicate... predicates) { return xor(first, Arrays.asList(predicates)); } } diff --git a/src/share/classes/java/util/functions/Reducers.java b/src/share/classes/java/util/functions/Reducers.java --- a/src/share/classes/java/util/functions/Reducers.java +++ b/src/share/classes/java/util/functions/Reducers.java @@ -38,7 +38,7 @@ /** * A reducer who's {@code reduce} method always returns the base. */ - public static final Reducer NOP = (u, t) -> u; + private static final Reducer NOP = (u, t) -> u; /** * Only utility methods. @@ -92,7 +92,7 @@ * @return the composition of the provided mapper and reducer. */ public static Reducer compose( - Reducer reducer, Mapper mapper) { + Reducer reducer, Mapper mapper) { Objects.requireNonNull(reducer); Objects.requireNonNull(mapper); @@ -116,7 +116,7 @@ * reducer. */ public static Reducer compose( - Reducer reducer, Predicate predicate) { + Reducer reducer, Predicate predicate) { Objects.requireNonNull(reducer); Objects.requireNonNull(predicate); > > On 9/11/2011 7:59 AM, R?mi Forax wrote: >> better with the patch >> >> R?mi >> >> On 09/11/2011 01:52 PM, R?mi Forax wrote: >>> Hi all, >>> I've tried to fix some bugs of the current implementation of >>> java.util.functions. >>> >>> - some constants are still public >>> (BTW, when the compiler will be able to generate the correct bytecode >>> for a lambda, these constants will be not needed any more >>> because constant lambda will be constant by default) >>> - a lot of generic signature aren't right and there is inconsistency >>> between the files. >>> - some casts are wrong, you can't cast a Predicate to >>> a Predicate, it's not safe. >>> - some methods return a Predicate instead of a >>> Predicate so it will not work if the predicate is used by example >>> in a ?: >>> - some short cuts in the implementation are wrong (by example, >>> testing if there is an element in an iterable before creating >>> the lambda is wrong because the iterable can be populated >>> before the lambda is called. >>> - fix some implementations, BTW I think the methods xor should be >>> removed >>> for the same reason there is no ^^ in C >>> (nobody use xor in test between booleans) >>> >>> cheers, >>> R?mi >>> >>> On 09/10/2011 03:49 AM, stuart.marks at oracle.com wrote: >>>> Changeset: d9e4e3c106a7 >>>> Author: smarks >>>> Date: 2011-09-09 18:48 -0700 >>>> URL: http://hg.openjdk.java.net/lambda/lambda/jdk/rev/d9e4e3c106a7 >>>> >>>> Update initial lambda APIs and tests to use new syntax. >>>> >>>> ! src/share/classes/java/util/functions/Blocks.java >>>> ! src/share/classes/java/util/functions/Mappers.java >>>> ! src/share/classes/java/util/functions/Predicates.java >>>> ! src/share/classes/java/util/functions/Reducers.java >>>> ! test/java/util/Collection/Extensions.java >>>> ! test/java/util/Collection/MOAT.java >>>> ! test/java/util/List/Extensions.java >>>> ! test/java/util/functions/Block/BlocksTest.java >>>> ! test/java/util/functions/Mapper/MappersTest.java >>>> ! test/java/util/functions/Predicate/PredicatesTest.java >>>> ! test/java/util/functions/Reducer/ReducersTest.java >>>> >>>> >>> >> >> >> >> > > On 9/11/2011 7:59 AM, R?mi Forax wrote: >> better with the patch :) >> >> R?mi >> >> On 09/11/2011 01:52 PM, R?mi Forax wrote: >>> Hi all, >>> I've tried to fix some bugs of the current implementation of >>> java.util.functions. >>> >>> - some constants are still public >>> (BTW, when the compiler will be able to generate the correct bytecode >>> for a lambda, these constants will be not needed any more >>> because constant lambda will be constant by default) >>> - a lot of generic signature aren't right and there is inconsistency >>> between the files. >>> - some casts are wrong, you can't cast a Predicate to >>> a Predicate, it's not safe. >>> - some methods return a Predicate instead of a >>> Predicate so it will not work if the predicate is used by example >>> in a ?: >>> - some short cuts in the implementation are wrong (by example, >>> testing if there is an element in an iterable before creating >>> the lambda is wrong because the iterable can be populated >>> before the lambda is called. >>> - fix some implementations, BTW I think the methods xor should be >>> removed >>> for the same reason there is no ^^ in C >>> (nobody use xor in test between booleans) >>> >>> cheers, >>> R?mi >>> >>> On 09/10/2011 03:49 AM, stuart.marks at oracle.com wrote: >>>> Changeset: d9e4e3c106a7 >>>> Author: smarks >>>> Date: 2011-09-09 18:48 -0700 >>>> URL: http://hg.openjdk.java.net/lambda/lambda/jdk/rev/d9e4e3c106a7 >>>> >>>> Update initial lambda APIs and tests to use new syntax. >>>> >>>> ! src/share/classes/java/util/functions/Blocks.java >>>> ! src/share/classes/java/util/functions/Mappers.java >>>> ! src/share/classes/java/util/functions/Predicates.java >>>> ! src/share/classes/java/util/functions/Reducers.java >>>> ! test/java/util/Collection/Extensions.java >>>> ! test/java/util/Collection/MOAT.java >>>> ! test/java/util/List/Extensions.java >>>> ! test/java/util/functions/Block/BlocksTest.java >>>> ! test/java/util/functions/Mapper/MappersTest.java >>>> ! test/java/util/functions/Predicate/PredicatesTest.java >>>> ! test/java/util/functions/Reducer/ReducersTest.java >>>> >>>> >>> >> >> >> >> From bobfoster at gmail.com Sun Sep 11 10:30:44 2011 From: bobfoster at gmail.com (Bob Foster) Date: Sun, 11 Sep 2011 10:30:44 -0700 Subject: hg: lambda/lambda/jdk: Update initial lambda APIs and tests to use new syntax. Message-ID: Remi Forax wrote: > BTW I think the methods xor should be removed > for the same reason there is no ^^ in C > (nobody use xor in test between booleans) There is no ^^ in C because xor can't be short-circuited. You can, however, use ^ to combine logical results in C. I've done it. Pedantry aside, you're probably right. :) Bob From collin.fagan at gmail.com Sun Sep 11 18:29:33 2011 From: collin.fagan at gmail.com (Collin Fagan) Date: Sun, 11 Sep 2011 20:29:33 -0500 Subject: hg: lambda/lambda/jdk: Update initial lambda APIs and tests to use new syntax. In-Reply-To: References: Message-ID: I vote to leave xor in. I've had to write it a few times now and it's always frustrating when xor is overlooked. Collin On Sun, Sep 11, 2011 at 12:30 PM, Bob Foster wrote: > Remi Forax wrote: > > > BTW I think the methods xor should be removed > > for the same reason there is no ^^ in C > > (nobody use xor in test between booleans) > > There is no ^^ in C because xor can't be short-circuited. You can, however, > use ^ to combine logical results in C. I've done it. > > Pedantry aside, you're probably right. :) > > Bob > > From stuart.marks at oracle.com Sun Sep 11 22:02:33 2011 From: stuart.marks at oracle.com (Stuart Marks) Date: Sun, 11 Sep 2011 22:02:33 -0700 Subject: hg: lambda/lambda/jdk: Update initial lambda APIs and tests to use new syntax. In-Reply-To: <4E6CA11B.9040603@univ-mlv.fr> References: <20110910015030.3ED284750C@hg.openjdk.java.net> <4E6CA11B.9040603@univ-mlv.fr> Message-ID: <4E6D9269.7030603@oracle.com> Hi R?mi, Thanks for generating this patch. In general, the generic signature changes look pretty good. I had to make some adjustments in order to get things to compile. I've appended and attached an additional patch to be applied on top of yours. Please check it over. With this additional patch applied, everything compiles and the relevant tests pass. (I'm attaching the patch as well as appending it in the message body, since including it in the message body subjects it to line wrapping and whitespace mangling. At least R?mi might receive the attachment intact, even if the rest of the mailing list doesn't.) There were several places where a type parameter was removed. Unfortunately in some cases the method body had declared local variables using that type parameter. I've redeclared those locals to have the expanded type, usually something like Predicate. This simplifies the method signature at the expense of making the method body more complicated. I think this is the right tradeoff, though, as it buries the use of wildcards within the library implementation instead of exposing it to all clients. In the case of Mappers.instantiate(), I had to restore the 'final' declaration on the 'constructor' local variable. Without this declaration the compiler complained that this variable isn't effectively final. Hm, if code compiles and works with a variable declared 'final', and then the code is changed only by removing 'final', shouldn't that variable be effectively final? Maybe it's a compiler bug. R?mi, I think you have push access to the repos, so go ahead and apply my patch and do a push. If you have any trouble, please let me know and I can do it for you. Thanks again. s'marks [patch appended below] On 9/11/11 4:52 AM, R?mi Forax wrote: > Hi all, > I've tried to fix some bugs of the current implementation of > java.util.functions. > > - some constants are still public > (BTW, when the compiler will be able to generate the correct bytecode > for a lambda, these constants will be not needed any more > because constant lambda will be constant by default) > - a lot of generic signature aren't right and there is inconsistency > between the files. > - some casts are wrong, you can't cast a Predicate to > a Predicate, it's not safe. > - some methods return a Predicate instead of a > Predicate so it will not work if the predicate is used by example > in a ?: > - some short cuts in the implementation are wrong (by example, > testing if there is an element in an iterable before creating > the lambda is wrong because the iterable can be populated > before the lambda is called. > - fix some implementations, BTW I think the methods xor should be removed > for the same reason there is no ^^ in C > (nobody use xor in test between booleans) > > cheers, > R?mi diff -r f6aef0811357 src/share/classes/java/util/functions/Blocks.java --- a/src/share/classes/java/util/functions/Blocks.java Sun Sep 11 21:30:34 2011 -0700 +++ b/src/share/classes/java/util/functions/Blocks.java Sun Sep 11 21:44:53 2011 -0700 @@ -87,7 +87,7 @@ * @return a Block which performs in sequence the {@code first} and * {@code second} Blocks */ - public static Block chain( + public static Block chain( Block first, Block second) { Objects.requireNonNull(first); Objects.requireNonNull(second); @@ -119,7 +119,7 @@ } return t -> { - for (B block : sequence) + for (Block block : sequence) block.apply(t); }; } @@ -143,7 +143,7 @@ return t -> { first.apply(t); - for (B block : sequence) + for (Block block : sequence) block.apply(t); }; } @@ -163,7 +163,7 @@ Objects.requireNonNull(sequence); return t -> { - for (B block : sequence) + for (Block block : sequence) block.apply(t); }; } @@ -189,7 +189,7 @@ return t -> { first.apply(t); - for (B block : sequence) + for (Block block : sequence) block.apply(t); }; } diff -r f6aef0811357 src/share/classes/java/util/functions/Mappers.java --- a/src/share/classes/java/util/functions/Mappers.java Sun Sep 11 21:30:34 2011 -0700 +++ b/src/share/classes/java/util/functions/Mappers.java Sun Sep 11 21:44:53 2011 -0700 @@ -154,7 +154,7 @@ Objects.requireNonNull(clazzT); Objects.requireNonNull(clazzU); - Constructor constructor; + final Constructor constructor; try { constructor = clazzU.getConstructor(clazzT); } catch(NoSuchMethodException noConstructor) { diff -r f6aef0811357 src/share/classes/java/util/functions/Predicates.java --- a/src/share/classes/java/util/functions/Predicates.java Sun Sep 11 21:30:34 2011 -0700 +++ b/src/share/classes/java/util/functions/Predicates.java Sun Sep 11 21:44:53 2011 -0700 @@ -26,6 +26,7 @@ import java.util.Arrays; import java.util.Collection; +import java.util.Iterator; import java.util.Objects; /** @@ -70,6 +71,7 @@ * Returns a predicate that evaluates to {@code true} if the reference * being tested is {@code null}. * + * @param the type of values evaluated by the predicate. * @return a predicate that evaluates to {@code true} if the reference * being tested is {@code null} */ @@ -81,6 +83,7 @@ * Returns a predicate that evaluates to {@code true} if the reference * being tested is non-{@code null}. * + * @param the type of values evaluated by the predicate. * @return a predicate that evaluates to {@code true} if the reference * being tested is is non-{@code null} */ @@ -91,6 +94,7 @@ /** * Returns a predicate that always evaluates to {@code false}. * + * @param the type of values evaluated by the predicate. * @return a predicate that always evaluates to {@code false}. */ public static Predicate alwaysFalse() { @@ -100,6 +104,7 @@ /** * Returns a predicate that always evaluates to {@code true}. * + * @param the type of values evaluated by the predicate. * @return a predicate that always evaluates to {@code true}. */ public static Predicate alwaysTrue() { @@ -111,6 +116,7 @@ * tested is an instance of the provided class. If the object being tested * is {@code null} this predicate evaluates to {@code false}. * + * @param the type of values evaluated by the predicate. * @param clazz The target class to be matched by the predicate. * @return a predicate that evaluates to {@code true} if the object being * tested is an instance of the provided class @@ -122,6 +128,7 @@ /** * Returns a predicate that who's result is {@code target == object}. * + * @param the type of values evaluated by the predicate. * @param target The target value to be compared for identity equality. * @return a predicate that who's result is {@code target == object}. */ @@ -133,6 +140,7 @@ * Returns a predicate who's result matches * {@code Objects.equals(target, t)}. * + * @param the type of values evaluated by the predicate. * @param t The target value to be compared for equality. * @return a predicate who's result matches {@code Objects.equals(target, t)} */ @@ -175,13 +183,11 @@ * predicate evaluates to {@code false} * * @param the type of values evaluated by the predicate. - * @param

type of predicates. * @param predicate The predicate to be evaluated. * @return A predicate who's result is the logical inverse of the provided * predicate. */ - public static Predicate negate( - Predicate predicate) { + public static Predicate negate(Predicate predicate) { return t -> !predicate.eval(t); } @@ -192,7 +198,6 @@ * {@code false} predicate. * * @param the type of values evaluated by the predicates. - * @param

type of predicates. * @param first initial component predicate to be evaluated. * @param second additional component predicate to be evaluated. * @return A predicate who's result is {@code true} iff all component @@ -213,7 +218,6 @@ * {@code false} predicate. * * @param the type of values evaluated by the predicates. - * @param

type of predicates. * @param predicates The predicates to be evaluated. * @return A predicate who's result is {@code true} iff all component * predicates are {@code true}. @@ -223,7 +227,7 @@ Objects.requireNonNull(predicates); return t -> { - for (P predicate : predicates) { + for (Predicate predicate : predicates) { if (!predicate.eval(t)) { return false; } @@ -239,14 +243,13 @@ * {@code false} predicate. * * @param the type of values evaluated by the predicates. - * @param

type of predicates. * @param first An initial predicate to be evaluated before the others. * @param predicates The predicates to be evaluated. * @return A predicate who's result is {@code true} iff all component * predicates are {@code true}. */ static Predicate and( - P first, Iterable> predicates) { + Predicate first, Iterable> predicates) { Objects.requireNonNull(first); Objects.requireNonNull(predicates); @@ -254,7 +257,7 @@ if (!first.eval(t)) { return false; } - for (P predicate : predicates) { + for (Predicate predicate : predicates) { if (!predicate.eval(t)) { return false; } @@ -270,7 +273,6 @@ * {@code false} predicate. * * @param the type of values evaluated by the predicates. - * @param

type of predicates. * @param predicates The predicates to be evaluated. * @return A predicate who's result is {@code true} iff all component * predicates are {@code true}. @@ -287,8 +289,7 @@ * {@code false} predicate. * * @param the type of values evaluated by the predicates. - * @param

type of predicates. - * @param first An initial predicate to be evaluated. + * @param first An initial predicate to be evaluated. * @param predicates The predicates to be evaluated. * @return A predicate who's result is {@code true} iff all component * predicates are {@code true}. @@ -306,7 +307,6 @@ * {@code true} predicate. * * @param the type of values evaluated by the predicates. - * @param

type of predicates. * @param first initial component predicate to be evaluated. * @param second additional component predicate to be evaluated. * @return A predicate who's result is {@code true} if any component @@ -327,7 +327,6 @@ * {@code true} predicate. * * @param the type of values evaluated by the predicates. - * @param

type of predicates. * @param predicates The predicates to be evaluated. * @return A predicate who's result is {@code true} if any component * predicate's result is {@code true}. @@ -337,7 +336,7 @@ Objects.requireNonNull(predicates); return t -> { - for (P predicate : predicates) { + for (Predicate predicate : predicates) { if (predicate.eval(t)) { return true; } @@ -353,7 +352,6 @@ * {@code true} predicate. * * @param the type of values evaluated by the predicates. - * @param

type of predicates. * @param predicates The predicates to be evaluated. * @return A predicate who's result is {@code true} if any component * predicate's result is {@code true}. @@ -367,7 +365,7 @@ if (first.eval(t)) { return true; } - for (P predicate : predicates) { + for (Predicate predicate : predicates) { if (predicate.eval(t)) { return true; } @@ -383,7 +381,6 @@ * {@code true} predicate. * * @param the type of values evaluated by the predicates. - * @param

type of predicates. * @param predicates The predicates to be evaluated. * @return A predicate who's result is {@code true} if any component * predicate's result is {@code true}. @@ -418,7 +415,6 @@ * fails to match the first predicate's result. * * @param the type of values evaluated by the predicates. - * @param

type of predicates. * @param first initial component predicate to be evaluated. * @param second additional component predicate to be evaluated. * @return a predicate that evaluates to {@code false} if all or none of @@ -439,7 +435,6 @@ * fails to match the first predicate's result. * * @param the type of values evaluated by the predicates. - * @param

type of predicates. * @param components The predicates to be evaluated. * @return a predicate that evaluates to {@code false} if all or none of * the component predicates evaluate to {@code true} @@ -450,7 +445,7 @@ return t -> { - Iterator iterator = predicates.iterator(); + Iterator> iterator = predicates.iterator(); if (!iterator.hasNext()) { return false; } @@ -460,7 +455,7 @@ return true; } } - return value; + return false; }; } @@ -471,19 +466,18 @@ * fails to match the first predicate's result. * * @param the type of values evaluated by the predicates. - * @param

type of predicates. * @param predicates The predicates to be evaluated. * @return a predicate that evaluates to {@code false} if all or none of the * component predicates evaluate to {@code true} */ - static Predicate xor( - P first, Iterable> predicates) { + static Predicate xor( + Predicate first, Iterable> predicates) { Objects.requireNonNull(first); Objects.requireNonNull(predicates); return t -> { boolean initial = first.eval(t); - for (P predicate : predicates) { + for (Predicate predicate : predicates) { if (!(initial ^ predicate.eval(t))) { return true; } @@ -499,7 +493,6 @@ * fails to match the first predicate's result. * * @param the type of values evaluated by the predicates. - * @param

type of predicates. * @param predicates The predicates to be evaluated. * @return a predicate that evaluates to {@code false} if all or none of the * component predicates evaluate to {@code true} @@ -516,14 +509,13 @@ * fails to match the first predicate's result. * * @param the type of values evaluated by the predicates. - * @param

type of predicates. * @param predicates The predicates to be evaluated. * @return a predicate that evaluates to {@code false} if all or none of the * component predicates evaluate to {@code true} */ @SafeVarargs static Predicate xor( - P first, Predicate... predicates) { + Predicate first, Predicate... predicates) { return xor(first, Arrays.asList(predicates)); } } -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: remi2.pch.txt Url: http://mail.openjdk.java.net/pipermail/lambda-dev/attachments/20110911/7324bb01/attachment-0001.txt From stuart.marks at oracle.com Sun Sep 11 22:12:58 2011 From: stuart.marks at oracle.com (Stuart Marks) Date: Sun, 11 Sep 2011 22:12:58 -0700 Subject: hg: lambda/lambda/jdk: Update initial lambda APIs and tests to use new syntax. In-Reply-To: References: Message-ID: <4E6D94DA.3080703@oracle.com> On 9/11/11 6:29 PM, Collin Fagan wrote: > On Sun, Sep 11, 2011 at 12:30 PM, Bob Foster wrote: > >> Remi Forax wrote: >> >>> BTW I think the methods xor should be removed >>> for the same reason there is no ^^ in C >>> (nobody use xor in test between booleans) >> >> There is no ^^ in C because xor can't be short-circuited. You can, however, >> use ^ to combine logical results in C. I've done it. >> >> Pedantry aside, you're probably right. :) >> >> Bob >> > I vote to leave xor in. I've had to write it a few times now and it's always > frustrating when xor is overlooked. > > Collin The binary xor seems useful, but I find the N-ary xor questionable. Indeed, this was discussed when the functions were initially pushed; see the thread http://mail.openjdk.java.net/pipermail/lambda-dev/2011-August/003772.html in particular the comments from Steven Simpson and David Holmes. The method's doc seems to describe xnor. In addition I don't think there was agreement on the definition of N-ary xor. Even if we did agree, I'm not sure it would actually be useful. :-) So, I'd vote to remove the N-ary xor() variants. s'marks From forax at univ-mlv.fr Mon Sep 12 02:48:31 2011 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Mon, 12 Sep 2011 11:48:31 +0200 Subject: hg: lambda/lambda/jdk: Update initial lambda APIs and tests to use new syntax. In-Reply-To: <4E6D9269.7030603@oracle.com> References: <20110910015030.3ED284750C@hg.openjdk.java.net> <4E6CA11B.9040603@univ-mlv.fr> <4E6D9269.7030603@oracle.com> Message-ID: <4E6DD56F.5000801@univ-mlv.fr> On 09/12/2011 07:02 AM, Stuart Marks wrote: > In the case of Mappers.instantiate(), I had to restore the 'final' > declaration on the 'constructor' local variable. Without this > declaration the compiler complained that this variable isn't > effectively final. Hm, if code compiles and works with a variable > declared 'final', and then the code is changed only by removing > 'final', shouldn't that variable be effectively final? Maybe it's a > compiler bug. Yes, I think it's a compiler bug. Maurizio, here is a small test case: public class EffectivelyFinalLateInit { public static void main(String[] args) { String s; s = "foo"; Runnable r = () -> { System.out.println(s); }; } } compiler output: EffectivelyFinalLateInit.java:5: error: local variable s cannot be referenced Runnable r = () -> { System.out.println(s); }; ^ local variables referenced from the body of a lambda expression must be 'effectively final' R?mi From forax at univ-mlv.fr Mon Sep 12 03:05:18 2011 From: forax at univ-mlv.fr (forax at univ-mlv.fr) Date: Mon, 12 Sep 2011 10:05:18 +0000 Subject: hg: lambda/lambda/jdk: Clean up the initial lambda APIs Message-ID: <20110912100538.363D74759D@hg.openjdk.java.net> Changeset: 673a4304b3c0 Author: forax Date: 2011-09-12 12:02 +0200 URL: http://hg.openjdk.java.net/lambda/lambda/jdk/rev/673a4304b3c0 Clean up the initial lambda APIs Summary: Avoid the declaration of a secondary type variable by using a wildcard Predicate

to Predicate Remove unsafe cast, casting a Predicate to a Predicate, it's not safe. Some Lambda constants are still declared public. Reviewed-by: smarks ! src/share/classes/java/util/functions/Block.java ! src/share/classes/java/util/functions/Blocks.java ! src/share/classes/java/util/functions/Mappers.java ! src/share/classes/java/util/functions/Predicates.java ! src/share/classes/java/util/functions/Reducers.java From maurizio.cimadamore at oracle.com Mon Sep 12 03:27:43 2011 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Mon, 12 Sep 2011 11:27:43 +0100 Subject: hg: lambda/lambda/jdk: Update initial lambda APIs and tests to use new syntax. In-Reply-To: <4E6DD56F.5000801@univ-mlv.fr> References: <20110910015030.3ED284750C@hg.openjdk.java.net> <4E6CA11B.9040603@univ-mlv.fr> <4E6D9269.7030603@oracle.com> <4E6DD56F.5000801@univ-mlv.fr> Message-ID: <4E6DDE9F.6080609@oracle.com> On 12/09/11 10:48, R?mi Forax wrote: > On 09/12/2011 07:02 AM, Stuart Marks wrote: >> In the case of Mappers.instantiate(), I had to restore the 'final' >> declaration on the 'constructor' local variable. Without this >> declaration the compiler complained that this variable isn't >> effectively final. Hm, if code compiles and works with a variable >> declared 'final', and then the code is changed only by removing >> 'final', shouldn't that variable be effectively final? Maybe it's a >> compiler bug. > > Yes, I think it's a compiler bug. Yeah - I know about that - the notion of effectively final only applied to variables that have an initializer. There's a glitch between the compiler and the current spec. Maurizio > > Maurizio, here is a small test case: > public class EffectivelyFinalLateInit { > public static void main(String[] args) { > String s; > s = "foo"; > Runnable r = () -> { System.out.println(s); }; > } > } > > compiler output: > EffectivelyFinalLateInit.java:5: error: local variable s cannot be > referenced > Runnable r = () -> { System.out.println(s); }; > ^ > local variables referenced from the body of a lambda expression must > be 'effectively final' > > > R?mi From cgdecker at gmail.com Mon Sep 12 08:28:37 2011 From: cgdecker at gmail.com (Colin Decker) Date: Mon, 12 Sep 2011 11:28:37 -0400 Subject: hg: lambda/lambda/jdk: Update initial lambda APIs and tests to use new syntax. In-Reply-To: <4E6CA11B.9040603@univ-mlv.fr> References: <20110910015030.3ED284750C@hg.openjdk.java.net> <4E6CA11B.9040603@univ-mlv.fr> Message-ID: On Sun, Sep 11, 2011 at 7:52 AM, R?mi Forax wrote: > > - some casts are wrong, you can't cast a Predicate to > a Predicate, it's not safe. > What isn't safe about it? If it weren't safe, it wouldn't be safe to cast Predicates to Predicate as you later advocate. > - some methods return a Predicate instead of a > Predicate so it will not work if the predicate is used by example > in a ?: > It isn't a bug for the methods to return the actual type of the predicate and I don't recall having seen any valid arguments in the last discussion as to why they should return Predicate. From maurizio.cimadamore at oracle.com Mon Sep 12 09:14:54 2011 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Mon, 12 Sep 2011 17:14:54 +0100 Subject: hg: lambda/lambda/jdk: Update initial lambda APIs and tests to use new syntax. In-Reply-To: References: <20110910015030.3ED284750C@hg.openjdk.java.net> <4E6CA11B.9040603@univ-mlv.fr> Message-ID: <4E6E2FFE.8020505@oracle.com> On 12/09/11 16:28, Colin Decker wrote: > On Sun, Sep 11, 2011 at 7:52 AM, R?mi Forax wrote: >> - some casts are wrong, you can't cast a Predicate to >> a Predicate, it's not safe. >> > What isn't safe about it? If it weren't safe, it wouldn't be safe to cast > Predicates to Predicate as you later advocate. From a language perspective, both casts are unsafe. i.e. class Foo { Foo(X x) { this.x = x); X x; } Foo fn = new Foo(""); Foo fnn = (Foo)fn; Number n = fnn.x; //runtime class cast exception Similar problem happens with Foo -> Foo case: Foo unsafe() { return (Foo)new Foo(""); } Foo fnn = unsafe(); Number n = fnn.x; //runtime class cast exception In the case of predicate however, since predicate consumes values of type T, it is not possible to reproduce the problem - given the shape of Predicate, a Predicate is always 'stricter' than a Predicate (i.e. the arguments passed to the first can safely be passed to the second). As such the cast can be considered as pseudo-safe, even though, strictly speaking, it is not (thanks to the fact that the type parameter of Predicate only occurs in a contravariant position). Maurizio > >> - some methods return a Predicate instead of a >> Predicate so it will not work if the predicate is used by example >> in a ?: >> > It isn't a bug for the methods to return the actual type of the predicate > and I don't recall having seen any valid arguments in the last discussion as > to why they should return Predicate. > From neal at gafter.com Mon Sep 12 09:19:18 2011 From: neal at gafter.com (Neal Gafter) Date: Mon, 12 Sep 2011 09:19:18 -0700 Subject: hg: lambda/lambda/jdk: Update initial lambda APIs and tests to use new syntax. In-Reply-To: References: <20110910015030.3ED284750C@hg.openjdk.java.net> <4E6CA11B.9040603@univ-mlv.fr> Message-ID: On Mon, Sep 12, 2011 at 8:28 AM, Colin Decker wrote: > On Sun, Sep 11, 2011 at 7:52 AM, R?mi Forax wrote: > > > > - some casts are wrong, you can't cast a Predicate to > > a Predicate, it's not safe. > > > > What isn't safe about it? > Among other things, it is wrong (in the sense that you may be casting something to a type that it isn't). Adding this sort of broken code to the JDK, and encouraging other people to write such code, will be an impediment to ever reifying generics in the future. (If generics were reified, the cast would fail). From stuart.marks at oracle.com Mon Sep 12 09:51:16 2011 From: stuart.marks at oracle.com (stuart.marks at oracle.com) Date: Mon, 12 Sep 2011 16:51:16 +0000 Subject: hg: lambda/lambda/jdk: Additional adjustments to generic parameters. Message-ID: <20110912165134.870F0475AD@hg.openjdk.java.net> Changeset: 4cd31c0af247 Author: smarks Date: 2011-09-12 09:51 -0700 URL: http://hg.openjdk.java.net/lambda/lambda/jdk/rev/4cd31c0af247 Additional adjustments to generic parameters. ! src/share/classes/java/util/functions/Blocks.java ! src/share/classes/java/util/functions/Predicates.java From stuart.marks at oracle.com Mon Sep 12 10:00:11 2011 From: stuart.marks at oracle.com (Stuart Marks) Date: Mon, 12 Sep 2011 10:00:11 -0700 Subject: hg: lambda/lambda/jdk: Additional adjustments to generic parameters. In-Reply-To: <20110912165134.870F0475AD@hg.openjdk.java.net> References: <20110912165134.870F0475AD@hg.openjdk.java.net> Message-ID: <4E6E3A9B.8000301@oracle.com> I had to push a few more fixes in order to get things to compile. s'marks On 9/12/11 9:51 AM, stuart.marks at oracle.com wrote: > Changeset: 4cd31c0af247 > Author: smarks > Date: 2011-09-12 09:51 -0700 > URL: http://hg.openjdk.java.net/lambda/lambda/jdk/rev/4cd31c0af247 > > Additional adjustments to generic parameters. > > ! src/share/classes/java/util/functions/Blocks.java > ! src/share/classes/java/util/functions/Predicates.java > > From forax at univ-mlv.fr Mon Sep 12 10:05:00 2011 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Mon, 12 Sep 2011 19:05:00 +0200 Subject: hg: lambda/lambda/jdk: Additional adjustments to generic parameters. In-Reply-To: <4E6E3A9B.8000301@oracle.com> References: <20110912165134.870F0475AD@hg.openjdk.java.net> <4E6E3A9B.8000301@oracle.com> Message-ID: <4E6E3BBC.6000604@univ-mlv.fr> On 09/12/2011 07:00 PM, Stuart Marks wrote: > I had to push a few more fixes in order to get things to compile. > > s'marks Really weird ! I was able to compile before pushing the things. anyway thanks. R?mi > > On 9/12/11 9:51 AM, stuart.marks at oracle.com wrote: >> Changeset: 4cd31c0af247 >> Author: smarks >> Date: 2011-09-12 09:51 -0700 >> URL: http://hg.openjdk.java.net/lambda/lambda/jdk/rev/4cd31c0af247 >> >> Additional adjustments to generic parameters. >> >> ! src/share/classes/java/util/functions/Blocks.java >> ! src/share/classes/java/util/functions/Predicates.java >> >> From forax at univ-mlv.fr Mon Sep 12 10:06:02 2011 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Mon, 12 Sep 2011 19:06:02 +0200 Subject: hg: lambda/lambda/jdk: Update initial lambda APIs and tests to use new syntax. In-Reply-To: References: <20110910015030.3ED284750C@hg.openjdk.java.net> <4E6CA11B.9040603@univ-mlv.fr> Message-ID: <4E6E3BFA.9040402@univ-mlv.fr> On 09/12/2011 06:19 PM, Neal Gafter wrote: > On Mon, Sep 12, 2011 at 8:28 AM, Colin Decker > wrote: > > On Sun, Sep 11, 2011 at 7:52 AM, R?mi Forax > wrote: > > > > - some casts are wrong, you can't cast a Predicate to > > a Predicate, it's not safe. > > > > What isn't safe about it? > > > Among other things, it is wrong (in the sense that you may be casting > something to a type that it isn't). Adding this sort of broken code > to the JDK, and encouraging other people to write such code, will be > an impediment to ever reifying generics in the future. (If generics > were reified, the cast would fail). And since we now have invokedynamic, reified generics are not far away :) R?mi From bobfoster at gmail.com Mon Sep 12 11:22:39 2011 From: bobfoster at gmail.com (Bob Foster) Date: Mon, 12 Sep 2011 11:22:39 -0700 Subject: hg: lambda/lambda/jdk: Update initial lambda APIs and tests to use new syntax Message-ID: On Sun, 11 Sep 2011 22:12:58 -0700 Stuart Marks wrote: > The binary xor seems useful, but I find the N-ary xor questionable. Indeed, > this was discussed when the functions were initially pushed; see the thread > > http://mail.openjdk.java.net/pipermail/lambda-dev/2011-August/003772.html > > in particular the comments from Steven Simpson and David Holmes. The method's > doc seems to describe xnor. In addition I don't think there was agreement on > the definition of N-ary xor. Even if we did agree, I'm not sure it would > actually be useful. :-) So, I'd vote to remove the N-ary xor() variants. I recall that peculiar thread. :) As Steven Simpson said then: > I would expect N-ary XOR to yield true if the number of true > operands is odd, with no possibility of short-circuiting the result This is not just Steven's opinion, it's the definition of xor. Adding more operands - A ^ B ^ C ^ ... - doesn't change the definition. Should fix the n-ary case as above, change its name or remove it. Bob From David.Holmes at oracle.com Mon Sep 12 23:39:05 2011 From: David.Holmes at oracle.com (David Holmes) Date: Tue, 13 Sep 2011 16:39:05 +1000 Subject: hg: lambda/lambda/jdk: Update initial lambda APIs and tests to use new syntax In-Reply-To: References: Message-ID: <4E6EFA89.3010107@oracle.com> On 13/09/2011 4:22 AM, Bob Foster wrote: > On Sun, 11 Sep 2011 22:12:58 -0700 Stuart Marks wrote: > >> The binary xor seems useful, but I find the N-ary xor questionable. > Indeed, >> this was discussed when the functions were initially pushed; see the > thread >> >> http://mail.openjdk.java.net/pipermail/lambda-dev/2011-August/003772.html >> >> in particular the comments from Steven Simpson and David Holmes. The > method's >> doc seems to describe xnor. In addition I don't think there was agreement > on >> the definition of N-ary xor. Even if we did agree, I'm not sure it would >> actually be useful. :-) So, I'd vote to remove the N-ary xor() variants. > > I recall that peculiar thread. :) As Steven Simpson said then: > >> I would expect N-ary XOR to yield true if the number of true >> operands is odd, with no possibility of short-circuiting the result > > This is not just Steven's opinion, it's the definition of xor. Adding more > operands - A ^ B ^ C ^ ... - doesn't change the definition. Should fix the > n-ary case as above, change its name or remove it. I'd vote for removal. While N-ary XOR seems to have adopted a definition based on associative composition ( A ^ B ^ C = A ^ (B^C) ) this lacks any intuitive interpretation based on "exclusivity": A^B means one or the other may be true but not both. Whereas A^B^C allows all three to be true at once. David > Bob > From forax at univ-mlv.fr Tue Sep 13 00:05:07 2011 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Tue, 13 Sep 2011 09:05:07 +0200 Subject: hg: lambda/lambda/jdk: Update initial lambda APIs and tests to use new syntax. In-Reply-To: References: <20110910015030.3ED284750C@hg.openjdk.java.net> <4E6CA11B.9040603@univ-mlv.fr> <4E6CA299.6020709@univ-mlv.fr> <4E6CB1C7.2060904@oracle.com> <4E6CCA0F.4050007@univ-mlv.fr> Message-ID: <4E6F00A3.2050900@univ-mlv.fr> On 09/12/2011 07:56 PM, Paul Benedict wrote: > If I may ask, why is preferable to type? Mostly for consistency, the collection API is written in that way. Historically, during the development of jdk5, the signatures was using several type variables and when wildcards was introduced (near the end), the signatures was changed to their actual format. I suppose it's because it's more readable once you get use to use wildcards (cf Item 28 of Effective Java [1]) by example void copy(List dst, List src) is in my opinion better than: void copy(List dst, List src) R?mi [1] http://java.sun.com/docs/books/effective/generics.pdf > > On Sun, Sep 11, 2011 at 9:47 AM, R?mi Forax wrote: >> On 09/11/2011 03:04 PM, Brian Goetz wrote: >>> Patch eaten by mailing list :( >> ok, patch inlined >> >> R?mi >> >> diff --git a/src/share/classes/java/util/functions/Block.java >> b/src/share/classes/java/util/functions/Block.java >> --- a/src/share/classes/java/util/functions/Block.java >> +++ b/src/share/classes/java/util/functions/Block.java >> @@ -56,7 +56,7 @@ >> * @return a Block which performs in sequence the {@code apply} >> method of >> * this Block and the {@code apply} method of the specified Block >> operation >> */ >> -> Block chain(B second) default >> Blocks.chain; >> + Block chain(Block second) default Blocks.chain; >> >> /** >> * Returns a Block which performs in sequence the {@code apply} >> methods of >> @@ -68,7 +68,7 @@ >> * this Block and the {@code apply} methods of the specified Block >> * operations >> */ >> -> Block chain(B... sequence) default >> Blocks.chain; >> + Block chain(Block... sequence) default Blocks.chain; >> >> /** >> * Returns a Block which performs in sequence the {@code apply} >> methods of >> @@ -80,7 +80,7 @@ >> * this Block and the {@code apply} methods of the specified Block >> * operations >> */ >> -> Block chain(Iterable sequence) >> default Blocks.chain; >> + Block chain(Iterable> sequence) >> default Blocks.chain; >> >> /** >> * Returns a Block which repeatedly performs the {@code apply} >> method of >> diff --git a/src/share/classes/java/util/functions/Blocks.java >> b/src/share/classes/java/util/functions/Blocks.java >> --- a/src/share/classes/java/util/functions/Blocks.java >> +++ b/src/share/classes/java/util/functions/Blocks.java >> @@ -87,8 +87,8 @@ >> * @return a Block which performs in sequence the {@code first} and >> * {@code second} Blocks >> */ >> - public static, T> Block chain( >> - B first, B second) { >> + public static Block chain( >> + Block first, Block second) { >> Objects.requireNonNull(first); >> Objects.requireNonNull(second); >> >> @@ -112,7 +112,7 @@ >> * operations >> */ >> @SafeVarargs >> - public static, T> Block chain(B... >> sequence) { >> + public static Block chain(Block... sequence) { >> Objects.requireNonNull(sequence); >> if(0 == sequence.length) { >> return nop(); >> @@ -133,17 +133,14 @@ >> * @param sequence additional Blocks to be chained after the first >> Block. A >> * copy is made of the sequence >> * @return a block that when applied to a {@code t} applies all >> of the >> - * specified blocks in sequential oder >> + * specified blocks in sequential order >> */ >> @SafeVarargs >> - public static, T> Block chain( >> - B first, B... sequence) { >> + public static Block chain( >> + Block first, Block... sequence) { >> Objects.requireNonNull(first); >> Objects.requireNonNull(sequence); >> - if(0 == sequence.length) { >> - return (Block) first; >> - } >> - >> + >> return t -> { >> first.apply(t); >> for (B block : sequence) >> @@ -159,14 +156,11 @@ >> * @param components The blocks to be executed. A copy is made of the >> * components. >> * @return a block that when applied to a {@code t} applies all >> of the >> - * specified blocks in sequential oder. >> + * specified blocks in sequential order. >> */ >> - public static, T> Block chain( >> - Iterable sequence) { >> + public static Block chain( >> + Iterable> sequence) { >> Objects.requireNonNull(sequence); >> - if(!sequence.iterator().hasNext()) { >> - return nop(); >> - } >> >> return t -> { >> for (B block : sequence) >> @@ -183,10 +177,10 @@ >> * @param components The blocks to be executed. A copy is made of the >> * components. >> * @return a block that when applied to a {@code t} applies all of >> the >> - * specified blocks in sequential oder. >> + * specified blocks in sequential order. >> */ >> - public static, T> Block chain( >> - Block first, Iterable sequence) { >> + public static Block chain( >> + Block first, Iterable> T>> sequence) { >> Objects.requireNonNull(first); >> Objects.requireNonNull(sequence); >> if(!sequence.iterator().hasNext()) { >> @@ -214,8 +208,9 @@ >> if(times< 0) { throw new IllegalArgumentException("negative >> times");} >> >> return t -> { >> - for (int i = 0; i< times; i++) >> + for (int i = 0; i< times; i++) { >> block.apply(t); >> + } >> }; >> } >> >> @@ -230,13 +225,14 @@ >> * @return a Block which repeatedly performs the {@code apply} >> method of >> * this Block. >> */ >> - public static Block whileRepeat(Block block, Predicate> super T> decider) { >> + public static Block whileRepeat(Block block, >> Predicate decider) { >> Objects.requireNonNull(block); >> Objects.requireNonNull(decider); >> >> return t -> { >> - while (decider.eval(t)) >> + while (decider.eval(t)) { >> block.apply(t); >> + } >> }; >> } >> >> @@ -251,7 +247,7 @@ >> * @return a Block which repeatedly performs the {@code apply} >> method of >> * this Block. >> */ >> - public static Block repeatUntil(Block block, Predicate> super T> decider) { >> + public static Block repeatUntil(Block block, >> Predicate decider) { >> Objects.requireNonNull(block); >> Objects.requireNonNull(decider); >> >> diff --git a/src/share/classes/java/util/functions/Mappers.java >> b/src/share/classes/java/util/functions/Mappers.java >> --- a/src/share/classes/java/util/functions/Mappers.java >> +++ b/src/share/classes/java/util/functions/Mappers.java >> @@ -41,13 +41,13 @@ >> * A mapper which who's {@code map} method returns the provided >> * input. >> */ >> - public static final Mapper IDENTITY = t -> t; >> + private static final Mapper IDENTITY = t -> t; >> >> /** >> * A mapper which performs a mapping from an object to it's >> * string representation. >> */ >> - public static final Mapper STRING = >> + private static final Mapper STRING = >> t -> String.valueOf(t); >> >> /** >> @@ -150,11 +150,11 @@ >> * @throws NoSuchMethodException when {@code} has no >> constructor which >> * takes a {@code} as a parameter. >> */ >> - public static Mapper instantiate(final Class> T> clazzT, final Class clazzU) { >> + public static Mapper instantiate(Class >> clazzT, Class clazzU) { >> Objects.requireNonNull(clazzT); >> Objects.requireNonNull(clazzU); >> >> - final Constructor constructor; >> + Constructor constructor; >> try { >> constructor = clazzU.getConstructor(clazzT); >> } catch(NoSuchMethodException noConstructor) { >> @@ -184,7 +184,7 @@ >> * @throws IllegalArgumentException for all values of {@code} not >> * present in the map >> */ >> - public static Mapper forMap(final Map> extends U> map) { >> + public static Mapper forMap(Map> U> map) { >> Objects.requireNonNull(map); >> >> return t -> { >> @@ -208,13 +208,9 @@ >> * @param defaultValue the value returned by {@code map} method for >> * {code} values not contained in the provided map >> */ >> - public static Mapper forMap(final Map> extends U> map, final U defaultValue) { >> + public static Mapper forMap(Map> U> map, U defaultValue) { >> Objects.requireNonNull(map); >> >> - if(map.isEmpty()) { >> - return constant(defaultValue); >> - } >> - >> return t -> map.containsKey(t) ? map.get(t) : defaultValue; >> } >> >> diff --git a/src/share/classes/java/util/functions/Predicates.java >> b/src/share/classes/java/util/functions/Predicates.java >> --- a/src/share/classes/java/util/functions/Predicates.java >> +++ b/src/share/classes/java/util/functions/Predicates.java >> @@ -40,24 +40,24 @@ >> * a predicate that evaluates to {@code true} if the reference >> * being tested is {@code null}. >> */ >> - public static final Predicate IS_NULL = t -> t == null; >> + private static final Predicate IS_NULL = t -> t == null; >> >> /** >> * a predicate that evaluates to {@code true} if the reference >> * being tested is not {@code null}. >> */ >> - public static final Predicate NON_NULL = t -> t != null; >> + private static final Predicate NON_NULL = t -> t != null; >> >> /** >> * a predicate who's result is always {@code false}. >> */ >> - public static final Predicate FALSE = t -> false; >> + private static final Predicate FALSE = t -> false; >> >> >> /** >> * a predicate who's result is always {@code true}. >> */ >> - public static final Predicate TRUE = t -> true; >> + private static final Predicate TRUE = t -> true; >> >> /** >> * singleton utils >> @@ -73,8 +73,8 @@ >> * @return a predicate that evaluates to {@code true} if the >> reference >> * being tested is {@code null} >> */ >> - public static Predicate isNull() { >> - return IS_NULL; >> + public static Predicate isNull() { >> + return (Predicate)IS_NULL; >> } >> >> /** >> @@ -84,8 +84,8 @@ >> * @return a predicate that evaluates to {@code true} if the >> reference >> * being tested is is non-{@code null} >> */ >> - public static Predicate nonNull() { >> - return NON_NULL; >> + public static Predicate nonNull() { >> + return (Predicate)NON_NULL; >> } >> >> /** >> @@ -93,8 +93,8 @@ >> * >> * @return a predicate that always evaluates to {@code false}. >> */ >> - public static Predicate alwaysFalse() { >> - return FALSE; >> + public static Predicate alwaysFalse() { >> + return (Predicate)FALSE; >> } >> >> /** >> @@ -102,8 +102,8 @@ >> * >> * @return a predicate that always evaluates to {@code true}. >> */ >> - public static Predicate alwaysTrue() { >> - return TRUE; >> + public static Predicate alwaysTrue() { >> + return (Predicate)TRUE; >> } >> >> /** >> @@ -115,7 +115,7 @@ >> * @return a predicate that evaluates to {@code true} if the >> object being >> * tested is an instance of the provided class >> */ >> - public static Predicate instanceOf(Class clazz) { >> + public static Predicate instanceOf(Class clazz) { >> return o -> clazz.isInstance(o); >> } >> >> @@ -125,7 +125,7 @@ >> * @param target The target value to be compared for identity >> equality. >> * @return a predicate that who's result is {@code target == object}. >> */ >> - public static Predicate isSame(Object target) { >> + public static Predicate isSame(Object target) { >> return obj -> obj == target; >> } >> >> @@ -136,7 +136,7 @@ >> * @param t The target value to be compared for equality. >> * @return a predicate who's result matches {@code >> Objects.equals(target, t)} >> */ >> - public static Predicate isEqual(Object target) { >> + public static Predicate isEqual(Object target) { >> if (null == target) >> return Predicates.isNull(); >> else >> @@ -155,7 +155,7 @@ >> * is a member of the provided collection. The collection is not >> defensively >> * copied so changes to it will alter the behavior of the predicate. >> */ >> - public static Predicate contains(Collection >> target) { >> + public static Predicate contains(Collection target) { >> return t -> target.contains(t); >> } >> >> @@ -166,7 +166,7 @@ >> * @return the composition of the provided mapper and predicate >> */ >> public static Predicate compose( >> - Predicate predicate, Mapper mapper) { >> + Predicate predicate, Mapper> V> mapper) { >> return t -> predicate.eval(mapper.map(t)); >> } >> >> @@ -180,8 +180,8 @@ >> * @return A predicate who's result is the logical inverse of the >> provided >> * predicate. >> */ >> - public static> Predicate negate( >> - P predicate) { >> + public static Predicate negate( >> + Predicate predicate) { >> return t -> !predicate.eval(t); >> } >> >> @@ -198,12 +198,8 @@ >> * @return A predicate who's result is {@code true} iff all component >> * predicates are {@code true}. >> */ >> - public static> Predicate and( >> - Predicate first, P second) { >> - if((null != first)&& (first == second)) { >> - return (Predicate) first; >> - } >> - >> + public static Predicate and( >> + Predicate first, Predicate second) { >> Objects.requireNonNull(first); >> Objects.requireNonNull(second); >> >> @@ -222,13 +218,10 @@ >> * @return A predicate who's result is {@code true} iff all component >> * predicates are {@code true}. >> */ >> - public static> Predicate and( >> - Iterable

predicates) { >> + public static Predicate and( >> + Iterable> predicates) { >> Objects.requireNonNull(predicates); >> - if (!predicates.iterator().hasNext()) { >> - throw new IllegalArgumentException("no predicates"); >> - } >> - >> + >> return t -> { >> for (P predicate : predicates) { >> if (!predicate.eval(t)) { >> @@ -252,13 +245,10 @@ >> * @return A predicate who's result is {@code true} iff all component >> * predicates are {@code true}. >> */ >> - static> Predicate and( >> - P first, Iterable

predicates) { >> + static Predicate and( >> + P first, Iterable> >> predicates) { >> Objects.requireNonNull(first); >> Objects.requireNonNull(predicates); >> - if(!predicates.iterator().hasNext()) { >> - return (Predicate) first; >> - } >> >> return t -> { >> if (!first.eval(t)) { >> @@ -286,8 +276,8 @@ >> * predicates are {@code true}. >> */ >> @SafeVarargs >> - public static> Predicate and( >> - P... predicates) { >> + public static Predicate and( >> + Predicate... predicates) { >> return and(Arrays.asList(predicates)); >> } >> /** >> @@ -304,8 +294,8 @@ >> * predicates are {@code true}. >> */ >> @SafeVarargs >> - static> Predicate and( >> - P first, P... predicates) { >> + static Predicate and( >> + Predicate first, Predicate... >> predicates) { >> return and(first, Arrays.asList(predicates)); >> } >> >> @@ -322,12 +312,8 @@ >> * @return A predicate who's result is {@code true} if any component >> * predicate's result is {@code true}. >> */ >> - public static> Predicate or( >> - Predicate first, P second) { >> - if((null != first)&& (first == second)) { >> - return (Predicate) first; >> - } >> - >> + public static Predicate or( >> + Predicate first, Predicate second) { >> Objects.requireNonNull(first); >> Objects.requireNonNull(second); >> >> @@ -346,13 +332,10 @@ >> * @return A predicate who's result is {@code true} if any component >> * predicate's result is {@code true}. >> */ >> - public static> Predicate or( >> - Iterable

predicates) { >> + public static Predicate or( >> + Iterable> predicates) { >> Objects.requireNonNull(predicates); >> - if (!predicates.iterator().hasNext()) { >> - throw new IllegalArgumentException("no predicates"); >> - } >> - >> + >> return t -> { >> for (P predicate : predicates) { >> if (predicate.eval(t)) { >> @@ -375,14 +358,11 @@ >> * @return A predicate who's result is {@code true} if any component >> * predicate's result is {@code true}. >> */ >> - static> Predicate or( >> - P first, Iterable

predicates) { >> + static Predicate or( >> + Predicate first, Iterable> super T>> predicates) { >> Objects.requireNonNull(first); >> Objects.requireNonNull(predicates); >> - if (!predicates.iterator().hasNext()) { >> - return (Predicate) first; >> - } >> - >> + >> return t -> { >> if (first.eval(t)) { >> return true; >> @@ -409,8 +389,8 @@ >> * predicate's result is {@code true}. >> */ >> @SafeVarargs >> - public static> Predicate or( >> - P... predicates) { >> + public static Predicate or( >> + Predicate... predicates) { >> return or(Arrays.asList(predicates)); >> } >> >> @@ -426,8 +406,8 @@ >> * predicate's result is {@code true}. >> */ >> @SafeVarargs >> - static> Predicate or( >> - P first, P... predicates) { >> + static Predicate or( >> + Predicate first, Predicate... >> predicates) { >> return or(first, Arrays.asList(predicates)); >> } >> >> @@ -444,12 +424,8 @@ >> * @return a predicate that evaluates to {@code false} if all or >> none of >> * the component predicates evaluate to {@code true} >> */ >> - public static> Predicate xor( >> - Predicate first, P second) { >> - if((null != first)&& (first == second)) { >> - return (Predicate) alwaysFalse(); >> - } >> - >> + public static Predicate xor( >> + Predicate first, Predicate second) { >> Objects.requireNonNull(first); >> Objects.requireNonNull(second); >> >> @@ -468,25 +444,23 @@ >> * @return a predicate that evaluates to {@code false} if all or >> none of >> * the component predicates evaluate to {@code true} >> */ >> - public static> Predicate xor( >> - Iterable

predicates) { >> + public static Predicate xor( >> + Iterable> predicates) { >> Objects.requireNonNull(predicates); >> - if(!predicates.iterator().hasNext()) { >> - throw new IllegalArgumentException("no predicates"); >> - } >> + >> >> return t -> { >> - Boolean initial = null; >> - for (P predicate : predicates) { >> - if (null == initial) { >> - initial = predicate.eval(t); >> - } else { >> - if (!(initial ^ predicate.eval(t))) { >> - return true; >> - } >> + Iterator iterator = predicates.iterator(); >> + if (!iterator.hasNext()) { >> + return false; >> + } >> + boolean initial = iterator.next().eval(t); >> + while(iterator.hasNext()) { >> + if (!(initial ^ iterator.next().eval(t))) { >> + return true; >> } >> } >> - return false; >> + return value; >> }; >> } >> >> @@ -502,8 +476,8 @@ >> * @return a predicate that evaluates to {@code false} if all or >> none of the >> * component predicates evaluate to {@code true} >> */ >> - static> Predicate xor( >> - P first, Iterable

predicates) { >> + static Predicate xor( >> + P first, Iterable> >> predicates) { >> Objects.requireNonNull(first); >> Objects.requireNonNull(predicates); >> >> @@ -531,7 +505,7 @@ >> * component predicates evaluate to {@code true} >> */ >> @SafeVarargs >> - public static> Predicate >> xor(P... predicates) { >> + public static Predicate xor(Predicate... >> predicates) { >> return xor(Arrays.asList(predicates)); >> } >> >> @@ -548,8 +522,8 @@ >> * component predicates evaluate to {@code true} >> */ >> @SafeVarargs >> - static> Predicate xor( >> - P first, P... predicates) { >> + static Predicate xor( >> + P first, Predicate... predicates) { >> return xor(first, Arrays.asList(predicates)); >> } >> } >> diff --git a/src/share/classes/java/util/functions/Reducers.java >> b/src/share/classes/java/util/functions/Reducers.java >> --- a/src/share/classes/java/util/functions/Reducers.java >> +++ b/src/share/classes/java/util/functions/Reducers.java >> @@ -38,7 +38,7 @@ >> /** >> * A reducer who's {@code reduce} method always returns the base. >> */ >> - public static final Reducer NOP = (u, t) -> u; >> + private static final Reducer NOP = (u, t) -> u; >> >> /** >> * Only utility methods. >> @@ -92,7 +92,7 @@ >> * @return the composition of the provided mapper and reducer. >> */ >> public static Reducer compose( >> - Reducer reducer, Mapper >> mapper) { >> + Reducer reducer, Mapper> T> mapper) { >> Objects.requireNonNull(reducer); >> Objects.requireNonNull(mapper); >> >> @@ -116,7 +116,7 @@ >> * reducer. >> */ >> public static Reducer compose( >> - Reducer reducer, Predicate predicate) { >> + Reducer reducer, Predicate >> predicate) { >> Objects.requireNonNull(reducer); >> Objects.requireNonNull(predicate); >> >> >>> On 9/11/2011 7:59 AM, R?mi Forax wrote: >>>> better with the patch >>>> >>>> R?mi >>>> >>>> On 09/11/2011 01:52 PM, R?mi Forax wrote: >>>>> Hi all, >>>>> I've tried to fix some bugs of the current implementation of >>>>> java.util.functions. >>>>> >>>>> - some constants are still public >>>>> (BTW, when the compiler will be able to generate the correct bytecode >>>>> for a lambda, these constants will be not needed any more >>>>> because constant lambda will be constant by default) >>>>> - a lot of generic signature aren't right and there is inconsistency >>>>> between the files. >>>>> - some casts are wrong, you can't cast a Predicate to >>>>> a Predicate, it's not safe. >>>>> - some methods return a Predicate instead of a >>>>> Predicate so it will not work if the predicate is used by example >>>>> in a ?: >>>>> - some short cuts in the implementation are wrong (by example, >>>>> testing if there is an element in an iterable before creating >>>>> the lambda is wrong because the iterable can be populated >>>>> before the lambda is called. >>>>> - fix some implementations, BTW I think the methods xor should be >>>>> removed >>>>> for the same reason there is no ^^ in C >>>>> (nobody use xor in test between booleans) >>>>> >>>>> cheers, >>>>> R?mi >>>>> >>>>> On 09/10/2011 03:49 AM, stuart.marks at oracle.com wrote: >>>>>> Changeset: d9e4e3c106a7 >>>>>> Author: smarks >>>>>> Date: 2011-09-09 18:48 -0700 >>>>>> URL: http://hg.openjdk.java.net/lambda/lambda/jdk/rev/d9e4e3c106a7 >>>>>> >>>>>> Update initial lambda APIs and tests to use new syntax. >>>>>> >>>>>> ! src/share/classes/java/util/functions/Blocks.java >>>>>> ! src/share/classes/java/util/functions/Mappers.java >>>>>> ! src/share/classes/java/util/functions/Predicates.java >>>>>> ! src/share/classes/java/util/functions/Reducers.java >>>>>> ! test/java/util/Collection/Extensions.java >>>>>> ! test/java/util/Collection/MOAT.java >>>>>> ! test/java/util/List/Extensions.java >>>>>> ! test/java/util/functions/Block/BlocksTest.java >>>>>> ! test/java/util/functions/Mapper/MappersTest.java >>>>>> ! test/java/util/functions/Predicate/PredicatesTest.java >>>>>> ! test/java/util/functions/Reducer/ReducersTest.java >>>>>> >>>>>> >>>> >>>> >>>> >> >> >>> On 9/11/2011 7:59 AM, R?mi Forax wrote: >>>> better with the patch :) >>>> >>>> R?mi >>>> >>>> On 09/11/2011 01:52 PM, R?mi Forax wrote: >>>>> Hi all, >>>>> I've tried to fix some bugs of the current implementation of >>>>> java.util.functions. >>>>> >>>>> - some constants are still public >>>>> (BTW, when the compiler will be able to generate the correct bytecode >>>>> for a lambda, these constants will be not needed any more >>>>> because constant lambda will be constant by default) >>>>> - a lot of generic signature aren't right and there is inconsistency >>>>> between the files. >>>>> - some casts are wrong, you can't cast a Predicate to >>>>> a Predicate, it's not safe. >>>>> - some methods return a Predicate instead of a >>>>> Predicate so it will not work if the predicate is used by example >>>>> in a ?: >>>>> - some short cuts in the implementation are wrong (by example, >>>>> testing if there is an element in an iterable before creating >>>>> the lambda is wrong because the iterable can be populated >>>>> before the lambda is called. >>>>> - fix some implementations, BTW I think the methods xor should be >>>>> removed >>>>> for the same reason there is no ^^ in C >>>>> (nobody use xor in test between booleans) >>>>> >>>>> cheers, >>>>> R?mi >>>>> >>>>> On 09/10/2011 03:49 AM, stuart.marks at oracle.com wrote: >>>>>> Changeset: d9e4e3c106a7 >>>>>> Author: smarks >>>>>> Date: 2011-09-09 18:48 -0700 >>>>>> URL: http://hg.openjdk.java.net/lambda/lambda/jdk/rev/d9e4e3c106a7 >>>>>> >>>>>> Update initial lambda APIs and tests to use new syntax. >>>>>> >>>>>> ! src/share/classes/java/util/functions/Blocks.java >>>>>> ! src/share/classes/java/util/functions/Mappers.java >>>>>> ! src/share/classes/java/util/functions/Predicates.java >>>>>> ! src/share/classes/java/util/functions/Reducers.java >>>>>> ! test/java/util/Collection/Extensions.java >>>>>> ! test/java/util/Collection/MOAT.java >>>>>> ! test/java/util/List/Extensions.java >>>>>> ! test/java/util/functions/Block/BlocksTest.java >>>>>> ! test/java/util/functions/Mapper/MappersTest.java >>>>>> ! test/java/util/functions/Predicate/PredicatesTest.java >>>>>> ! test/java/util/functions/Reducer/ReducersTest.java >>>>>> >>>>>> >>>> >>>> >>>> >> >> From peter.levart at marand.si Tue Sep 13 00:20:40 2011 From: peter.levart at marand.si (Peter Levart) Date: Tue, 13 Sep 2011 09:20:40 +0200 Subject: hg: lambda/lambda/jdk: Update initial lambda APIs and tests to use new syntax. In-Reply-To: <4E6F00A3.2050900@univ-mlv.fr> References: <20110910015030.3ED284750C@hg.openjdk.java.net> <4E6F00A3.2050900@univ-mlv.fr> Message-ID: <201109130920.41007.peter.levart@marand.si> On 09/13/11, R?mi Forax wrote: > On 09/12/2011 07:56 PM, Paul Benedict wrote: > > If I may ask, why is preferable to type? > > Mostly for consistency, the collection API is written in that way. > Historically, during the development of jdk5, the signatures was using > several type variables > and when wildcards was introduced (near the end), the signatures was > changed to their > actual format. > > I suppose it's because it's more readable once you get use to use wildcards > (cf Item 28 of Effective Java [1]) > by example > void copy(List dst, List src) > is in my opinion better than: > void copy(List dst, List src) > What about: void copy(List dst, List src) Isn't this the equivalent of: void copy(List dst, List src) ...but using wildcard instead? Peter > R?mi > [1] http://java.sun.com/docs/books/effective/generics.pdf > > > > > On Sun, Sep 11, 2011 at 9:47 AM, R?mi Forax wrote: > >> On 09/11/2011 03:04 PM, Brian Goetz wrote: > >>> Patch eaten by mailing list :( > >> ok, patch inlined > >> > >> R?mi > >> > >> diff --git a/src/share/classes/java/util/functions/Block.java > >> b/src/share/classes/java/util/functions/Block.java > >> --- a/src/share/classes/java/util/functions/Block.java > >> +++ b/src/share/classes/java/util/functions/Block.java > >> @@ -56,7 +56,7 @@ > >> * @return a Block which performs in sequence the {@code apply} > >> method of > >> * this Block and the {@code apply} method of the specified Block > >> operation > >> */ > >> -> Block chain(B second) default > >> Blocks.chain; > >> + Block chain(Block second) default Blocks.chain; > >> > >> /** > >> * Returns a Block which performs in sequence the {@code apply} > >> methods of > >> @@ -68,7 +68,7 @@ > >> * this Block and the {@code apply} methods of the specified Block > >> * operations > >> */ > >> -> Block chain(B... sequence) default > >> Blocks.chain; > >> + Block chain(Block... sequence) default Blocks.chain; > >> > >> /** > >> * Returns a Block which performs in sequence the {@code apply} > >> methods of > >> @@ -80,7 +80,7 @@ > >> * this Block and the {@code apply} methods of the specified Block > >> * operations > >> */ > >> -> Block chain(Iterable sequence) > >> default Blocks.chain; > >> + Block chain(Iterable> sequence) > >> default Blocks.chain; > >> > >> /** > >> * Returns a Block which repeatedly performs the {@code apply} > >> method of > >> diff --git a/src/share/classes/java/util/functions/Blocks.java > >> b/src/share/classes/java/util/functions/Blocks.java > >> --- a/src/share/classes/java/util/functions/Blocks.java > >> +++ b/src/share/classes/java/util/functions/Blocks.java > >> @@ -87,8 +87,8 @@ > >> * @return a Block which performs in sequence the {@code first} and > >> * {@code second} Blocks > >> */ > >> - public static, T> Block chain( > >> - B first, B second) { > >> + public static Block chain( > >> + Block first, Block second) { > >> Objects.requireNonNull(first); > >> Objects.requireNonNull(second); > >> > >> @@ -112,7 +112,7 @@ > >> * operations > >> */ > >> @SafeVarargs > >> - public static, T> Block chain(B... > >> sequence) { > >> + public static Block chain(Block... sequence) { > >> Objects.requireNonNull(sequence); > >> if(0 == sequence.length) { > >> return nop(); > >> @@ -133,17 +133,14 @@ > >> * @param sequence additional Blocks to be chained after the first > >> Block. A > >> * copy is made of the sequence > >> * @return a block that when applied to a {@code t} applies all > >> of the > >> - * specified blocks in sequential oder > >> + * specified blocks in sequential order > >> */ > >> @SafeVarargs > >> - public static, T> Block chain( > >> - B first, B... sequence) { > >> + public static Block chain( > >> + Block first, Block... sequence) { > >> Objects.requireNonNull(first); > >> Objects.requireNonNull(sequence); > >> - if(0 == sequence.length) { > >> - return (Block) first; > >> - } > >> - > >> + > >> return t -> { > >> first.apply(t); > >> for (B block : sequence) > >> @@ -159,14 +156,11 @@ > >> * @param components The blocks to be executed. A copy is made of the > >> * components. > >> * @return a block that when applied to a {@code t} applies all > >> of the > >> - * specified blocks in sequential oder. > >> + * specified blocks in sequential order. > >> */ > >> - public static, T> Block chain( > >> - Iterable sequence) { > >> + public static Block chain( > >> + Iterable> sequence) { > >> Objects.requireNonNull(sequence); > >> - if(!sequence.iterator().hasNext()) { > >> - return nop(); > >> - } > >> > >> return t -> { > >> for (B block : sequence) > >> @@ -183,10 +177,10 @@ > >> * @param components The blocks to be executed. A copy is made of the > >> * components. > >> * @return a block that when applied to a {@code t} applies all of > >> the > >> - * specified blocks in sequential oder. > >> + * specified blocks in sequential order. > >> */ > >> - public static, T> Block chain( > >> - Block first, Iterable sequence) { > >> + public static Block chain( > >> + Block first, Iterable >> T>> sequence) { > >> Objects.requireNonNull(first); > >> Objects.requireNonNull(sequence); > >> if(!sequence.iterator().hasNext()) { > >> @@ -214,8 +208,9 @@ > >> if(times< 0) { throw new IllegalArgumentException("negative > >> times");} > >> > >> return t -> { > >> - for (int i = 0; i< times; i++) > >> + for (int i = 0; i< times; i++) { > >> block.apply(t); > >> + } > >> }; > >> } > >> > >> @@ -230,13 +225,14 @@ > >> * @return a Block which repeatedly performs the {@code apply} > >> method of > >> * this Block. > >> */ > >> - public static Block whileRepeat(Block block, Predicate >> super T> decider) { > >> + public static Block whileRepeat(Block block, > >> Predicate decider) { > >> Objects.requireNonNull(block); > >> Objects.requireNonNull(decider); > >> > >> return t -> { > >> - while (decider.eval(t)) > >> + while (decider.eval(t)) { > >> block.apply(t); > >> + } > >> }; > >> } > >> > >> @@ -251,7 +247,7 @@ > >> * @return a Block which repeatedly performs the {@code apply} > >> method of > >> * this Block. > >> */ > >> - public static Block repeatUntil(Block block, Predicate >> super T> decider) { > >> + public static Block repeatUntil(Block block, > >> Predicate decider) { > >> Objects.requireNonNull(block); > >> Objects.requireNonNull(decider); > >> > >> diff --git a/src/share/classes/java/util/functions/Mappers.java > >> b/src/share/classes/java/util/functions/Mappers.java > >> --- a/src/share/classes/java/util/functions/Mappers.java > >> +++ b/src/share/classes/java/util/functions/Mappers.java > >> @@ -41,13 +41,13 @@ > >> * A mapper which who's {@code map} method returns the provided > >> * input. > >> */ > >> - public static final Mapper IDENTITY = t -> t; > >> + private static final Mapper IDENTITY = t -> t; > >> > >> /** > >> * A mapper which performs a mapping from an object to it's > >> * string representation. > >> */ > >> - public static final Mapper STRING = > >> + private static final Mapper STRING = > >> t -> String.valueOf(t); > >> > >> /** > >> @@ -150,11 +150,11 @@ > >> * @throws NoSuchMethodException when {@code} has no > >> constructor which > >> * takes a {@code} as a parameter. > >> */ > >> - public static Mapper instantiate(final Class >> T> clazzT, final Class clazzU) { > >> + public static Mapper instantiate(Class > >> clazzT, Class clazzU) { > >> Objects.requireNonNull(clazzT); > >> Objects.requireNonNull(clazzU); > >> > >> - final Constructor constructor; > >> + Constructor constructor; > >> try { > >> constructor = clazzU.getConstructor(clazzT); > >> } catch(NoSuchMethodException noConstructor) { > >> @@ -184,7 +184,7 @@ > >> * @throws IllegalArgumentException for all values of {@code} not > >> * present in the map > >> */ > >> - public static Mapper forMap(final Map >> extends U> map) { > >> + public static Mapper forMap(Map >> U> map) { > >> Objects.requireNonNull(map); > >> > >> return t -> { > >> @@ -208,13 +208,9 @@ > >> * @param defaultValue the value returned by {@code map} method for > >> * {code} values not contained in the provided map > >> */ > >> - public static Mapper forMap(final Map >> extends U> map, final U defaultValue) { > >> + public static Mapper forMap(Map >> U> map, U defaultValue) { > >> Objects.requireNonNull(map); > >> > >> - if(map.isEmpty()) { > >> - return constant(defaultValue); > >> - } > >> - > >> return t -> map.containsKey(t) ? map.get(t) : defaultValue; > >> } > >> > >> diff --git a/src/share/classes/java/util/functions/Predicates.java > >> b/src/share/classes/java/util/functions/Predicates.java > >> --- a/src/share/classes/java/util/functions/Predicates.java > >> +++ b/src/share/classes/java/util/functions/Predicates.java > >> @@ -40,24 +40,24 @@ > >> * a predicate that evaluates to {@code true} if the reference > >> * being tested is {@code null}. > >> */ > >> - public static final Predicate IS_NULL = t -> t == null; > >> + private static final Predicate IS_NULL = t -> t == null; > >> > >> /** > >> * a predicate that evaluates to {@code true} if the reference > >> * being tested is not {@code null}. > >> */ > >> - public static final Predicate NON_NULL = t -> t != null; > >> + private static final Predicate NON_NULL = t -> t != null; > >> > >> /** > >> * a predicate who's result is always {@code false}. > >> */ > >> - public static final Predicate FALSE = t -> false; > >> + private static final Predicate FALSE = t -> false; > >> > >> > >> /** > >> * a predicate who's result is always {@code true}. > >> */ > >> - public static final Predicate TRUE = t -> true; > >> + private static final Predicate TRUE = t -> true; > >> > >> /** > >> * singleton utils > >> @@ -73,8 +73,8 @@ > >> * @return a predicate that evaluates to {@code true} if the > >> reference > >> * being tested is {@code null} > >> */ > >> - public static Predicate isNull() { > >> - return IS_NULL; > >> + public static Predicate isNull() { > >> + return (Predicate)IS_NULL; > >> } > >> > >> /** > >> @@ -84,8 +84,8 @@ > >> * @return a predicate that evaluates to {@code true} if the > >> reference > >> * being tested is is non-{@code null} > >> */ > >> - public static Predicate nonNull() { > >> - return NON_NULL; > >> + public static Predicate nonNull() { > >> + return (Predicate)NON_NULL; > >> } > >> > >> /** > >> @@ -93,8 +93,8 @@ > >> * > >> * @return a predicate that always evaluates to {@code false}. > >> */ > >> - public static Predicate alwaysFalse() { > >> - return FALSE; > >> + public static Predicate alwaysFalse() { > >> + return (Predicate)FALSE; > >> } > >> > >> /** > >> @@ -102,8 +102,8 @@ > >> * > >> * @return a predicate that always evaluates to {@code true}. > >> */ > >> - public static Predicate alwaysTrue() { > >> - return TRUE; > >> + public static Predicate alwaysTrue() { > >> + return (Predicate)TRUE; > >> } > >> > >> /** > >> @@ -115,7 +115,7 @@ > >> * @return a predicate that evaluates to {@code true} if the > >> object being > >> * tested is an instance of the provided class > >> */ > >> - public static Predicate instanceOf(Class clazz) { > >> + public static Predicate instanceOf(Class clazz) { > >> return o -> clazz.isInstance(o); > >> } > >> > >> @@ -125,7 +125,7 @@ > >> * @param target The target value to be compared for identity > >> equality. > >> * @return a predicate that who's result is {@code target == object}. > >> */ > >> - public static Predicate isSame(Object target) { > >> + public static Predicate isSame(Object target) { > >> return obj -> obj == target; > >> } > >> > >> @@ -136,7 +136,7 @@ > >> * @param t The target value to be compared for equality. > >> * @return a predicate who's result matches {@code > >> Objects.equals(target, t)} > >> */ > >> - public static Predicate isEqual(Object target) { > >> + public static Predicate isEqual(Object target) { > >> if (null == target) > >> return Predicates.isNull(); > >> else > >> @@ -155,7 +155,7 @@ > >> * is a member of the provided collection. The collection is not > >> defensively > >> * copied so changes to it will alter the behavior of the predicate. > >> */ > >> - public static Predicate contains(Collection > >> target) { > >> + public static Predicate contains(Collection target) { > >> return t -> target.contains(t); > >> } > >> > >> @@ -166,7 +166,7 @@ > >> * @return the composition of the provided mapper and predicate > >> */ > >> public static Predicate compose( > >> - Predicate predicate, Mapper mapper) { > >> + Predicate predicate, Mapper >> V> mapper) { > >> return t -> predicate.eval(mapper.map(t)); > >> } > >> > >> @@ -180,8 +180,8 @@ > >> * @return A predicate who's result is the logical inverse of the > >> provided > >> * predicate. > >> */ > >> - public static> Predicate negate( > >> - P predicate) { > >> + public static Predicate negate( > >> + Predicate predicate) { > >> return t -> !predicate.eval(t); > >> } > >> > >> @@ -198,12 +198,8 @@ > >> * @return A predicate who's result is {@code true} iff all component > >> * predicates are {@code true}. > >> */ > >> - public static> Predicate and( > >> - Predicate first, P second) { > >> - if((null != first)&& (first == second)) { > >> - return (Predicate) first; > >> - } > >> - > >> + public static Predicate and( > >> + Predicate first, Predicate second) { > >> Objects.requireNonNull(first); > >> Objects.requireNonNull(second); > >> > >> @@ -222,13 +218,10 @@ > >> * @return A predicate who's result is {@code true} iff all component > >> * predicates are {@code true}. > >> */ > >> - public static> Predicate and( > >> - Iterable

predicates) { > >> + public static Predicate and( > >> + Iterable> predicates) { > >> Objects.requireNonNull(predicates); > >> - if (!predicates.iterator().hasNext()) { > >> - throw new IllegalArgumentException("no predicates"); > >> - } > >> - > >> + > >> return t -> { > >> for (P predicate : predicates) { > >> if (!predicate.eval(t)) { > >> @@ -252,13 +245,10 @@ > >> * @return A predicate who's result is {@code true} iff all component > >> * predicates are {@code true}. > >> */ > >> - static> Predicate and( > >> - P first, Iterable

predicates) { > >> + static Predicate and( > >> + P first, Iterable> > >> predicates) { > >> Objects.requireNonNull(first); > >> Objects.requireNonNull(predicates); > >> - if(!predicates.iterator().hasNext()) { > >> - return (Predicate) first; > >> - } > >> > >> return t -> { > >> if (!first.eval(t)) { > >> @@ -286,8 +276,8 @@ > >> * predicates are {@code true}. > >> */ > >> @SafeVarargs > >> - public static> Predicate and( > >> - P... predicates) { > >> + public static Predicate and( > >> + Predicate... predicates) { > >> return and(Arrays.asList(predicates)); > >> } > >> /** > >> @@ -304,8 +294,8 @@ > >> * predicates are {@code true}. > >> */ > >> @SafeVarargs > >> - static> Predicate and( > >> - P first, P... predicates) { > >> + static Predicate and( > >> + Predicate first, Predicate... > >> predicates) { > >> return and(first, Arrays.asList(predicates)); > >> } > >> > >> @@ -322,12 +312,8 @@ > >> * @return A predicate who's result is {@code true} if any component > >> * predicate's result is {@code true}. > >> */ > >> - public static> Predicate or( > >> - Predicate first, P second) { > >> - if((null != first)&& (first == second)) { > >> - return (Predicate) first; > >> - } > >> - > >> + public static Predicate or( > >> + Predicate first, Predicate second) { > >> Objects.requireNonNull(first); > >> Objects.requireNonNull(second); > >> > >> @@ -346,13 +332,10 @@ > >> * @return A predicate who's result is {@code true} if any component > >> * predicate's result is {@code true}. > >> */ > >> - public static> Predicate or( > >> - Iterable

predicates) { > >> + public static Predicate or( > >> + Iterable> predicates) { > >> Objects.requireNonNull(predicates); > >> - if (!predicates.iterator().hasNext()) { > >> - throw new IllegalArgumentException("no predicates"); > >> - } > >> - > >> + > >> return t -> { > >> for (P predicate : predicates) { > >> if (predicate.eval(t)) { > >> @@ -375,14 +358,11 @@ > >> * @return A predicate who's result is {@code true} if any component > >> * predicate's result is {@code true}. > >> */ > >> - static> Predicate or( > >> - P first, Iterable

predicates) { > >> + static Predicate or( > >> + Predicate first, Iterable >> super T>> predicates) { > >> Objects.requireNonNull(first); > >> Objects.requireNonNull(predicates); > >> - if (!predicates.iterator().hasNext()) { > >> - return (Predicate) first; > >> - } > >> - > >> + > >> return t -> { > >> if (first.eval(t)) { > >> return true; > >> @@ -409,8 +389,8 @@ > >> * predicate's result is {@code true}. > >> */ > >> @SafeVarargs > >> - public static> Predicate or( > >> - P... predicates) { > >> + public static Predicate or( > >> + Predicate... predicates) { > >> return or(Arrays.asList(predicates)); > >> } > >> > >> @@ -426,8 +406,8 @@ > >> * predicate's result is {@code true}. > >> */ > >> @SafeVarargs > >> - static> Predicate or( > >> - P first, P... predicates) { > >> + static Predicate or( > >> + Predicate first, Predicate... > >> predicates) { > >> return or(first, Arrays.asList(predicates)); > >> } > >> > >> @@ -444,12 +424,8 @@ > >> * @return a predicate that evaluates to {@code false} if all or > >> none of > >> * the component predicates evaluate to {@code true} > >> */ > >> - public static> Predicate xor( > >> - Predicate first, P second) { > >> - if((null != first)&& (first == second)) { > >> - return (Predicate) alwaysFalse(); > >> - } > >> - > >> + public static Predicate xor( > >> + Predicate first, Predicate second) { > >> Objects.requireNonNull(first); > >> Objects.requireNonNull(second); > >> > >> @@ -468,25 +444,23 @@ > >> * @return a predicate that evaluates to {@code false} if all or > >> none of > >> * the component predicates evaluate to {@code true} > >> */ > >> - public static> Predicate xor( > >> - Iterable

predicates) { > >> + public static Predicate xor( > >> + Iterable> predicates) { > >> Objects.requireNonNull(predicates); > >> - if(!predicates.iterator().hasNext()) { > >> - throw new IllegalArgumentException("no predicates"); > >> - } > >> + > >> > >> return t -> { > >> - Boolean initial = null; > >> - for (P predicate : predicates) { > >> - if (null == initial) { > >> - initial = predicate.eval(t); > >> - } else { > >> - if (!(initial ^ predicate.eval(t))) { > >> - return true; > >> - } > >> + Iterator iterator = predicates.iterator(); > >> + if (!iterator.hasNext()) { > >> + return false; > >> + } > >> + boolean initial = iterator.next().eval(t); > >> + while(iterator.hasNext()) { > >> + if (!(initial ^ iterator.next().eval(t))) { > >> + return true; > >> } > >> } > >> - return false; > >> + return value; > >> }; > >> } > >> > >> @@ -502,8 +476,8 @@ > >> * @return a predicate that evaluates to {@code false} if all or > >> none of the > >> * component predicates evaluate to {@code true} > >> */ > >> - static> Predicate xor( > >> - P first, Iterable

predicates) { > >> + static Predicate xor( > >> + P first, Iterable> > >> predicates) { > >> Objects.requireNonNull(first); > >> Objects.requireNonNull(predicates); > >> > >> @@ -531,7 +505,7 @@ > >> * component predicates evaluate to {@code true} > >> */ > >> @SafeVarargs > >> - public static> Predicate > >> xor(P... predicates) { > >> + public static Predicate xor(Predicate... > >> predicates) { > >> return xor(Arrays.asList(predicates)); > >> } > >> > >> @@ -548,8 +522,8 @@ > >> * component predicates evaluate to {@code true} > >> */ > >> @SafeVarargs > >> - static> Predicate xor( > >> - P first, P... predicates) { > >> + static Predicate xor( > >> + P first, Predicate... predicates) { > >> return xor(first, Arrays.asList(predicates)); > >> } > >> } > >> diff --git a/src/share/classes/java/util/functions/Reducers.java > >> b/src/share/classes/java/util/functions/Reducers.java > >> --- a/src/share/classes/java/util/functions/Reducers.java > >> +++ b/src/share/classes/java/util/functions/Reducers.java > >> @@ -38,7 +38,7 @@ > >> /** > >> * A reducer who's {@code reduce} method always returns the base. > >> */ > >> - public static final Reducer NOP = (u, t) -> u; > >> + private static final Reducer NOP = (u, t) -> u; > >> > >> /** > >> * Only utility methods. > >> @@ -92,7 +92,7 @@ > >> * @return the composition of the provided mapper and reducer. > >> */ > >> public static Reducer compose( > >> - Reducer reducer, Mapper > >> mapper) { > >> + Reducer reducer, Mapper >> T> mapper) { > >> Objects.requireNonNull(reducer); > >> Objects.requireNonNull(mapper); > >> > >> @@ -116,7 +116,7 @@ > >> * reducer. > >> */ > >> public static Reducer compose( > >> - Reducer reducer, Predicate predicate) { > >> + Reducer reducer, Predicate > >> predicate) { > >> Objects.requireNonNull(reducer); > >> Objects.requireNonNull(predicate); > >> > >> > >>> On 9/11/2011 7:59 AM, R?mi Forax wrote: > >>>> better with the patch > >>>> > >>>> R?mi > >>>> > >>>> On 09/11/2011 01:52 PM, R?mi Forax wrote: > >>>>> Hi all, > >>>>> I've tried to fix some bugs of the current implementation of > >>>>> java.util.functions. > >>>>> > >>>>> - some constants are still public > >>>>> (BTW, when the compiler will be able to generate the correct bytecode > >>>>> for a lambda, these constants will be not needed any more > >>>>> because constant lambda will be constant by default) > >>>>> - a lot of generic signature aren't right and there is inconsistency > >>>>> between the files. > >>>>> - some casts are wrong, you can't cast a Predicate to > >>>>> a Predicate, it's not safe. > >>>>> - some methods return a Predicate instead of a > >>>>> Predicate so it will not work if the predicate is used by example > >>>>> in a ?: > >>>>> - some short cuts in the implementation are wrong (by example, > >>>>> testing if there is an element in an iterable before creating > >>>>> the lambda is wrong because the iterable can be populated > >>>>> before the lambda is called. > >>>>> - fix some implementations, BTW I think the methods xor should be > >>>>> removed > >>>>> for the same reason there is no ^^ in C > >>>>> (nobody use xor in test between booleans) > >>>>> > >>>>> cheers, > >>>>> R?mi > >>>>> > >>>>> On 09/10/2011 03:49 AM, stuart.marks at oracle.com wrote: > >>>>>> Changeset: d9e4e3c106a7 > >>>>>> Author: smarks > >>>>>> Date: 2011-09-09 18:48 -0700 > >>>>>> URL: http://hg.openjdk.java.net/lambda/lambda/jdk/rev/d9e4e3c106a7 > >>>>>> > >>>>>> Update initial lambda APIs and tests to use new syntax. > >>>>>> > >>>>>> ! src/share/classes/java/util/functions/Blocks.java > >>>>>> ! src/share/classes/java/util/functions/Mappers.java > >>>>>> ! src/share/classes/java/util/functions/Predicates.java > >>>>>> ! src/share/classes/java/util/functions/Reducers.java > >>>>>> ! test/java/util/Collection/Extensions.java > >>>>>> ! test/java/util/Collection/MOAT.java > >>>>>> ! test/java/util/List/Extensions.java > >>>>>> ! test/java/util/functions/Block/BlocksTest.java > >>>>>> ! test/java/util/functions/Mapper/MappersTest.java > >>>>>> ! test/java/util/functions/Predicate/PredicatesTest.java > >>>>>> ! test/java/util/functions/Reducer/ReducersTest.java > >>>>>> > >>>>>> > >>>> > >>>> > >>>> > >> > >> > >>> On 9/11/2011 7:59 AM, R?mi Forax wrote: > >>>> better with the patch :) > >>>> > >>>> R?mi > >>>> > >>>> On 09/11/2011 01:52 PM, R?mi Forax wrote: > >>>>> Hi all, > >>>>> I've tried to fix some bugs of the current implementation of > >>>>> java.util.functions. > >>>>> > >>>>> - some constants are still public > >>>>> (BTW, when the compiler will be able to generate the correct bytecode > >>>>> for a lambda, these constants will be not needed any more > >>>>> because constant lambda will be constant by default) > >>>>> - a lot of generic signature aren't right and there is inconsistency > >>>>> between the files. > >>>>> - some casts are wrong, you can't cast a Predicate to > >>>>> a Predicate, it's not safe. > >>>>> - some methods return a Predicate instead of a > >>>>> Predicate so it will not work if the predicate is used by example > >>>>> in a ?: > >>>>> - some short cuts in the implementation are wrong (by example, > >>>>> testing if there is an element in an iterable before creating > >>>>> the lambda is wrong because the iterable can be populated > >>>>> before the lambda is called. > >>>>> - fix some implementations, BTW I think the methods xor should be > >>>>> removed > >>>>> for the same reason there is no ^^ in C > >>>>> (nobody use xor in test between booleans) > >>>>> > >>>>> cheers, > >>>>> R?mi > >>>>> > >>>>> On 09/10/2011 03:49 AM, stuart.marks at oracle.com wrote: > >>>>>> Changeset: d9e4e3c106a7 > >>>>>> Author: smarks > >>>>>> Date: 2011-09-09 18:48 -0700 > >>>>>> URL: http://hg.openjdk.java.net/lambda/lambda/jdk/rev/d9e4e3c106a7 > >>>>>> > >>>>>> Update initial lambda APIs and tests to use new syntax. > >>>>>> > >>>>>> ! src/share/classes/java/util/functions/Blocks.java > >>>>>> ! src/share/classes/java/util/functions/Mappers.java > >>>>>> ! src/share/classes/java/util/functions/Predicates.java > >>>>>> ! src/share/classes/java/util/functions/Reducers.java > >>>>>> ! test/java/util/Collection/Extensions.java > >>>>>> ! test/java/util/Collection/MOAT.java > >>>>>> ! test/java/util/List/Extensions.java > >>>>>> ! test/java/util/functions/Block/BlocksTest.java > >>>>>> ! test/java/util/functions/Mapper/MappersTest.java > >>>>>> ! test/java/util/functions/Predicate/PredicatesTest.java > >>>>>> ! test/java/util/functions/Reducer/ReducersTest.java > >>>>>> > >>>>>> > >>>> > >>>> > >>>> > >> > >> > > > From forax at univ-mlv.fr Tue Sep 13 01:09:07 2011 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Tue, 13 Sep 2011 10:09:07 +0200 Subject: hg: lambda/lambda/jdk: Update initial lambda APIs and tests to use new syntax. In-Reply-To: <201109130920.41007.peter.levart@marand.si> References: <20110910015030.3ED284750C@hg.openjdk.java.net> <4E6F00A3.2050900@univ-mlv.fr> <201109130920.41007.peter.levart@marand.si> Message-ID: <4E6F0FA3.8070907@univ-mlv.fr> On 09/13/2011 09:20 AM, Peter Levart wrote: > On 09/13/11, R?mi Forax wrote: >> On 09/12/2011 07:56 PM, Paul Benedict wrote: >>> If I may ask, why is preferable to type? >> Mostly for consistency, the collection API is written in that way. >> Historically, during the development of jdk5, the signatures was using >> several type variables >> and when wildcards was introduced (near the end), the signatures was >> changed to their >> actual format. >> >> I suppose it's because it's more readable once you get use to use wildcards >> (cf Item 28 of Effective Java [1]) >> by example >> void copy(List dst, List src) >> is in my opinion better than: >> void copy(List dst, List src) >> > What about: > > void copy(List dst, List src) > > Isn't this the equivalent of: > > void copy(List dst, List src) > > ...but using wildcard instead? They are only equivalent if no type argument are specified when calling them and are not override equivalent. R?mi > > Peter > >> R?mi >> [1] http://java.sun.com/docs/books/effective/generics.pdf >> >>> On Sun, Sep 11, 2011 at 9:47 AM, R?mi Forax wrote: >>>> On 09/11/2011 03:04 PM, Brian Goetz wrote: >>>>> Patch eaten by mailing list :( >>>> ok, patch inlined >>>> >>>> R?mi >>>> >>>> diff --git a/src/share/classes/java/util/functions/Block.java >>>> b/src/share/classes/java/util/functions/Block.java >>>> --- a/src/share/classes/java/util/functions/Block.java >>>> +++ b/src/share/classes/java/util/functions/Block.java >>>> @@ -56,7 +56,7 @@ >>>> * @return a Block which performs in sequence the {@code apply} >>>> method of >>>> * this Block and the {@code apply} method of the specified Block >>>> operation >>>> */ >>>> -> Block chain(B second) default >>>> Blocks.chain; >>>> + Block chain(Block second) default Blocks.chain; >>>> >>>> /** >>>> * Returns a Block which performs in sequence the {@code apply} >>>> methods of >>>> @@ -68,7 +68,7 @@ >>>> * this Block and the {@code apply} methods of the specified Block >>>> * operations >>>> */ >>>> -> Block chain(B... sequence) default >>>> Blocks.chain; >>>> + Block chain(Block... sequence) default Blocks.chain; >>>> >>>> /** >>>> * Returns a Block which performs in sequence the {@code apply} >>>> methods of >>>> @@ -80,7 +80,7 @@ >>>> * this Block and the {@code apply} methods of the specified Block >>>> * operations >>>> */ >>>> -> Block chain(Iterable sequence) >>>> default Blocks.chain; >>>> + Block chain(Iterable> sequence) >>>> default Blocks.chain; >>>> >>>> /** >>>> * Returns a Block which repeatedly performs the {@code apply} >>>> method of >>>> diff --git a/src/share/classes/java/util/functions/Blocks.java >>>> b/src/share/classes/java/util/functions/Blocks.java >>>> --- a/src/share/classes/java/util/functions/Blocks.java >>>> +++ b/src/share/classes/java/util/functions/Blocks.java >>>> @@ -87,8 +87,8 @@ >>>> * @return a Block which performs in sequence the {@code first} and >>>> * {@code second} Blocks >>>> */ >>>> - public static, T> Block chain( >>>> - B first, B second) { >>>> + public static Block chain( >>>> + Block first, Block second) { >>>> Objects.requireNonNull(first); >>>> Objects.requireNonNull(second); >>>> >>>> @@ -112,7 +112,7 @@ >>>> * operations >>>> */ >>>> @SafeVarargs >>>> - public static, T> Block chain(B... >>>> sequence) { >>>> + public static Block chain(Block... sequence) { >>>> Objects.requireNonNull(sequence); >>>> if(0 == sequence.length) { >>>> return nop(); >>>> @@ -133,17 +133,14 @@ >>>> * @param sequence additional Blocks to be chained after the first >>>> Block. A >>>> * copy is made of the sequence >>>> * @return a block that when applied to a {@code t} applies all >>>> of the >>>> - * specified blocks in sequential oder >>>> + * specified blocks in sequential order >>>> */ >>>> @SafeVarargs >>>> - public static, T> Block chain( >>>> - B first, B... sequence) { >>>> + public static Block chain( >>>> + Block first, Block... sequence) { >>>> Objects.requireNonNull(first); >>>> Objects.requireNonNull(sequence); >>>> - if(0 == sequence.length) { >>>> - return (Block) first; >>>> - } >>>> - >>>> + >>>> return t -> { >>>> first.apply(t); >>>> for (B block : sequence) >>>> @@ -159,14 +156,11 @@ >>>> * @param components The blocks to be executed. A copy is made of the >>>> * components. >>>> * @return a block that when applied to a {@code t} applies all >>>> of the >>>> - * specified blocks in sequential oder. >>>> + * specified blocks in sequential order. >>>> */ >>>> - public static, T> Block chain( >>>> - Iterable sequence) { >>>> + public static Block chain( >>>> + Iterable> sequence) { >>>> Objects.requireNonNull(sequence); >>>> - if(!sequence.iterator().hasNext()) { >>>> - return nop(); >>>> - } >>>> >>>> return t -> { >>>> for (B block : sequence) >>>> @@ -183,10 +177,10 @@ >>>> * @param components The blocks to be executed. A copy is made of the >>>> * components. >>>> * @return a block that when applied to a {@code t} applies all of >>>> the >>>> - * specified blocks in sequential oder. >>>> + * specified blocks in sequential order. >>>> */ >>>> - public static, T> Block chain( >>>> - Block first, Iterable sequence) { >>>> + public static Block chain( >>>> + Block first, Iterable>>> T>> sequence) { >>>> Objects.requireNonNull(first); >>>> Objects.requireNonNull(sequence); >>>> if(!sequence.iterator().hasNext()) { >>>> @@ -214,8 +208,9 @@ >>>> if(times< 0) { throw new IllegalArgumentException("negative >>>> times");} >>>> >>>> return t -> { >>>> - for (int i = 0; i< times; i++) >>>> + for (int i = 0; i< times; i++) { >>>> block.apply(t); >>>> + } >>>> }; >>>> } >>>> >>>> @@ -230,13 +225,14 @@ >>>> * @return a Block which repeatedly performs the {@code apply} >>>> method of >>>> * this Block. >>>> */ >>>> - public static Block whileRepeat(Block block, Predicate>>> super T> decider) { >>>> + public static Block whileRepeat(Block block, >>>> Predicate decider) { >>>> Objects.requireNonNull(block); >>>> Objects.requireNonNull(decider); >>>> >>>> return t -> { >>>> - while (decider.eval(t)) >>>> + while (decider.eval(t)) { >>>> block.apply(t); >>>> + } >>>> }; >>>> } >>>> >>>> @@ -251,7 +247,7 @@ >>>> * @return a Block which repeatedly performs the {@code apply} >>>> method of >>>> * this Block. >>>> */ >>>> - public static Block repeatUntil(Block block, Predicate>>> super T> decider) { >>>> + public static Block repeatUntil(Block block, >>>> Predicate decider) { >>>> Objects.requireNonNull(block); >>>> Objects.requireNonNull(decider); >>>> >>>> diff --git a/src/share/classes/java/util/functions/Mappers.java >>>> b/src/share/classes/java/util/functions/Mappers.java >>>> --- a/src/share/classes/java/util/functions/Mappers.java >>>> +++ b/src/share/classes/java/util/functions/Mappers.java >>>> @@ -41,13 +41,13 @@ >>>> * A mapper which who's {@code map} method returns the provided >>>> * input. >>>> */ >>>> - public static final Mapper IDENTITY = t -> t; >>>> + private static final Mapper IDENTITY = t -> t; >>>> >>>> /** >>>> * A mapper which performs a mapping from an object to it's >>>> * string representation. >>>> */ >>>> - public static final Mapper STRING = >>>> + private static final Mapper STRING = >>>> t -> String.valueOf(t); >>>> >>>> /** >>>> @@ -150,11 +150,11 @@ >>>> * @throws NoSuchMethodException when {@code} has no >>>> constructor which >>>> * takes a {@code} as a parameter. >>>> */ >>>> - public static Mapper instantiate(final Class>>> T> clazzT, final Class clazzU) { >>>> + public static Mapper instantiate(Class >>>> clazzT, Class clazzU) { >>>> Objects.requireNonNull(clazzT); >>>> Objects.requireNonNull(clazzU); >>>> >>>> - final Constructor constructor; >>>> + Constructor constructor; >>>> try { >>>> constructor = clazzU.getConstructor(clazzT); >>>> } catch(NoSuchMethodException noConstructor) { >>>> @@ -184,7 +184,7 @@ >>>> * @throws IllegalArgumentException for all values of {@code} not >>>> * present in the map >>>> */ >>>> - public static Mapper forMap(final Map>>> extends U> map) { >>>> + public static Mapper forMap(Map>>> U> map) { >>>> Objects.requireNonNull(map); >>>> >>>> return t -> { >>>> @@ -208,13 +208,9 @@ >>>> * @param defaultValue the value returned by {@code map} method for >>>> * {code} values not contained in the provided map >>>> */ >>>> - public static Mapper forMap(final Map>>> extends U> map, final U defaultValue) { >>>> + public static Mapper forMap(Map>>> U> map, U defaultValue) { >>>> Objects.requireNonNull(map); >>>> >>>> - if(map.isEmpty()) { >>>> - return constant(defaultValue); >>>> - } >>>> - >>>> return t -> map.containsKey(t) ? map.get(t) : defaultValue; >>>> } >>>> >>>> diff --git a/src/share/classes/java/util/functions/Predicates.java >>>> b/src/share/classes/java/util/functions/Predicates.java >>>> --- a/src/share/classes/java/util/functions/Predicates.java >>>> +++ b/src/share/classes/java/util/functions/Predicates.java >>>> @@ -40,24 +40,24 @@ >>>> * a predicate that evaluates to {@code true} if the reference >>>> * being tested is {@code null}. >>>> */ >>>> - public static final Predicate IS_NULL = t -> t == null; >>>> + private static final Predicate IS_NULL = t -> t == null; >>>> >>>> /** >>>> * a predicate that evaluates to {@code true} if the reference >>>> * being tested is not {@code null}. >>>> */ >>>> - public static final Predicate NON_NULL = t -> t != null; >>>> + private static final Predicate NON_NULL = t -> t != null; >>>> >>>> /** >>>> * a predicate who's result is always {@code false}. >>>> */ >>>> - public static final Predicate FALSE = t -> false; >>>> + private static final Predicate FALSE = t -> false; >>>> >>>> >>>> /** >>>> * a predicate who's result is always {@code true}. >>>> */ >>>> - public static final Predicate TRUE = t -> true; >>>> + private static final Predicate TRUE = t -> true; >>>> >>>> /** >>>> * singleton utils >>>> @@ -73,8 +73,8 @@ >>>> * @return a predicate that evaluates to {@code true} if the >>>> reference >>>> * being tested is {@code null} >>>> */ >>>> - public static Predicate isNull() { >>>> - return IS_NULL; >>>> + public static Predicate isNull() { >>>> + return (Predicate)IS_NULL; >>>> } >>>> >>>> /** >>>> @@ -84,8 +84,8 @@ >>>> * @return a predicate that evaluates to {@code true} if the >>>> reference >>>> * being tested is is non-{@code null} >>>> */ >>>> - public static Predicate nonNull() { >>>> - return NON_NULL; >>>> + public static Predicate nonNull() { >>>> + return (Predicate)NON_NULL; >>>> } >>>> >>>> /** >>>> @@ -93,8 +93,8 @@ >>>> * >>>> * @return a predicate that always evaluates to {@code false}. >>>> */ >>>> - public static Predicate alwaysFalse() { >>>> - return FALSE; >>>> + public static Predicate alwaysFalse() { >>>> + return (Predicate)FALSE; >>>> } >>>> >>>> /** >>>> @@ -102,8 +102,8 @@ >>>> * >>>> * @return a predicate that always evaluates to {@code true}. >>>> */ >>>> - public static Predicate alwaysTrue() { >>>> - return TRUE; >>>> + public static Predicate alwaysTrue() { >>>> + return (Predicate)TRUE; >>>> } >>>> >>>> /** >>>> @@ -115,7 +115,7 @@ >>>> * @return a predicate that evaluates to {@code true} if the >>>> object being >>>> * tested is an instance of the provided class >>>> */ >>>> - public static Predicate instanceOf(Class clazz) { >>>> + public static Predicate instanceOf(Class clazz) { >>>> return o -> clazz.isInstance(o); >>>> } >>>> >>>> @@ -125,7 +125,7 @@ >>>> * @param target The target value to be compared for identity >>>> equality. >>>> * @return a predicate that who's result is {@code target == object}. >>>> */ >>>> - public static Predicate isSame(Object target) { >>>> + public static Predicate isSame(Object target) { >>>> return obj -> obj == target; >>>> } >>>> >>>> @@ -136,7 +136,7 @@ >>>> * @param t The target value to be compared for equality. >>>> * @return a predicate who's result matches {@code >>>> Objects.equals(target, t)} >>>> */ >>>> - public static Predicate isEqual(Object target) { >>>> + public static Predicate isEqual(Object target) { >>>> if (null == target) >>>> return Predicates.isNull(); >>>> else >>>> @@ -155,7 +155,7 @@ >>>> * is a member of the provided collection. The collection is not >>>> defensively >>>> * copied so changes to it will alter the behavior of the predicate. >>>> */ >>>> - public static Predicate contains(Collection >>>> target) { >>>> + public static Predicate contains(Collection target) { >>>> return t -> target.contains(t); >>>> } >>>> >>>> @@ -166,7 +166,7 @@ >>>> * @return the composition of the provided mapper and predicate >>>> */ >>>> public static Predicate compose( >>>> - Predicate predicate, Mapper mapper) { >>>> + Predicate predicate, Mapper>>> V> mapper) { >>>> return t -> predicate.eval(mapper.map(t)); >>>> } >>>> >>>> @@ -180,8 +180,8 @@ >>>> * @return A predicate who's result is the logical inverse of the >>>> provided >>>> * predicate. >>>> */ >>>> - public static> Predicate negate( >>>> - P predicate) { >>>> + public static Predicate negate( >>>> + Predicate predicate) { >>>> return t -> !predicate.eval(t); >>>> } >>>> >>>> @@ -198,12 +198,8 @@ >>>> * @return A predicate who's result is {@code true} iff all component >>>> * predicates are {@code true}. >>>> */ >>>> - public static> Predicate and( >>>> - Predicate first, P second) { >>>> - if((null != first)&& (first == second)) { >>>> - return (Predicate) first; >>>> - } >>>> - >>>> + public static Predicate and( >>>> + Predicate first, Predicate second) { >>>> Objects.requireNonNull(first); >>>> Objects.requireNonNull(second); >>>> >>>> @@ -222,13 +218,10 @@ >>>> * @return A predicate who's result is {@code true} iff all component >>>> * predicates are {@code true}. >>>> */ >>>> - public static> Predicate and( >>>> - Iterable

predicates) { >>>> + public static Predicate and( >>>> + Iterable> predicates) { >>>> Objects.requireNonNull(predicates); >>>> - if (!predicates.iterator().hasNext()) { >>>> - throw new IllegalArgumentException("no predicates"); >>>> - } >>>> - >>>> + >>>> return t -> { >>>> for (P predicate : predicates) { >>>> if (!predicate.eval(t)) { >>>> @@ -252,13 +245,10 @@ >>>> * @return A predicate who's result is {@code true} iff all component >>>> * predicates are {@code true}. >>>> */ >>>> - static> Predicate and( >>>> - P first, Iterable

predicates) { >>>> + static Predicate and( >>>> + P first, Iterable> >>>> predicates) { >>>> Objects.requireNonNull(first); >>>> Objects.requireNonNull(predicates); >>>> - if(!predicates.iterator().hasNext()) { >>>> - return (Predicate) first; >>>> - } >>>> >>>> return t -> { >>>> if (!first.eval(t)) { >>>> @@ -286,8 +276,8 @@ >>>> * predicates are {@code true}. >>>> */ >>>> @SafeVarargs >>>> - public static> Predicate and( >>>> - P... predicates) { >>>> + public static Predicate and( >>>> + Predicate... predicates) { >>>> return and(Arrays.asList(predicates)); >>>> } >>>> /** >>>> @@ -304,8 +294,8 @@ >>>> * predicates are {@code true}. >>>> */ >>>> @SafeVarargs >>>> - static> Predicate and( >>>> - P first, P... predicates) { >>>> + static Predicate and( >>>> + Predicate first, Predicate... >>>> predicates) { >>>> return and(first, Arrays.asList(predicates)); >>>> } >>>> >>>> @@ -322,12 +312,8 @@ >>>> * @return A predicate who's result is {@code true} if any component >>>> * predicate's result is {@code true}. >>>> */ >>>> - public static> Predicate or( >>>> - Predicate first, P second) { >>>> - if((null != first)&& (first == second)) { >>>> - return (Predicate) first; >>>> - } >>>> - >>>> + public static Predicate or( >>>> + Predicate first, Predicate second) { >>>> Objects.requireNonNull(first); >>>> Objects.requireNonNull(second); >>>> >>>> @@ -346,13 +332,10 @@ >>>> * @return A predicate who's result is {@code true} if any component >>>> * predicate's result is {@code true}. >>>> */ >>>> - public static> Predicate or( >>>> - Iterable

predicates) { >>>> + public static Predicate or( >>>> + Iterable> predicates) { >>>> Objects.requireNonNull(predicates); >>>> - if (!predicates.iterator().hasNext()) { >>>> - throw new IllegalArgumentException("no predicates"); >>>> - } >>>> - >>>> + >>>> return t -> { >>>> for (P predicate : predicates) { >>>> if (predicate.eval(t)) { >>>> @@ -375,14 +358,11 @@ >>>> * @return A predicate who's result is {@code true} if any component >>>> * predicate's result is {@code true}. >>>> */ >>>> - static> Predicate or( >>>> - P first, Iterable

predicates) { >>>> + static Predicate or( >>>> + Predicate first, Iterable>>> super T>> predicates) { >>>> Objects.requireNonNull(first); >>>> Objects.requireNonNull(predicates); >>>> - if (!predicates.iterator().hasNext()) { >>>> - return (Predicate) first; >>>> - } >>>> - >>>> + >>>> return t -> { >>>> if (first.eval(t)) { >>>> return true; >>>> @@ -409,8 +389,8 @@ >>>> * predicate's result is {@code true}. >>>> */ >>>> @SafeVarargs >>>> - public static> Predicate or( >>>> - P... predicates) { >>>> + public static Predicate or( >>>> + Predicate... predicates) { >>>> return or(Arrays.asList(predicates)); >>>> } >>>> >>>> @@ -426,8 +406,8 @@ >>>> * predicate's result is {@code true}. >>>> */ >>>> @SafeVarargs >>>> - static> Predicate or( >>>> - P first, P... predicates) { >>>> + static Predicate or( >>>> + Predicate first, Predicate... >>>> predicates) { >>>> return or(first, Arrays.asList(predicates)); >>>> } >>>> >>>> @@ -444,12 +424,8 @@ >>>> * @return a predicate that evaluates to {@code false} if all or >>>> none of >>>> * the component predicates evaluate to {@code true} >>>> */ >>>> - public static> Predicate xor( >>>> - Predicate first, P second) { >>>> - if((null != first)&& (first == second)) { >>>> - return (Predicate) alwaysFalse(); >>>> - } >>>> - >>>> + public static Predicate xor( >>>> + Predicate first, Predicate second) { >>>> Objects.requireNonNull(first); >>>> Objects.requireNonNull(second); >>>> >>>> @@ -468,25 +444,23 @@ >>>> * @return a predicate that evaluates to {@code false} if all or >>>> none of >>>> * the component predicates evaluate to {@code true} >>>> */ >>>> - public static> Predicate xor( >>>> - Iterable

predicates) { >>>> + public static Predicate xor( >>>> + Iterable> predicates) { >>>> Objects.requireNonNull(predicates); >>>> - if(!predicates.iterator().hasNext()) { >>>> - throw new IllegalArgumentException("no predicates"); >>>> - } >>>> + >>>> >>>> return t -> { >>>> - Boolean initial = null; >>>> - for (P predicate : predicates) { >>>> - if (null == initial) { >>>> - initial = predicate.eval(t); >>>> - } else { >>>> - if (!(initial ^ predicate.eval(t))) { >>>> - return true; >>>> - } >>>> + Iterator iterator = predicates.iterator(); >>>> + if (!iterator.hasNext()) { >>>> + return false; >>>> + } >>>> + boolean initial = iterator.next().eval(t); >>>> + while(iterator.hasNext()) { >>>> + if (!(initial ^ iterator.next().eval(t))) { >>>> + return true; >>>> } >>>> } >>>> - return false; >>>> + return value; >>>> }; >>>> } >>>> >>>> @@ -502,8 +476,8 @@ >>>> * @return a predicate that evaluates to {@code false} if all or >>>> none of the >>>> * component predicates evaluate to {@code true} >>>> */ >>>> - static> Predicate xor( >>>> - P first, Iterable

predicates) { >>>> + static Predicate xor( >>>> + P first, Iterable> >>>> predicates) { >>>> Objects.requireNonNull(first); >>>> Objects.requireNonNull(predicates); >>>> >>>> @@ -531,7 +505,7 @@ >>>> * component predicates evaluate to {@code true} >>>> */ >>>> @SafeVarargs >>>> - public static> Predicate >>>> xor(P... predicates) { >>>> + public static Predicate xor(Predicate... >>>> predicates) { >>>> return xor(Arrays.asList(predicates)); >>>> } >>>> >>>> @@ -548,8 +522,8 @@ >>>> * component predicates evaluate to {@code true} >>>> */ >>>> @SafeVarargs >>>> - static> Predicate xor( >>>> - P first, P... predicates) { >>>> + static Predicate xor( >>>> + P first, Predicate... predicates) { >>>> return xor(first, Arrays.asList(predicates)); >>>> } >>>> } >>>> diff --git a/src/share/classes/java/util/functions/Reducers.java >>>> b/src/share/classes/java/util/functions/Reducers.java >>>> --- a/src/share/classes/java/util/functions/Reducers.java >>>> +++ b/src/share/classes/java/util/functions/Reducers.java >>>> @@ -38,7 +38,7 @@ >>>> /** >>>> * A reducer who's {@code reduce} method always returns the base. >>>> */ >>>> - public static final Reducer NOP = (u, t) -> u; >>>> + private static final Reducer NOP = (u, t) -> u; >>>> >>>> /** >>>> * Only utility methods. >>>> @@ -92,7 +92,7 @@ >>>> * @return the composition of the provided mapper and reducer. >>>> */ >>>> public static Reducer compose( >>>> - Reducer reducer, Mapper >>>> mapper) { >>>> + Reducer reducer, Mapper>>> T> mapper) { >>>> Objects.requireNonNull(reducer); >>>> Objects.requireNonNull(mapper); >>>> >>>> @@ -116,7 +116,7 @@ >>>> * reducer. >>>> */ >>>> public static Reducer compose( >>>> - Reducer reducer, Predicate predicate) { >>>> + Reducer reducer, Predicate >>>> predicate) { >>>> Objects.requireNonNull(reducer); >>>> Objects.requireNonNull(predicate); >>>> >>>> >>>>> On 9/11/2011 7:59 AM, R?mi Forax wrote: >>>>>> better with the patch >>>>>> >>>>>> R?mi >>>>>> >>>>>> On 09/11/2011 01:52 PM, R?mi Forax wrote: >>>>>>> Hi all, >>>>>>> I've tried to fix some bugs of the current implementation of >>>>>>> java.util.functions. >>>>>>> >>>>>>> - some constants are still public >>>>>>> (BTW, when the compiler will be able to generate the correct bytecode >>>>>>> for a lambda, these constants will be not needed any more >>>>>>> because constant lambda will be constant by default) >>>>>>> - a lot of generic signature aren't right and there is inconsistency >>>>>>> between the files. >>>>>>> - some casts are wrong, you can't cast a Predicate to >>>>>>> a Predicate, it's not safe. >>>>>>> - some methods return a Predicate instead of a >>>>>>> Predicate so it will not work if the predicate is used by example >>>>>>> in a ?: >>>>>>> - some short cuts in the implementation are wrong (by example, >>>>>>> testing if there is an element in an iterable before creating >>>>>>> the lambda is wrong because the iterable can be populated >>>>>>> before the lambda is called. >>>>>>> - fix some implementations, BTW I think the methods xor should be >>>>>>> removed >>>>>>> for the same reason there is no ^^ in C >>>>>>> (nobody use xor in test between booleans) >>>>>>> >>>>>>> cheers, >>>>>>> R?mi >>>>>>> >>>>>>> On 09/10/2011 03:49 AM, stuart.marks at oracle.com wrote: >>>>>>>> Changeset: d9e4e3c106a7 >>>>>>>> Author: smarks >>>>>>>> Date: 2011-09-09 18:48 -0700 >>>>>>>> URL: http://hg.openjdk.java.net/lambda/lambda/jdk/rev/d9e4e3c106a7 >>>>>>>> >>>>>>>> Update initial lambda APIs and tests to use new syntax. >>>>>>>> >>>>>>>> ! src/share/classes/java/util/functions/Blocks.java >>>>>>>> ! src/share/classes/java/util/functions/Mappers.java >>>>>>>> ! src/share/classes/java/util/functions/Predicates.java >>>>>>>> ! src/share/classes/java/util/functions/Reducers.java >>>>>>>> ! test/java/util/Collection/Extensions.java >>>>>>>> ! test/java/util/Collection/MOAT.java >>>>>>>> ! test/java/util/List/Extensions.java >>>>>>>> ! test/java/util/functions/Block/BlocksTest.java >>>>>>>> ! test/java/util/functions/Mapper/MappersTest.java >>>>>>>> ! test/java/util/functions/Predicate/PredicatesTest.java >>>>>>>> ! test/java/util/functions/Reducer/ReducersTest.java >>>>>>>> >>>>>>>> >>>>>> >>>>>> >>>> >>>>> On 9/11/2011 7:59 AM, R?mi Forax wrote: >>>>>> better with the patch :) >>>>>> >>>>>> R?mi >>>>>> >>>>>> On 09/11/2011 01:52 PM, R?mi Forax wrote: >>>>>>> Hi all, >>>>>>> I've tried to fix some bugs of the current implementation of >>>>>>> java.util.functions. >>>>>>> >>>>>>> - some constants are still public >>>>>>> (BTW, when the compiler will be able to generate the correct bytecode >>>>>>> for a lambda, these constants will be not needed any more >>>>>>> because constant lambda will be constant by default) >>>>>>> - a lot of generic signature aren't right and there is inconsistency >>>>>>> between the files. >>>>>>> - some casts are wrong, you can't cast a Predicate to >>>>>>> a Predicate, it's not safe. >>>>>>> - some methods return a Predicate instead of a >>>>>>> Predicate so it will not work if the predicate is used by example >>>>>>> in a ?: >>>>>>> - some short cuts in the implementation are wrong (by example, >>>>>>> testing if there is an element in an iterable before creating >>>>>>> the lambda is wrong because the iterable can be populated >>>>>>> before the lambda is called. >>>>>>> - fix some implementations, BTW I think the methods xor should be >>>>>>> removed >>>>>>> for the same reason there is no ^^ in C >>>>>>> (nobody use xor in test between booleans) >>>>>>> >>>>>>> cheers, >>>>>>> R?mi >>>>>>> >>>>>>> On 09/10/2011 03:49 AM, stuart.marks at oracle.com wrote: >>>>>>>> Changeset: d9e4e3c106a7 >>>>>>>> Author: smarks >>>>>>>> Date: 2011-09-09 18:48 -0700 >>>>>>>> URL: http://hg.openjdk.java.net/lambda/lambda/jdk/rev/d9e4e3c106a7 >>>>>>>> >>>>>>>> Update initial lambda APIs and tests to use new syntax. >>>>>>>> >>>>>>>> ! src/share/classes/java/util/functions/Blocks.java >>>>>>>> ! src/share/classes/java/util/functions/Mappers.java >>>>>>>> ! src/share/classes/java/util/functions/Predicates.java >>>>>>>> ! src/share/classes/java/util/functions/Reducers.java >>>>>>>> ! test/java/util/Collection/Extensions.java >>>>>>>> ! test/java/util/Collection/MOAT.java >>>>>>>> ! test/java/util/List/Extensions.java >>>>>>>> ! test/java/util/functions/Block/BlocksTest.java >>>>>>>> ! test/java/util/functions/Mapper/MappersTest.java >>>>>>>> ! test/java/util/functions/Predicate/PredicatesTest.java >>>>>>>> ! test/java/util/functions/Reducer/ReducersTest.java >>>>>>>> >>>>>>>> >>>>>> >>>>>> >>>> >> >> From tronicek at fit.cvut.cz Tue Sep 13 01:40:49 2011 From: tronicek at fit.cvut.cz (=?utf-8?B?IlpkZW7Em2sgVHJvbsOtxI1layI=?=) Date: Tue, 13 Sep 2011 10:40:49 +0200 Subject: hg: lambda/lambda/jdk: Update initial lambda APIs and tests to use new syntax. In-Reply-To: <4E6F00A3.2050900@univ-mlv.fr> References: <20110910015030.3ED284750C@hg.openjdk.java.net> <4E6CA11B.9040603@univ-mlv.fr> <4E6CA299.6020709@univ-mlv.fr> <4E6CB1C7.2060904@oracle.com> <4E6CCA0F.4050007@univ-mlv.fr> <4E6F00A3.2050900@univ-mlv.fr> Message-ID: <36fb05f4099978646fbbfd377827f4b8.squirrel@imap.fit.cvut.cz> R?mi Forax napsal(a): > On 09/12/2011 07:56 PM, Paul Benedict wrote: >> If I may ask, why is preferable to type? > > Mostly for consistency, the collection API is written in that way. > Historically, during the development of jdk5, the signatures was using > several type variables > and when wildcards was introduced (near the end), the signatures was > changed to their > actual format. > > I suppose it's because it's more readable once you get use to use > wildcards > (cf Item 28 of Effective Java [1]) > by example > void copy(List dst, List src) > is in my opinion better than: > void copy(List dst, List src) I think the reason is flexibility. For example, List dst = new ArrayList<>(); List src = ...; // invocation of the method that returns List copy(dst, src); If there was List instead of List in the copy method, it could not compile. Z. -- Zdenek Tronicek FIT CTU in Prague > R?mi > [1] http://java.sun.com/docs/books/effective/generics.pdf > >> >> On Sun, Sep 11, 2011 at 9:47 AM, R?mi Forax wrote: >>> On 09/11/2011 03:04 PM, Brian Goetz wrote: >>>> Patch eaten by mailing list :( >>> ok, patch inlined >>> >>> R?mi >>> >>> diff --git a/src/share/classes/java/util/functions/Block.java >>> b/src/share/classes/java/util/functions/Block.java >>> --- a/src/share/classes/java/util/functions/Block.java >>> +++ b/src/share/classes/java/util/functions/Block.java >>> @@ -56,7 +56,7 @@ >>> * @return a Block which performs in sequence the {@code apply} >>> method of >>> * this Block and the {@code apply} method of the specified Block >>> operation >>> */ >>> -> Block chain(B second) default >>> Blocks.chain; >>> + Block chain(Block second) default Blocks.chain; >>> >>> /** >>> * Returns a Block which performs in sequence the {@code apply} >>> methods of >>> @@ -68,7 +68,7 @@ >>> * this Block and the {@code apply} methods of the specified >>> Block >>> * operations >>> */ >>> -> Block chain(B... sequence) default >>> Blocks.chain; >>> + Block chain(Block... sequence) default >>> Blocks.chain; >>> >>> /** >>> * Returns a Block which performs in sequence the {@code apply} >>> methods of >>> @@ -80,7 +80,7 @@ >>> * this Block and the {@code apply} methods of the specified >>> Block >>> * operations >>> */ >>> -> Block chain(Iterable sequence) >>> default Blocks.chain; >>> + Block chain(Iterable> sequence) >>> default Blocks.chain; >>> >>> /** >>> * Returns a Block which repeatedly performs the {@code apply} >>> method of >>> diff --git a/src/share/classes/java/util/functions/Blocks.java >>> b/src/share/classes/java/util/functions/Blocks.java >>> --- a/src/share/classes/java/util/functions/Blocks.java >>> +++ b/src/share/classes/java/util/functions/Blocks.java >>> @@ -87,8 +87,8 @@ >>> * @return a Block which performs in sequence the {@code first} >>> and >>> * {@code second} Blocks >>> */ >>> - public static, T> Block chain( >>> - B first, B second) { >>> + public static Block chain( >>> + Block first, Block second) { >>> Objects.requireNonNull(first); >>> Objects.requireNonNull(second); >>> >>> @@ -112,7 +112,7 @@ >>> * operations >>> */ >>> @SafeVarargs >>> - public static, T> Block chain(B... >>> sequence) { >>> + public static Block chain(Block... sequence) { >>> Objects.requireNonNull(sequence); >>> if(0 == sequence.length) { >>> return nop(); >>> @@ -133,17 +133,14 @@ >>> * @param sequence additional Blocks to be chained after the >>> first >>> Block. A >>> * copy is made of the sequence >>> * @return a block that when applied to a {@code t} applies all >>> of the >>> - * specified blocks in sequential oder >>> + * specified blocks in sequential order >>> */ >>> @SafeVarargs >>> - public static, T> Block chain( >>> - B first, B... sequence) { >>> + public static Block chain( >>> + Block first, Block... sequence) { >>> Objects.requireNonNull(first); >>> Objects.requireNonNull(sequence); >>> - if(0 == sequence.length) { >>> - return (Block) first; >>> - } >>> - >>> + >>> return t -> { >>> first.apply(t); >>> for (B block : sequence) >>> @@ -159,14 +156,11 @@ >>> * @param components The blocks to be executed. A copy is made of >>> the >>> * components. >>> * @return a block that when applied to a {@code t} applies all >>> of the >>> - * specified blocks in sequential oder. >>> + * specified blocks in sequential order. >>> */ >>> - public static, T> Block chain( >>> - Iterable sequence) { >>> + public static Block chain( >>> + Iterable> sequence) { >>> Objects.requireNonNull(sequence); >>> - if(!sequence.iterator().hasNext()) { >>> - return nop(); >>> - } >>> >>> return t -> { >>> for (B block : sequence) >>> @@ -183,10 +177,10 @@ >>> * @param components The blocks to be executed. A copy is made of >>> the >>> * components. >>> * @return a block that when applied to a {@code t} applies all >>> of >>> the >>> - * specified blocks in sequential oder. >>> + * specified blocks in sequential order. >>> */ >>> - public static, T> Block chain( >>> - Block first, Iterable sequence) { >>> + public static Block chain( >>> + Block first, Iterable>> T>> sequence) { >>> Objects.requireNonNull(first); >>> Objects.requireNonNull(sequence); >>> if(!sequence.iterator().hasNext()) { >>> @@ -214,8 +208,9 @@ >>> if(times< 0) { throw new IllegalArgumentException("negative >>> times");} >>> >>> return t -> { >>> - for (int i = 0; i< times; i++) >>> + for (int i = 0; i< times; i++) { >>> block.apply(t); >>> + } >>> }; >>> } >>> >>> @@ -230,13 +225,14 @@ >>> * @return a Block which repeatedly performs the {@code apply} >>> method of >>> * this Block. >>> */ >>> - public static Block whileRepeat(Block block, >>> Predicate>> super T> decider) { >>> + public static Block whileRepeat(Block block, >>> Predicate decider) { >>> Objects.requireNonNull(block); >>> Objects.requireNonNull(decider); >>> >>> return t -> { >>> - while (decider.eval(t)) >>> + while (decider.eval(t)) { >>> block.apply(t); >>> + } >>> }; >>> } >>> >>> @@ -251,7 +247,7 @@ >>> * @return a Block which repeatedly performs the {@code apply} >>> method of >>> * this Block. >>> */ >>> - public static Block repeatUntil(Block block, >>> Predicate>> super T> decider) { >>> + public static Block repeatUntil(Block block, >>> Predicate decider) { >>> Objects.requireNonNull(block); >>> Objects.requireNonNull(decider); >>> >>> diff --git a/src/share/classes/java/util/functions/Mappers.java >>> b/src/share/classes/java/util/functions/Mappers.java >>> --- a/src/share/classes/java/util/functions/Mappers.java >>> +++ b/src/share/classes/java/util/functions/Mappers.java >>> @@ -41,13 +41,13 @@ >>> * A mapper which who's {@code map} method returns the provided >>> * input. >>> */ >>> - public static final Mapper IDENTITY = t -> t; >>> + private static final Mapper IDENTITY = t -> t; >>> >>> /** >>> * A mapper which performs a mapping from an object to it's >>> * string representation. >>> */ >>> - public static final Mapper STRING = >>> + private static final Mapper STRING = >>> t -> String.valueOf(t); >>> >>> /** >>> @@ -150,11 +150,11 @@ >>> * @throws NoSuchMethodException when {@code} has no >>> constructor which >>> * takes a {@code} as a parameter. >>> */ >>> - public static Mapper instantiate(final Class>> extends >>> T> clazzT, final Class clazzU) { >>> + public static Mapper instantiate(Class >>> clazzT, Class clazzU) { >>> Objects.requireNonNull(clazzT); >>> Objects.requireNonNull(clazzU); >>> >>> - final Constructor constructor; >>> + Constructor constructor; >>> try { >>> constructor = clazzU.getConstructor(clazzT); >>> } catch(NoSuchMethodException noConstructor) { >>> @@ -184,7 +184,7 @@ >>> * @throws IllegalArgumentException for all values of {@code} >>> not >>> * present in the map >>> */ >>> - public static Mapper forMap(final Map>> extends U> map) { >>> + public static Mapper forMap(Map>> U> map) { >>> Objects.requireNonNull(map); >>> >>> return t -> { >>> @@ -208,13 +208,9 @@ >>> * @param defaultValue the value returned by {@code map} method >>> for >>> * {code} values not contained in the provided map >>> */ >>> - public static Mapper forMap(final Map>> extends U> map, final U defaultValue) { >>> + public static Mapper forMap(Map>> U> map, U defaultValue) { >>> Objects.requireNonNull(map); >>> >>> - if(map.isEmpty()) { >>> - return constant(defaultValue); >>> - } >>> - >>> return t -> map.containsKey(t) ? map.get(t) : defaultValue; >>> } >>> >>> diff --git a/src/share/classes/java/util/functions/Predicates.java >>> b/src/share/classes/java/util/functions/Predicates.java >>> --- a/src/share/classes/java/util/functions/Predicates.java >>> +++ b/src/share/classes/java/util/functions/Predicates.java >>> @@ -40,24 +40,24 @@ >>> * a predicate that evaluates to {@code true} if the reference >>> * being tested is {@code null}. >>> */ >>> - public static final Predicate IS_NULL = t -> t == null; >>> + private static final Predicate IS_NULL = t -> t == null; >>> >>> /** >>> * a predicate that evaluates to {@code true} if the reference >>> * being tested is not {@code null}. >>> */ >>> - public static final Predicate NON_NULL = t -> t != null; >>> + private static final Predicate NON_NULL = t -> t != >>> null; >>> >>> /** >>> * a predicate who's result is always {@code false}. >>> */ >>> - public static final Predicate FALSE = t -> false; >>> + private static final Predicate FALSE = t -> false; >>> >>> >>> /** >>> * a predicate who's result is always {@code true}. >>> */ >>> - public static final Predicate TRUE = t -> true; >>> + private static final Predicate TRUE = t -> true; >>> >>> /** >>> * singleton utils >>> @@ -73,8 +73,8 @@ >>> * @return a predicate that evaluates to {@code true} if the >>> reference >>> * being tested is {@code null} >>> */ >>> - public static Predicate isNull() { >>> - return IS_NULL; >>> + public static Predicate isNull() { >>> + return (Predicate)IS_NULL; >>> } >>> >>> /** >>> @@ -84,8 +84,8 @@ >>> * @return a predicate that evaluates to {@code true} if the >>> reference >>> * being tested is is non-{@code null} >>> */ >>> - public static Predicate nonNull() { >>> - return NON_NULL; >>> + public static Predicate nonNull() { >>> + return (Predicate)NON_NULL; >>> } >>> >>> /** >>> @@ -93,8 +93,8 @@ >>> * >>> * @return a predicate that always evaluates to {@code false}. >>> */ >>> - public static Predicate alwaysFalse() { >>> - return FALSE; >>> + public static Predicate alwaysFalse() { >>> + return (Predicate)FALSE; >>> } >>> >>> /** >>> @@ -102,8 +102,8 @@ >>> * >>> * @return a predicate that always evaluates to {@code true}. >>> */ >>> - public static Predicate alwaysTrue() { >>> - return TRUE; >>> + public static Predicate alwaysTrue() { >>> + return (Predicate)TRUE; >>> } >>> >>> /** >>> @@ -115,7 +115,7 @@ >>> * @return a predicate that evaluates to {@code true} if the >>> object being >>> * tested is an instance of the provided class >>> */ >>> - public static Predicate instanceOf(Class clazz) { >>> + public static Predicate instanceOf(Class clazz) { >>> return o -> clazz.isInstance(o); >>> } >>> >>> @@ -125,7 +125,7 @@ >>> * @param target The target value to be compared for identity >>> equality. >>> * @return a predicate that who's result is {@code target == >>> object}. >>> */ >>> - public static Predicate isSame(Object target) { >>> + public static Predicate isSame(Object target) { >>> return obj -> obj == target; >>> } >>> >>> @@ -136,7 +136,7 @@ >>> * @param t The target value to be compared for equality. >>> * @return a predicate who's result matches {@code >>> Objects.equals(target, t)} >>> */ >>> - public static Predicate isEqual(Object target) { >>> + public static Predicate isEqual(Object target) { >>> if (null == target) >>> return Predicates.isNull(); >>> else >>> @@ -155,7 +155,7 @@ >>> * is a member of the provided collection. The collection is not >>> defensively >>> * copied so changes to it will alter the behavior of the >>> predicate. >>> */ >>> - public static Predicate contains(Collection >>> target) { >>> + public static Predicate contains(Collection target) { >>> return t -> target.contains(t); >>> } >>> >>> @@ -166,7 +166,7 @@ >>> * @return the composition of the provided mapper and predicate >>> */ >>> public static Predicate compose( >>> - Predicate predicate, Mapper mapper) { >>> + Predicate predicate, Mapper>> extends >>> V> mapper) { >>> return t -> predicate.eval(mapper.map(t)); >>> } >>> >>> @@ -180,8 +180,8 @@ >>> * @return A predicate who's result is the logical inverse of the >>> provided >>> * predicate. >>> */ >>> - public static> Predicate >>> negate( >>> - P predicate) { >>> + public static Predicate negate( >>> + Predicate predicate) { >>> return t -> !predicate.eval(t); >>> } >>> >>> @@ -198,12 +198,8 @@ >>> * @return A predicate who's result is {@code true} iff all >>> component >>> * predicates are {@code true}. >>> */ >>> - public static> Predicate >>> and( >>> - Predicate first, P second) { >>> - if((null != first)&& (first == second)) { >>> - return (Predicate) first; >>> - } >>> - >>> + public static Predicate and( >>> + Predicate first, Predicate >>> second) { >>> Objects.requireNonNull(first); >>> Objects.requireNonNull(second); >>> >>> @@ -222,13 +218,10 @@ >>> * @return A predicate who's result is {@code true} iff all >>> component >>> * predicates are {@code true}. >>> */ >>> - public static> Predicate >>> and( >>> - Iterable

predicates) { >>> + public static Predicate and( >>> + Iterable> predicates) { >>> Objects.requireNonNull(predicates); >>> - if (!predicates.iterator().hasNext()) { >>> - throw new IllegalArgumentException("no predicates"); >>> - } >>> - >>> + >>> return t -> { >>> for (P predicate : predicates) { >>> if (!predicate.eval(t)) { >>> @@ -252,13 +245,10 @@ >>> * @return A predicate who's result is {@code true} iff all >>> component >>> * predicates are {@code true}. >>> */ >>> - static> Predicate and( >>> - P first, Iterable

predicates) { >>> + static Predicate and( >>> + P first, Iterable> >>> predicates) { >>> Objects.requireNonNull(first); >>> Objects.requireNonNull(predicates); >>> - if(!predicates.iterator().hasNext()) { >>> - return (Predicate) first; >>> - } >>> >>> return t -> { >>> if (!first.eval(t)) { >>> @@ -286,8 +276,8 @@ >>> * predicates are {@code true}. >>> */ >>> @SafeVarargs >>> - public static> Predicate >>> and( >>> - P... predicates) { >>> + public static Predicate and( >>> + Predicate... predicates) { >>> return and(Arrays.asList(predicates)); >>> } >>> /** >>> @@ -304,8 +294,8 @@ >>> * predicates are {@code true}. >>> */ >>> @SafeVarargs >>> - static> Predicate and( >>> - P first, P... predicates) { >>> + static Predicate and( >>> + Predicate first, Predicate... >>> predicates) { >>> return and(first, Arrays.asList(predicates)); >>> } >>> >>> @@ -322,12 +312,8 @@ >>> * @return A predicate who's result is {@code true} if any >>> component >>> * predicate's result is {@code true}. >>> */ >>> - public static> Predicate >>> or( >>> - Predicate first, P second) { >>> - if((null != first)&& (first == second)) { >>> - return (Predicate) first; >>> - } >>> - >>> + public static Predicate or( >>> + Predicate first, Predicate >>> second) { >>> Objects.requireNonNull(first); >>> Objects.requireNonNull(second); >>> >>> @@ -346,13 +332,10 @@ >>> * @return A predicate who's result is {@code true} if any >>> component >>> * predicate's result is {@code true}. >>> */ >>> - public static> Predicate >>> or( >>> - Iterable

predicates) { >>> + public static Predicate or( >>> + Iterable> predicates) { >>> Objects.requireNonNull(predicates); >>> - if (!predicates.iterator().hasNext()) { >>> - throw new IllegalArgumentException("no predicates"); >>> - } >>> - >>> + >>> return t -> { >>> for (P predicate : predicates) { >>> if (predicate.eval(t)) { >>> @@ -375,14 +358,11 @@ >>> * @return A predicate who's result is {@code true} if any >>> component >>> * predicate's result is {@code true}. >>> */ >>> - static> Predicate or( >>> - P first, Iterable

predicates) { >>> + static Predicate or( >>> + Predicate first, Iterable>> Predicate>> super T>> predicates) { >>> Objects.requireNonNull(first); >>> Objects.requireNonNull(predicates); >>> - if (!predicates.iterator().hasNext()) { >>> - return (Predicate) first; >>> - } >>> - >>> + >>> return t -> { >>> if (first.eval(t)) { >>> return true; >>> @@ -409,8 +389,8 @@ >>> * predicate's result is {@code true}. >>> */ >>> @SafeVarargs >>> - public static> Predicate >>> or( >>> - P... predicates) { >>> + public static Predicate or( >>> + Predicate... predicates) { >>> return or(Arrays.asList(predicates)); >>> } >>> >>> @@ -426,8 +406,8 @@ >>> * predicate's result is {@code true}. >>> */ >>> @SafeVarargs >>> - static> Predicate or( >>> - P first, P... predicates) { >>> + static Predicate or( >>> + Predicate first, Predicate... >>> predicates) { >>> return or(first, Arrays.asList(predicates)); >>> } >>> >>> @@ -444,12 +424,8 @@ >>> * @return a predicate that evaluates to {@code false} if all or >>> none of >>> * the component predicates evaluate to {@code true} >>> */ >>> - public static> Predicate >>> xor( >>> - Predicate first, P second) { >>> - if((null != first)&& (first == second)) { >>> - return (Predicate) alwaysFalse(); >>> - } >>> - >>> + public static Predicate xor( >>> + Predicate first, Predicate second) >>> { >>> Objects.requireNonNull(first); >>> Objects.requireNonNull(second); >>> >>> @@ -468,25 +444,23 @@ >>> * @return a predicate that evaluates to {@code false} if all or >>> none of >>> * the component predicates evaluate to {@code true} >>> */ >>> - public static> Predicate >>> xor( >>> - Iterable

predicates) { >>> + public static Predicate xor( >>> + Iterable> predicates) { >>> Objects.requireNonNull(predicates); >>> - if(!predicates.iterator().hasNext()) { >>> - throw new IllegalArgumentException("no predicates"); >>> - } >>> + >>> >>> return t -> { >>> - Boolean initial = null; >>> - for (P predicate : predicates) { >>> - if (null == initial) { >>> - initial = predicate.eval(t); >>> - } else { >>> - if (!(initial ^ predicate.eval(t))) { >>> - return true; >>> - } >>> + Iterator iterator = predicates.iterator(); >>> + if (!iterator.hasNext()) { >>> + return false; >>> + } >>> + boolean initial = iterator.next().eval(t); >>> + while(iterator.hasNext()) { >>> + if (!(initial ^ iterator.next().eval(t))) { >>> + return true; >>> } >>> } >>> - return false; >>> + return value; >>> }; >>> } >>> >>> @@ -502,8 +476,8 @@ >>> * @return a predicate that evaluates to {@code false} if all or >>> none of the >>> * component predicates evaluate to {@code true} >>> */ >>> - static> Predicate xor( >>> - P first, Iterable

predicates) { >>> + static Predicate xor( >>> + P first, Iterable> >>> predicates) { >>> Objects.requireNonNull(first); >>> Objects.requireNonNull(predicates); >>> >>> @@ -531,7 +505,7 @@ >>> * component predicates evaluate to {@code true} >>> */ >>> @SafeVarargs >>> - public static> Predicate >>> xor(P... predicates) { >>> + public static Predicate xor(Predicate... >>> predicates) { >>> return xor(Arrays.asList(predicates)); >>> } >>> >>> @@ -548,8 +522,8 @@ >>> * component predicates evaluate to {@code true} >>> */ >>> @SafeVarargs >>> - static> Predicate xor( >>> - P first, P... predicates) { >>> + static Predicate xor( >>> + P first, Predicate... predicates) { >>> return xor(first, Arrays.asList(predicates)); >>> } >>> } >>> diff --git a/src/share/classes/java/util/functions/Reducers.java >>> b/src/share/classes/java/util/functions/Reducers.java >>> --- a/src/share/classes/java/util/functions/Reducers.java >>> +++ b/src/share/classes/java/util/functions/Reducers.java >>> @@ -38,7 +38,7 @@ >>> /** >>> * A reducer who's {@code reduce} method always returns the base. >>> */ >>> - public static final Reducer NOP = (u, t) -> u; >>> + private static final Reducer NOP = (u, t) -> u; >>> >>> /** >>> * Only utility methods. >>> @@ -92,7 +92,7 @@ >>> * @return the composition of the provided mapper and reducer. >>> */ >>> public static Reducer compose( >>> - Reducer reducer, Mapper >>> mapper) { >>> + Reducer reducer, Mapper>> extends >>> T> mapper) { >>> Objects.requireNonNull(reducer); >>> Objects.requireNonNull(mapper); >>> >>> @@ -116,7 +116,7 @@ >>> * reducer. >>> */ >>> public static Reducer compose( >>> - Reducer reducer, Predicate predicate) { >>> + Reducer reducer, Predicate >>> predicate) { >>> Objects.requireNonNull(reducer); >>> Objects.requireNonNull(predicate); >>> >>> >>>> On 9/11/2011 7:59 AM, R?mi Forax wrote: >>>>> better with the patch >>>>> >>>>> R?mi >>>>> >>>>> On 09/11/2011 01:52 PM, R?mi Forax wrote: >>>>>> Hi all, >>>>>> I've tried to fix some bugs of the current implementation of >>>>>> java.util.functions. >>>>>> >>>>>> - some constants are still public >>>>>> (BTW, when the compiler will be able to generate the correct >>>>>> bytecode >>>>>> for a lambda, these constants will be not needed any more >>>>>> because constant lambda will be constant by default) >>>>>> - a lot of generic signature aren't right and there is inconsistency >>>>>> between the files. >>>>>> - some casts are wrong, you can't cast a Predicate to >>>>>> a Predicate, it's not safe. >>>>>> - some methods return a Predicate instead of a >>>>>> Predicate so it will not work if the predicate is used by >>>>>> example >>>>>> in a ?: >>>>>> - some short cuts in the implementation are wrong (by example, >>>>>> testing if there is an element in an iterable before creating >>>>>> the lambda is wrong because the iterable can be populated >>>>>> before the lambda is called. >>>>>> - fix some implementations, BTW I think the methods xor should be >>>>>> removed >>>>>> for the same reason there is no ^^ in C >>>>>> (nobody use xor in test between booleans) >>>>>> >>>>>> cheers, >>>>>> R?mi >>>>>> >>>>>> On 09/10/2011 03:49 AM, stuart.marks at oracle.com wrote: >>>>>>> Changeset: d9e4e3c106a7 >>>>>>> Author: smarks >>>>>>> Date: 2011-09-09 18:48 -0700 >>>>>>> URL: http://hg.openjdk.java.net/lambda/lambda/jdk/rev/d9e4e3c106a7 >>>>>>> >>>>>>> Update initial lambda APIs and tests to use new syntax. >>>>>>> >>>>>>> ! src/share/classes/java/util/functions/Blocks.java >>>>>>> ! src/share/classes/java/util/functions/Mappers.java >>>>>>> ! src/share/classes/java/util/functions/Predicates.java >>>>>>> ! src/share/classes/java/util/functions/Reducers.java >>>>>>> ! test/java/util/Collection/Extensions.java >>>>>>> ! test/java/util/Collection/MOAT.java >>>>>>> ! test/java/util/List/Extensions.java >>>>>>> ! test/java/util/functions/Block/BlocksTest.java >>>>>>> ! test/java/util/functions/Mapper/MappersTest.java >>>>>>> ! test/java/util/functions/Predicate/PredicatesTest.java >>>>>>> ! test/java/util/functions/Reducer/ReducersTest.java >>>>>>> >>>>>>> >>>>> >>>>> >>>>> >>> >>> >>>> On 9/11/2011 7:59 AM, R?mi Forax wrote: >>>>> better with the patch :) >>>>> >>>>> R?mi >>>>> >>>>> On 09/11/2011 01:52 PM, R?mi Forax wrote: >>>>>> Hi all, >>>>>> I've tried to fix some bugs of the current implementation of >>>>>> java.util.functions. >>>>>> >>>>>> - some constants are still public >>>>>> (BTW, when the compiler will be able to generate the correct >>>>>> bytecode >>>>>> for a lambda, these constants will be not needed any more >>>>>> because constant lambda will be constant by default) >>>>>> - a lot of generic signature aren't right and there is inconsistency >>>>>> between the files. >>>>>> - some casts are wrong, you can't cast a Predicate to >>>>>> a Predicate, it's not safe. >>>>>> - some methods return a Predicate instead of a >>>>>> Predicate so it will not work if the predicate is used by >>>>>> example >>>>>> in a ?: >>>>>> - some short cuts in the implementation are wrong (by example, >>>>>> testing if there is an element in an iterable before creating >>>>>> the lambda is wrong because the iterable can be populated >>>>>> before the lambda is called. >>>>>> - fix some implementations, BTW I think the methods xor should be >>>>>> removed >>>>>> for the same reason there is no ^^ in C >>>>>> (nobody use xor in test between booleans) >>>>>> >>>>>> cheers, >>>>>> R?mi >>>>>> >>>>>> On 09/10/2011 03:49 AM, stuart.marks at oracle.com wrote: >>>>>>> Changeset: d9e4e3c106a7 >>>>>>> Author: smarks >>>>>>> Date: 2011-09-09 18:48 -0700 >>>>>>> URL: http://hg.openjdk.java.net/lambda/lambda/jdk/rev/d9e4e3c106a7 >>>>>>> >>>>>>> Update initial lambda APIs and tests to use new syntax. >>>>>>> >>>>>>> ! src/share/classes/java/util/functions/Blocks.java >>>>>>> ! src/share/classes/java/util/functions/Mappers.java >>>>>>> ! src/share/classes/java/util/functions/Predicates.java >>>>>>> ! src/share/classes/java/util/functions/Reducers.java >>>>>>> ! test/java/util/Collection/Extensions.java >>>>>>> ! test/java/util/Collection/MOAT.java >>>>>>> ! test/java/util/List/Extensions.java >>>>>>> ! test/java/util/functions/Block/BlocksTest.java >>>>>>> ! test/java/util/functions/Mapper/MappersTest.java >>>>>>> ! test/java/util/functions/Predicate/PredicatesTest.java >>>>>>> ! test/java/util/functions/Reducer/ReducersTest.java >>>>>>> >>>>>>> >>>>> >>>>> >>>>> >>> >>> > > > > From ss at comp.lancs.ac.uk Wed Sep 14 04:10:42 2011 From: ss at comp.lancs.ac.uk (Steven Simpson) Date: Wed, 14 Sep 2011 12:10:42 +0100 Subject: Effectively final In-Reply-To: <4E49300F.6030302@gmail.com> References: <4E3299FD.7020309@gmail.com> <4E32F709.6060205@oracle.com> <4E32FF30.40206@gmail.com> <4E3341F8.9040408@univ-mlv.fr> <4E33AE4F.7030703@gmail.com> <4E33BFA3.1040101@comp.lancs.ac.uk> <4E33CFBF.90303@gmail.com> <4E49286E.3020703@comp.lancs.ac.uk> <4E492BB1.3070904@comp.lancs.ac.uk> <4E49300F.6030302@gmail.com> Message-ID: <4E708BB2.2080805@comp.lancs.ac.uk> Just a loose end... On 15/08/11 15:41, Tim Fox wrote: > On 15/08/2011 15:22, Steven Simpson wrote: >> void foo(final Socket socket) { >> new Runnable() { >> boolean timedOut; >> public void run() { >> system.setTimeout(100, #{ timedOut = true; }); >> socket.onData(#{ if (!timedOut) System.out.println("Got data"); }); >> } >> }.run(); >> } > Steven, firstly thanks for putting in the effort to look at this. And > kudos for your ingenuity :) And yet I missed this trick!: void foo(final Socket socket) { new Object() { boolean timedOut; void run() { system.setTimeout(100, () -> { timedOut = true; }); socket.onData(() -> { if (!timedOut) System.out.println("Got data"); }); } }.run(); } So the object doesn't have to be Runnable, and run() doesn't have to be public, return void, or be called run! That's more convenient if you want to return a value, rather than doing tricks with Callable: return new Object() { int run() { return 0; } }.run(); Cheers, Steven From blackbelt1999 at sbcglobal.net Wed Sep 14 11:46:27 2011 From: blackbelt1999 at sbcglobal.net (blackbelt1999) Date: Wed, 14 Sep 2011 11:46:27 -0700 (PDT) Subject: Effectively final In-Reply-To: <4E708BB2.2080805@comp.lancs.ac.uk> References: <4E3299FD.7020309@gmail.com> <4E32F709.6060205@oracle.com> <4E32FF30.40206@gmail.com> <4E3341F8.9040408@univ-mlv.fr> <4E33AE4F.7030703@gmail.com> <4E33BFA3.1040101@comp.lancs.ac.uk> <4E33CFBF.90303@gmail.com> <4E49286E.3020703@comp.lancs.ac.uk> <4E492BB1.3070904@comp.lancs.ac.uk> <4E49300F.6030302@gmail.com> <4E708BB2.2080805@comp.lancs.ac.uk> Message-ID: <1316025987.12549.YahooMailRC@web180013.mail.gq1.yahoo.com> Is there not a fundamental difference between the original code and the new code, namely the original code creates a new thread of execution while the new code does not? If so, can't the new code be simplified to: void foo(final Socket socket) { boolean timedOut = false; system.setTimeout(100, () => { timedOut = true; }); socket.onData(() => { if (!timedOut) System.out.println("Got data"); }); } The above version .does not go through the expense of creating a new object while providing the same behavior? --Alan ________________________________ From: Steven Simpson To: lambda-dev at openjdk.java.net Sent: Wed, September 14, 2011 4:10:42 AM Subject: Re: Effectively final Just a loose end... On 15/08/11 15:41, Tim Fox wrote: > On 15/08/2011 15:22, Steven Simpson wrote: >> void foo(final Socket socket) { >> new Runnable() { >> boolean timedOut; >> public void run() { >> system.setTimeout(100, #{ timedOut = true; }); >> socket.onData(#{ if (!timedOut) System.out.println("Got data"); >}); >> } >> }.run(); >> } > Steven, firstly thanks for putting in the effort to look at this. And > kudos for your ingenuity :) And yet I missed this trick!: void foo(final Socket socket) { new Object() { boolean timedOut; void run() { system.setTimeout(100, () -> { timedOut = true; }); socket.onData(() -> { if (!timedOut) System.out.println("Got data"); }); } }.run(); } So the object doesn't have to be Runnable, and run() doesn't have to be public, return void, or be called run! That's more convenient if you want to return a value, rather than doing tricks with Callable: return new Object() { int run() { return 0; } }.run(); Cheers, Steven From neal at gafter.com Wed Sep 14 11:57:02 2011 From: neal at gafter.com (Neal Gafter) Date: Wed, 14 Sep 2011 11:57:02 -0700 Subject: Effectively final In-Reply-To: <1316025987.12549.YahooMailRC@web180013.mail.gq1.yahoo.com> References: <4E3299FD.7020309@gmail.com> <4E32F709.6060205@oracle.com> <4E32FF30.40206@gmail.com> <4E3341F8.9040408@univ-mlv.fr> <4E33AE4F.7030703@gmail.com> <4E33BFA3.1040101@comp.lancs.ac.uk> <4E33CFBF.90303@gmail.com> <4E49286E.3020703@comp.lancs.ac.uk> <4E492BB1.3070904@comp.lancs.ac.uk> <4E49300F.6030302@gmail.com> <4E708BB2.2080805@comp.lancs.ac.uk> <1316025987.12549.YahooMailRC@web180013.mail.gq1.yahoo.com> Message-ID: A lambda can't modify a local variable from the enclosing scope. On Wed, Sep 14, 2011 at 11:46 AM, blackbelt1999 wrote: > Is there not a fundamental difference between the original code and the new > code, namely the original code creates a new thread of execution while the > new > code does not? If so, can't the new code be simplified to: > > void foo(final Socket socket) { > boolean timedOut = false; > system.setTimeout(100, () => { timedOut = true; }); > socket.onData(() => { if (!timedOut) System.out.println("Got data"); > }); > } > > The above version .does not go through the expense of creating a new object > while providing the same behavior? > > --Alan > > > > > ________________________________ > From: Steven Simpson > To: lambda-dev at openjdk.java.net > Sent: Wed, September 14, 2011 4:10:42 AM > Subject: Re: Effectively final > > Just a loose end... > > On 15/08/11 15:41, Tim Fox wrote: > > On 15/08/2011 15:22, Steven Simpson wrote: > >> void foo(final Socket socket) { > >> new Runnable() { > >> boolean timedOut; > >> public void run() { > >> system.setTimeout(100, #{ timedOut = true; }); > >> socket.onData(#{ if (!timedOut) System.out.println("Got > data"); > >}); > >> } > >> }.run(); > >> } > > Steven, firstly thanks for putting in the effort to look at this. And > > kudos for your ingenuity :) > > And yet I missed this trick!: > > void foo(final Socket socket) { > new Object() { > boolean timedOut; > void run() { > system.setTimeout(100, () -> { timedOut = true; }); > socket.onData(() -> { if (!timedOut) System.out.println("Got > data"); > }); > } > }.run(); > } > > So the object doesn't have to be Runnable, and run() doesn't have to be > public, return void, or be called run! That's more convenient if you > want to return a value, rather than doing tricks with Callable: > > return new Object() { > int run() { return 0; } > }.run(); > > Cheers, > > Steven > > From blackbelt1999 at sbcglobal.net Wed Sep 14 12:05:38 2011 From: blackbelt1999 at sbcglobal.net (blackbelt1999) Date: Wed, 14 Sep 2011 12:05:38 -0700 (PDT) Subject: Effectively final In-Reply-To: References: <4E3299FD.7020309@gmail.com> <4E32F709.6060205@oracle.com> <4E32FF30.40206@gmail.com> <4E3341F8.9040408@univ-mlv.fr> <4E33AE4F.7030703@gmail.com> <4E33BFA3.1040101@comp.lancs.ac.uk> <4E33CFBF.90303@gmail.com> <4E49286E.3020703@comp.lancs.ac.uk> <4E492BB1.3070904@comp.lancs.ac.uk> <4E49300F.6030302@gmail.com> <4E708BB2.2080805@comp.lancs.ac.uk> <1316025987.12549.YahooMailRC@web180013.mail.gq1.yahoo.com> Message-ID: <1316027138.87347.YahooMailRC@web180015.mail.gq1.yahoo.com> Ahh, true, but isn't there still the fundamental difference (the original code creates a new thread while the new code does not)? --Alan ________________________________ From: Neal Gafter To: blackbelt1999 Cc: Steven Simpson ; lambda-dev at openjdk.java.net Sent: Wed, September 14, 2011 11:57:02 AM Subject: Re: Effectively final A lambda can't modify a local variable from the enclosing scope. On Wed, Sep 14, 2011 at 11:46 AM, blackbelt1999 wrote: Is there not a fundamental difference between the original code and the new >code, namely the original code creates a new thread of execution while the new >code does not? If so, can't the new code be simplified to: > > > void foo(final Socket socket) { > boolean timedOut = false; > > system.setTimeout(100, () => { timedOut = true; }); > socket.onData(() => { if (!timedOut) System.out.println("Got data"); }); > } > >The above version .does not go through the expense of creating a new object >while providing the same behavior? > >--Alan > > > > >________________________________ >From: Steven Simpson >To: lambda-dev at openjdk.java.net >Sent: Wed, September 14, 2011 4:10:42 AM >Subject: Re: Effectively final > > >Just a loose end... > >On 15/08/11 15:41, Tim Fox wrote: >> On 15/08/2011 15:22, Steven Simpson wrote: >>> void foo(final Socket socket) { >>> new Runnable() { >>> boolean timedOut; >>> public void run() { >>> system.setTimeout(100, #{ timedOut = true; }); >>> socket.onData(#{ if (!timedOut) System.out.println("Got data"); >>}); >>> } >>> }.run(); >>> } >> Steven, firstly thanks for putting in the effort to look at this. And >> kudos for your ingenuity :) > >And yet I missed this trick!: > > void foo(final Socket socket) { > new Object() { > boolean timedOut; > void run() { > system.setTimeout(100, () -> { timedOut = true; }); > socket.onData(() -> { if (!timedOut) System.out.println("Got data"); >}); > } > }.run(); > } > >So the object doesn't have to be Runnable, and run() doesn't have to be >public, return void, or be called run! That's more convenient if you >want to return a value, rather than doing tricks with Callable: > > return new Object() { > int run() { return 0; } > }.run(); > >Cheers, > >Steven > > From serge.boulay at gmail.com Wed Sep 14 12:48:32 2011 From: serge.boulay at gmail.com (Serge Boulay) Date: Wed, 14 Sep 2011 15:48:32 -0400 Subject: Effectively final In-Reply-To: References: <4E3299FD.7020309@gmail.com> <4E32F709.6060205@oracle.com> <4E32FF30.40206@gmail.com> <4E3341F8.9040408@univ-mlv.fr> <4E33AE4F.7030703@gmail.com> <4E33BFA3.1040101@comp.lancs.ac.uk> <4E33CFBF.90303@gmail.com> <4E49286E.3020703@comp.lancs.ac.uk> <4E492BB1.3070904@comp.lancs.ac.uk> <4E49300F.6030302@gmail.com> <4E708BB2.2080805@comp.lancs.ac.uk> <1316025987.12549.YahooMailRC@web180013.mail.gq1.yahoo.com> Message-ID: not even through a reference such as an atomic boolean ? (yes, I know Brian frowns on this stuff) void foo(final Socket socket) { AtomicBoolean timedOut = new AtomicBoolean(false); system.setTimeout(100, ->{ timedOut.set(true); }); socket.onData(->{ if (!timedOut.get()) System.out.println("Got data"); }); } On Wed, Sep 14, 2011 at 2:57 PM, Neal Gafter wrote: > A lambda can't modify a local variable from the enclosing scope. > > On Wed, Sep 14, 2011 at 11:46 AM, blackbelt1999 < > blackbelt1999 at sbcglobal.net > > wrote: > > > Is there not a fundamental difference between the original code and the > new > > code, namely the original code creates a new thread of execution while > the > > new > > code does not? If so, can't the new code be simplified to: > > > > void foo(final Socket socket) { > > boolean timedOut = false; > > system.setTimeout(100, () => { timedOut = true; }); > > socket.onData(() => { if (!timedOut) System.out.println("Got > data"); > > }); > > } > > > > The above version .does not go through the expense of creating a new > object > > while providing the same behavior? > > > > --Alan > > > > > > > > > > ________________________________ > > From: Steven Simpson > > To: lambda-dev at openjdk.java.net > > Sent: Wed, September 14, 2011 4:10:42 AM > > Subject: Re: Effectively final > > > > Just a loose end... > > > > On 15/08/11 15:41, Tim Fox wrote: > > > On 15/08/2011 15:22, Steven Simpson wrote: > > >> void foo(final Socket socket) { > > >> new Runnable() { > > >> boolean timedOut; > > >> public void run() { > > >> system.setTimeout(100, #{ timedOut = true; }); > > >> socket.onData(#{ if (!timedOut) System.out.println("Got > > data"); > > >}); > > >> } > > >> }.run(); > > >> } > > > Steven, firstly thanks for putting in the effort to look at this. And > > > kudos for your ingenuity :) > > > > And yet I missed this trick!: > > > > void foo(final Socket socket) { > > new Object() { > > boolean timedOut; > > void run() { > > system.setTimeout(100, () -> { timedOut = true; }); > > socket.onData(() -> { if (!timedOut) System.out.println("Got > > data"); > > }); > > } > > }.run(); > > } > > > > So the object doesn't have to be Runnable, and run() doesn't have to be > > public, return void, or be called run! That's more convenient if you > > want to return a value, rather than doing tricks with Callable: > > > > return new Object() { > > int run() { return 0; } > > }.run(); > > > > Cheers, > > > > Steven > > > > > > From ss at comp.lancs.ac.uk Wed Sep 14 12:49:29 2011 From: ss at comp.lancs.ac.uk (Steven Simpson) Date: Wed, 14 Sep 2011 20:49:29 +0100 Subject: Effectively final In-Reply-To: <1316025987.12549.YahooMailRC@web180013.mail.gq1.yahoo.com> References: <4E3299FD.7020309@gmail.com> <4E32F709.6060205@oracle.com> <4E32FF30.40206@gmail.com> <4E3341F8.9040408@univ-mlv.fr> <4E33AE4F.7030703@gmail.com> <4E33BFA3.1040101@comp.lancs.ac.uk> <4E33CFBF.90303@gmail.com> <4E49286E.3020703@comp.lancs.ac.uk> <4E492BB1.3070904@comp.lancs.ac.uk> <4E49300F.6030302@gmail.com> <4E708BB2.2080805@comp.lancs.ac.uk> <1316025987.12549.YahooMailRC@web180013.mail.gq1.yahoo.com> Message-ID: <4E710549.40307@comp.lancs.ac.uk> On 14/09/11 19:46, blackbelt1999 wrote: > Is there not a fundamental difference between the original code and > the new code, namely the original code creates a new thread of > execution while the new code does not? Neither version creates a new thread. The creation of a Runnable does not imply the creation of a new thread. > >> void foo(final Socket socket) { > >> new Runnable() { > >> boolean timedOut; > >> public void run() { > >> system.setTimeout(100, #{ timedOut = true; }); > >> socket.onData(#{ if (!timedOut) System.out.println("Got > data"); }); > >> } > >> }.run(); > >> } From blackbelt1999 at sbcglobal.net Wed Sep 14 13:16:40 2011 From: blackbelt1999 at sbcglobal.net (blackbelt1999) Date: Wed, 14 Sep 2011 13:16:40 -0700 (PDT) Subject: Effectively final In-Reply-To: <4E710549.40307@comp.lancs.ac.uk> References: <4E3299FD.7020309@gmail.com> <4E32F709.6060205@oracle.com> <4E32FF30.40206@gmail.com> <4E3341F8.9040408@univ-mlv.fr> <4E33AE4F.7030703@gmail.com> <4E33BFA3.1040101@comp.lancs.ac.uk> <4E33CFBF.90303@gmail.com> <4E49286E.3020703@comp.lancs.ac.uk> <4E492BB1.3070904@comp.lancs.ac.uk> <4E49300F.6030302@gmail.com> <4E708BB2.2080805@comp.lancs.ac.uk> <1316025987.12549.YahooMailRC@web180013.mail.gq1.yahoo.com> <4E710549.40307@comp.lancs.ac.uk> Message-ID: <1316031400.25179.YahooMailRC@web180016.mail.gq1.yahoo.com> OOPS! I see "Runnable" but I read "Thread". ________________________________ From: Steven Simpson To: lambda-dev at openjdk.java.net Sent: Wed, September 14, 2011 12:49:29 PM Subject: Re: Effectively final On 14/09/11 19:46, blackbelt1999 wrote: > Is there not a fundamental difference between the original code and > the new code, namely the original code creates a new thread of > execution while the new code does not? Neither version creates a new thread. The creation of a Runnable does not imply the creation of a new thread. > >> void foo(final Socket socket) { > >> new Runnable() { > >> boolean timedOut; > >> public void run() { > >> system.setTimeout(100, #{ timedOut = true; }); > >> socket.onData(#{ if (!timedOut) System.out.println("Got > data"); }); > >> } > >> }.run(); > >> } From mike.duigou at oracle.com Wed Sep 14 18:10:36 2011 From: mike.duigou at oracle.com (mike.duigou at oracle.com) Date: Thu, 15 Sep 2011 01:10:36 +0000 Subject: hg: lambda/lambda/jdk: Adds forEach/filter/map/reduce and fused versions to Iterable. Extension method defaults are in Iterables. Adds Iterators class with forEach/filter/map/reduce and fused for Iterator. Message-ID: <20110915011117.56A28476BA@hg.openjdk.java.net> Changeset: 51c58fb235e6 Author: mduigou Date: 2011-09-14 18:05 -0700 URL: http://hg.openjdk.java.net/lambda/lambda/jdk/rev/51c58fb235e6 Adds forEach/filter/map/reduce and fused versions to Iterable. Extension method defaults are in Iterables. Adds Iterators class with forEach/filter/map/reduce and fused for Iterator. ! make/java/java/FILES_java.gmk ! src/share/classes/java/lang/Iterable.java + src/share/classes/java/lang/Iterables.java ! src/share/classes/java/util/Collection.java ! src/share/classes/java/util/Iterator.java + src/share/classes/java/util/Iterators.java ! src/share/classes/java/util/functions/Block.java ! src/share/classes/java/util/functions/Blocks.java ! src/share/classes/java/util/functions/Mappers.java ! src/share/classes/java/util/functions/Predicates.java ! src/solaris/classes/sun/nio/fs/UnixPath.java + test/java/lang/Iterables/LambdasTests.java + test/java/util/Iterators/LambdasTests.java From mike.duigou at oracle.com Wed Sep 14 18:22:40 2011 From: mike.duigou at oracle.com (Mike Duigou) Date: Wed, 14 Sep 2011 18:22:40 -0700 Subject: foreach/filter/map/reduce on Iterable & Iterators Message-ID: <07D92BF2-8AF1-4E79-9287-87450B2AEF0C@oracle.com> I've pushed a change to the lambda dev repo which introduces forEach/filter/map/reduce (as well as fused versions such as "filterMapReduce") on the Iterable interface. In addition it currently adds isEmpty() and intoCollection(). We're still evaluating whether these last two are sufficiently useful to warrant inclusion. The implementation of forEach/filter/map/reduce for Iterable is provided via defaulted extension methods with the implementations residing in Iterables [name subject to change]. The implementations are a mix of eager and lazy and none make assumptions about concurrency capabilities (or lack thereof) of the source collections. The forEach(), reduce() and intoCollection() are all eager--they complete all work before returning. map() and filter() are lazy--they process elements as they are read from the result Iterable. Some of the behaviour uses the Iterators class. Iterators contains implementations of forEach/filter/map/reduce which work upon Iterators. The lazy/eager semantics are the same as the Iterables implementations. These methods are currently not provided as defenders upon Iterator, but they could be. From the limited discussion thus far it seems that having forEach/filter/map/reduce on Iterator will be used less commonly than on Iterable. For the cases where only an Iterator is available the static methods in Iterators can still be called. Very basic unit tests are also provided. Mike From brian.goetz at oracle.com Wed Sep 14 19:11:12 2011 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 14 Sep 2011 19:11:12 -0700 Subject: Effectively final In-Reply-To: References: <4E3299FD.7020309@gmail.com> <4E32F709.6060205@oracle.com> <4E32FF30.40206@gmail.com> <4E3341F8.9040408@univ-mlv.fr> <4E33AE4F.7030703@gmail.com> <4E33BFA3.1040101@comp.lancs.ac.uk> <4E33CFBF.90303@gmail.com> <4E49286E.3020703@comp.lancs.ac.uk> <4E492BB1.3070904@comp.lancs.ac.uk> <4E49300F.6030302@gmail.com> <4E708BB2.2080805@comp.lancs.ac.uk> <1316025987.12549.YahooMailRC@web180013.mail.gq1.yahoo.com> Message-ID: <2D061A47-ECB8-48F6-9F08-82547EA3DCC8@oracle.com> A final reference to thread-safe mutable state is fine, like AtomicBoilean. What is being captured is the reference, which is final. What will get you fired is using an array, which is not thread safe. Sent from my iPhone On Sep 14, 2011, at 12:48 PM, Serge Boulay wrote: > not even through a reference such as an atomic boolean ? (yes, I know Brian > frowns on this stuff) > > void foo(final Socket socket) { > AtomicBoolean timedOut = new AtomicBoolean(false); > system.setTimeout(100, ->{ timedOut.set(true); }); > socket.onData(->{ if (!timedOut.get()) System.out.println("Got data"); > }); > } > > On Wed, Sep 14, 2011 at 2:57 PM, Neal Gafter wrote: > >> A lambda can't modify a local variable from the enclosing scope. >> >> On Wed, Sep 14, 2011 at 11:46 AM, blackbelt1999 < >> blackbelt1999 at sbcglobal.net >>> wrote: >> >>> Is there not a fundamental difference between the original code and the >> new >>> code, namely the original code creates a new thread of execution while >> the >>> new >>> code does not? If so, can't the new code be simplified to: >>> >>> void foo(final Socket socket) { >>> boolean timedOut = false; >>> system.setTimeout(100, () => { timedOut = true; }); >>> socket.onData(() => { if (!timedOut) System.out.println("Got >> data"); >>> }); >>> } >>> >>> The above version .does not go through the expense of creating a new >> object >>> while providing the same behavior? >>> >>> --Alan >>> >>> >>> >>> >>> ________________________________ >>> From: Steven Simpson >>> To: lambda-dev at openjdk.java.net >>> Sent: Wed, September 14, 2011 4:10:42 AM >>> Subject: Re: Effectively final >>> >>> Just a loose end... >>> >>> On 15/08/11 15:41, Tim Fox wrote: >>>> On 15/08/2011 15:22, Steven Simpson wrote: >>>>> void foo(final Socket socket) { >>>>> new Runnable() { >>>>> boolean timedOut; >>>>> public void run() { >>>>> system.setTimeout(100, #{ timedOut = true; }); >>>>> socket.onData(#{ if (!timedOut) System.out.println("Got >>> data"); >>>> }); >>>>> } >>>>> }.run(); >>>>> } >>>> Steven, firstly thanks for putting in the effort to look at this. And >>>> kudos for your ingenuity :) >>> >>> And yet I missed this trick!: >>> >>> void foo(final Socket socket) { >>> new Object() { >>> boolean timedOut; >>> void run() { >>> system.setTimeout(100, () -> { timedOut = true; }); >>> socket.onData(() -> { if (!timedOut) System.out.println("Got >>> data"); >>> }); >>> } >>> }.run(); >>> } >>> >>> So the object doesn't have to be Runnable, and run() doesn't have to be >>> public, return void, or be called run! That's more convenient if you >>> want to return a value, rather than doing tricks with Callable: >>> >>> return new Object() { >>> int run() { return 0; } >>> }.run(); >>> >>> Cheers, >>> >>> Steven >>> >>> >> >> > From cgdecker at gmail.com Wed Sep 14 19:44:00 2011 From: cgdecker at gmail.com (Colin Decker) Date: Wed, 14 Sep 2011 22:44:00 -0400 Subject: foreach/filter/map/reduce on Iterable & Iterators In-Reply-To: <07D92BF2-8AF1-4E79-9287-87450B2AEF0C@oracle.com> References: <07D92BF2-8AF1-4E79-9287-87450B2AEF0C@oracle.com> Message-ID: The variance of the parameters for most of these methods needs to be changed. For example, filter should take Predicate and map should take Mapper. -- Colin On Wed, Sep 14, 2011 at 9:22 PM, Mike Duigou wrote: > I've pushed a change to the lambda dev repo which introduces > forEach/filter/map/reduce (as well as fused versions such as > "filterMapReduce") on the Iterable interface. In addition it currently adds > isEmpty() and intoCollection(). We're still evaluating whether these last > two are sufficiently useful to warrant inclusion. > > The implementation of forEach/filter/map/reduce for Iterable is provided > via defaulted extension methods with the implementations residing in > Iterables [name subject to change]. The implementations are a mix of eager > and lazy and none make assumptions about concurrency capabilities (or lack > thereof) of the source collections. The forEach(), reduce() and > intoCollection() are all eager--they complete all work before returning. > map() and filter() are lazy--they process elements as they are read from the > result Iterable. Some of the behaviour uses the Iterators class. > > Iterators contains implementations of forEach/filter/map/reduce which work > upon Iterators. The lazy/eager semantics are the same as the Iterables > implementations. These methods are currently not provided as defenders upon > Iterator, but they could be. From the limited discussion thus far it seems > that having forEach/filter/map/reduce on Iterator will be used less commonly > than on Iterable. For the cases where only an Iterator is available the > static methods in Iterators can still be called. > > Very basic unit tests are also provided. > > Mike > > From mike.duigou at oracle.com Wed Sep 14 19:59:12 2011 From: mike.duigou at oracle.com (Mike Duigou) Date: Wed, 14 Sep 2011 19:59:12 -0700 Subject: foreach/filter/map/reduce on Iterable & Iterators In-Reply-To: References: <07D92BF2-8AF1-4E79-9287-87450B2AEF0C@oracle.com> Message-ID: <0BF29E4A-53ED-4F73-BED3-CF1F0810686E@oracle.com> Yes I agree this should be done. On the other hand, is it reasonable to expect that most lambdas will be specified as SAM conversions which will make the "? super" unnecessary? Are there specific practical cases where we expect lambdas to be used that will require the "? super" in order to be accepted? Where will those lambdas be coming from? Mike On Sep 14 2011, at 19:44 , Colin Decker wrote: > The variance of the parameters for most of these methods needs to be changed. For example, filter should take Predicate and map should take Mapper. > > -- > Colin > > > On Wed, Sep 14, 2011 at 9:22 PM, Mike Duigou wrote: > I've pushed a change to the lambda dev repo which introduces forEach/filter/map/reduce (as well as fused versions such as "filterMapReduce") on the Iterable interface. In addition it currently adds isEmpty() and intoCollection(). We're still evaluating whether these last two are sufficiently useful to warrant inclusion. > > The implementation of forEach/filter/map/reduce for Iterable is provided via defaulted extension methods with the implementations residing in Iterables [name subject to change]. The implementations are a mix of eager and lazy and none make assumptions about concurrency capabilities (or lack thereof) of the source collections. The forEach(), reduce() and intoCollection() are all eager--they complete all work before returning. map() and filter() are lazy--they process elements as they are read from the result Iterable. Some of the behaviour uses the Iterators class. > > Iterators contains implementations of forEach/filter/map/reduce which work upon Iterators. The lazy/eager semantics are the same as the Iterables implementations. These methods are currently not provided as defenders upon Iterator, but they could be. From the limited discussion thus far it seems that having forEach/filter/map/reduce on Iterator will be used less commonly than on Iterable. For the cases where only an Iterator is available the static methods in Iterators can still be called. > > Very basic unit tests are also provided. > > Mike From cmotlin at gmail.com Wed Sep 14 20:38:00 2011 From: cmotlin at gmail.com (Craig P. Motlin) Date: Wed, 14 Sep 2011 23:38:00 -0400 Subject: foreach/filter/map/reduce on Iterable & Iterators In-Reply-To: <0BF29E4A-53ED-4F73-BED3-CF1F0810686E@oracle.com> References: <07D92BF2-8AF1-4E79-9287-87450B2AEF0C@oracle.com> <0BF29E4A-53ED-4F73-BED3-CF1F0810686E@oracle.com> Message-ID: The generics need to be Mapper on all Mapper method parameters. On Wed, Sep 14, 2011 at 10:59 PM, Mike Duigou wrote: > Yes I agree this should be done. > > On the other hand, is it reasonable to expect that most lambdas will be > specified as SAM conversions which will make the "? super" unnecessary? Are > there specific practical cases where we expect lambdas to be used that will > require the "? super" in order to be accepted? Where will those lambdas be > coming from? > > Mike > > On Sep 14 2011, at 19:44 , Colin Decker wrote: > > > The variance of the parameters for most of these methods needs to be > changed. For example, filter should take Predicate and map should > take Mapper. > > > > -- > > Colin > > > > > > On Wed, Sep 14, 2011 at 9:22 PM, Mike Duigou > wrote: > > I've pushed a change to the lambda dev repo which introduces > forEach/filter/map/reduce (as well as fused versions such as > "filterMapReduce") on the Iterable interface. In addition it currently adds > isEmpty() and intoCollection(). We're still evaluating whether these last > two are sufficiently useful to warrant inclusion. > > > > The implementation of forEach/filter/map/reduce for Iterable is provided > via defaulted extension methods with the implementations residing in > Iterables [name subject to change]. The implementations are a mix of eager > and lazy and none make assumptions about concurrency capabilities (or lack > thereof) of the source collections. The forEach(), reduce() and > intoCollection() are all eager--they complete all work before returning. > map() and filter() are lazy--they process elements as they are read from the > result Iterable. Some of the behaviour uses the Iterators class. > > > > Iterators contains implementations of forEach/filter/map/reduce which > work upon Iterators. The lazy/eager semantics are the same as the Iterables > implementations. These methods are currently not provided as defenders upon > Iterator, but they could be. From the limited discussion thus far it seems > that having forEach/filter/map/reduce on Iterator will be used less commonly > than on Iterable. For the cases where only an Iterator is available the > static methods in Iterators can still be called. > > > > Very basic unit tests are also provided. > > > > Mike > > From mike.duigou at oracle.com Wed Sep 14 21:58:58 2011 From: mike.duigou at oracle.com (mike.duigou at oracle.com) Date: Thu, 15 Sep 2011 04:58:58 +0000 Subject: hg: lambda/lambda/jdk: Improvements to generics. Message-ID: <20110915045933.3FB14476C3@hg.openjdk.java.net> Changeset: 5eb7c1f7bb43 Author: mduigou Date: 2011-09-14 21:59 -0700 URL: http://hg.openjdk.java.net/lambda/lambda/jdk/rev/5eb7c1f7bb43 Improvements to generics. ! src/share/classes/java/lang/Iterable.java ! src/share/classes/java/lang/Iterables.java ! src/share/classes/java/util/Iterators.java From neal at gafter.com Wed Sep 14 22:04:46 2011 From: neal at gafter.com (Neal Gafter) Date: Wed, 14 Sep 2011 22:04:46 -0700 Subject: foreach/filter/map/reduce on Iterable & Iterators In-Reply-To: <0BF29E4A-53ED-4F73-BED3-CF1F0810686E@oracle.com> References: <07D92BF2-8AF1-4E79-9287-87450B2AEF0C@oracle.com> <0BF29E4A-53ED-4F73-BED3-CF1F0810686E@oracle.com> Message-ID: On Wed, Sep 14, 2011 at 7:59 PM, Mike Duigou wrote: > Yes I agree this should be done. > > On the other hand, is it reasonable to expect that most lambdas will be > specified as SAM conversions which will make the "? super" unnecessary? Are > there specific practical cases where we expect lambdas to be used that will > require the "? super" in order to be accepted? Where will those lambdas be > coming from? > The lambdas may be coming from invocations of *other* methods, which have different signatures. From forax at univ-mlv.fr Thu Sep 15 00:21:20 2011 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Thu, 15 Sep 2011 09:21:20 +0200 Subject: hg: lambda/lambda/jdk: Improvements to generics. In-Reply-To: <20110915045933.3FB14476C3@hg.openjdk.java.net> References: <20110915045933.3FB14476C3@hg.openjdk.java.net> Message-ID: <4E71A770.9060100@univ-mlv.fr> On 09/15/2011 06:58 AM, mike.duigou at oracle.com wrote: > Changeset: 5eb7c1f7bb43 > Author: mduigou > Date: 2011-09-14 21:59 -0700 > URL: http://hg.openjdk.java.net/lambda/lambda/jdk/rev/5eb7c1f7bb43 > > Improvements to generics. > > ! src/share/classes/java/lang/Iterable.java > ! src/share/classes/java/lang/Iterables.java > ! src/share/classes/java/util/Iterators.java > > Hi Mike, all reducers should be Reducer reducer and not Reducer reducer R?mi From forax at univ-mlv.fr Thu Sep 15 00:30:05 2011 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Thu, 15 Sep 2011 09:30:05 +0200 Subject: Mismatch between the order of the type variable and the order of the SAM method formal parameters Message-ID: <4E71A97D.4050206@univ-mlv.fr> Hi all, Here is the declaration of a Reducer: interface Reducer { U reduce(U base, T t); } and how to use it: Reducer reducer = (Integer i, String s) -> i + s.length(); As you see the order of the type argument is not the same as the order of the type of the formal parameter of the lambda (Integer i, String s). I think it will be simpler if the signature of reduce() was changed to swap the two formal parameters. R?mi From forax at univ-mlv.fr Thu Sep 15 00:58:08 2011 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Thu, 15 Sep 2011 09:58:08 +0200 Subject: foreach/filter/map/reduce on Iterable & Iterators In-Reply-To: <07D92BF2-8AF1-4E79-9287-87450B2AEF0C@oracle.com> References: <07D92BF2-8AF1-4E79-9287-87450B2AEF0C@oracle.com> Message-ID: <4E71B010.20704@univ-mlv.fr> Hi Mike, Here is my comments: in Iterables, for filter, map and filterMap, you should create one class that implements Iterable and store a predicate (or null) and a mapper (or null) and an Iterable to crawle. This class should also override all defender method from Iterable, by example, if the mapper is null, if the filter is null and you call filter() then you create an new instance of that class that just store the filter. if the mapper is null and a filter already exist, you can combine the existing filter with the new one with and(), etc. With this trick we may even don't have to have the fused versions because the escape analysis done by the VM will be able to remove the intermediary object. forEach() should return void and not an Iterable because it's an eager operation, all lazy operations should return an Iterable, all eager operations should return the result or void. The name intoCollection is too verbose, "into" is in my opinion better. R?mi On 09/15/2011 03:22 AM, Mike Duigou wrote: > I've pushed a change to the lambda dev repo which introduces forEach/filter/map/reduce (as well as fused versions such as "filterMapReduce") on the Iterable interface. In addition it currently adds isEmpty() and intoCollection(). We're still evaluating whether these last two are sufficiently useful to warrant inclusion. > > The implementation of forEach/filter/map/reduce for Iterable is provided via defaulted extension methods with the implementations residing in Iterables [name subject to change]. The implementations are a mix of eager and lazy and none make assumptions about concurrency capabilities (or lack thereof) of the source collections. The forEach(), reduce() and intoCollection() are all eager--they complete all work before returning. map() and filter() are lazy--they process elements as they are read from the result Iterable. Some of the behaviour uses the Iterators class. > > Iterators contains implementations of forEach/filter/map/reduce which work upon Iterators. The lazy/eager semantics are the same as the Iterables implementations. These methods are currently not provided as defenders upon Iterator, but they could be. From the limited discussion thus far it seems that having forEach/filter/map/reduce on Iterator will be used less commonly than on Iterable. For the cases where only an Iterator is available the static methods in Iterators can still be called. > > Very basic unit tests are also provided. > > Mike > From cgdecker at gmail.com Thu Sep 15 04:56:59 2011 From: cgdecker at gmail.com (Colin Decker) Date: Thu, 15 Sep 2011 07:56:59 -0400 Subject: foreach/filter/map/reduce on Iterable & Iterators In-Reply-To: References: <07D92BF2-8AF1-4E79-9287-87450B2AEF0C@oracle.com> <0BF29E4A-53ED-4F73-BED3-CF1F0810686E@oracle.com> Message-ID: "? extends U" isn't necessary for map. All that allows is assigning what is really, say, an Iterable to Iterable or Iterable without casting, which doesn't help anything. -- Colin On Wed, Sep 14, 2011 at 11:38 PM, Craig P. Motlin wrote: > The generics need to be Mapper on all Mapper method > parameters. > > > On Wed, Sep 14, 2011 at 10:59 PM, Mike Duigou wrote: > >> Yes I agree this should be done. >> >> On the other hand, is it reasonable to expect that most lambdas will be >> specified as SAM conversions which will make the "? super" unnecessary? Are >> there specific practical cases where we expect lambdas to be used that will >> require the "? super" in order to be accepted? Where will those lambdas be >> coming from? >> >> Mike >> >> On Sep 14 2011, at 19:44 , Colin Decker wrote: >> >> > The variance of the parameters for most of these methods needs to be >> changed. For example, filter should take Predicate and map should >> take Mapper. >> > >> > -- >> > Colin >> > >> > >> > On Wed, Sep 14, 2011 at 9:22 PM, Mike Duigou >> wrote: >> > I've pushed a change to the lambda dev repo which introduces >> forEach/filter/map/reduce (as well as fused versions such as >> "filterMapReduce") on the Iterable interface. In addition it currently adds >> isEmpty() and intoCollection(). We're still evaluating whether these last >> two are sufficiently useful to warrant inclusion. >> > >> > The implementation of forEach/filter/map/reduce for Iterable is provided >> via defaulted extension methods with the implementations residing in >> Iterables [name subject to change]. The implementations are a mix of eager >> and lazy and none make assumptions about concurrency capabilities (or lack >> thereof) of the source collections. The forEach(), reduce() and >> intoCollection() are all eager--they complete all work before returning. >> map() and filter() are lazy--they process elements as they are read from the >> result Iterable. Some of the behaviour uses the Iterators class. >> > >> > Iterators contains implementations of forEach/filter/map/reduce which >> work upon Iterators. The lazy/eager semantics are the same as the Iterables >> implementations. These methods are currently not provided as defenders upon >> Iterator, but they could be. From the limited discussion thus far it seems >> that having forEach/filter/map/reduce on Iterator will be used less commonly >> than on Iterable. For the cases where only an Iterator is available the >> static methods in Iterators can still be called. >> > >> > Very basic unit tests are also provided. >> > >> > Mike >> >> > From maurizio.cimadamore at oracle.com Thu Sep 15 05:36:25 2011 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 15 Sep 2011 13:36:25 +0100 Subject: foreach/filter/map/reduce on Iterable & Iterators In-Reply-To: References: <07D92BF2-8AF1-4E79-9287-87450B2AEF0C@oracle.com> <0BF29E4A-53ED-4F73-BED3-CF1F0810686E@oracle.com> Message-ID: <4E71F149.1030008@oracle.com> On 15/09/11 12:56, Colin Decker wrote: > "? extends U" isn't necessary for map. All that allows is assigning what is > really, say, an Iterable to Iterable or Iterable > without casting, which doesn't help anything. > I think they are referring to changing the signature of Collection.map (and other related methods) from this: Iterable map(Mapper mapper) ... to this: Iterable map(Mapper mapper) ... Now, while this case the '? extends' is conceptually correct, I kinda agree that the outcome won't be too different should the '? extends' be omitted. Since U is a method type-parameter (whose bound is Object - unrelated to T), that means that most of the times type-inference will be able to infer the right type for U; for example: Mapper moo; Mapper mnn; Mapper mii; List li = ... li.map(moo) // U == Object li.map(mnn) // U == Number li.map(mii) // U == Integer The above will work regardless of whether you put the '? extends' wildcard or not. Where things will be different is when type-parameters are explicitly specified: li.map(mii) // ok with wildcards / error w/o wildcards (U == Object) li.map(mii) // ok with wildcards / error w/o wildcards (U == Number) Note that the above pattern might be common if i.e. you want to assign the result of the map operation to a type that is less specific than the type of the mapper. I.e. List lo = li.map(mii) // U == Integer, type-mismatch, List not compatible with List List lo = li.map(mii) // ok Maurizio From cmotlin at gmail.com Thu Sep 15 05:46:09 2011 From: cmotlin at gmail.com (Craig P. Motlin) Date: Thu, 15 Sep 2011 08:46:09 -0400 Subject: foreach/filter/map/reduce on Iterable & Iterators In-Reply-To: <4E71F149.1030008@oracle.com> References: <07D92BF2-8AF1-4E79-9287-87450B2AEF0C@oracle.com> <0BF29E4A-53ED-4F73-BED3-CF1F0810686E@oracle.com> <4E71F149.1030008@oracle.com> Message-ID: It seems like it doesn't matter much, but sometimes that flexibility is exactly what you need. Guava has the type signature I described [1]. And I came to the same conclusion on a similar API. And as Maurizio said, it is conceptually the correct type signature. Functions really are covariant in their parameter type and contravariant in their return type. Another way of looking at it - using wildcards this way may be unusual, but it should work: Mapper mapper = ...; myTypes.map(mapper); [1] http://docs.guava-libraries.googlecode.com/git-history/v9.0/javadoc/com/google/common/collect/Iterables.html#transform(java.lang.Iterable, com.google.common.base.Function) On Thu, Sep 15, 2011 at 8:36 AM, Maurizio Cimadamore < maurizio.cimadamore at oracle.com> wrote: > On 15/09/11 12:56, Colin Decker wrote: > >> "? extends U" isn't necessary for map. All that allows is assigning what >> is >> really, say, an Iterable to Iterable or >> Iterable >> without casting, which doesn't help anything. >> >> I think they are referring to changing the signature of Collection.map > (and other related methods) from this: > > Iterable map(Mapper mapper) ... > > to this: > > Iterable map(Mapper mapper) ... > > Now, while this case the '? extends' is conceptually correct, I kinda agree > that the outcome won't be too different should the '? extends' be omitted. > Since U is a method type-parameter (whose bound is Object - unrelated to T), > that means that most of the times type-inference will be able to infer the > right type for U; for example: > > Mapper moo; > Mapper mnn; > Mapper mii; > > List li = ... > li.map(moo) // U == Object > li.map(mnn) // U == Number > li.map(mii) // U == Integer > > The above will work regardless of whether you put the '? extends' wildcard > or not. Where things will be different is when type-parameters are > explicitly specified: > > li.map(mii) // ok with wildcards / error w/o wildcards (U == > Object) > li.map(mii) // ok with wildcards / error w/o wildcards (U == > Number) > > Note that the above pattern might be common if i.e. you want to assign the > result of the map operation to a type that is less specific than the type of > the mapper. I.e. > > List lo = li.map(mii) // U == Integer, type-mismatch, List > not compatible with List > List lo = li.map(mii) // ok > > Maurizio > > > > > > > From cgdecker at gmail.com Thu Sep 15 07:46:43 2011 From: cgdecker at gmail.com (Colin Decker) Date: Thu, 15 Sep 2011 10:46:43 -0400 Subject: foreach/filter/map/reduce on Iterable & Iterators In-Reply-To: References: <07D92BF2-8AF1-4E79-9287-87450B2AEF0C@oracle.com> <0BF29E4A-53ED-4F73-BED3-CF1F0810686E@oracle.com> <4E71F149.1030008@oracle.com> Message-ID: This doesn't mention Iterables.transform (though I believe the same applies), but in this mailing list thread [1] Kevin says that the signature of Lists.transform (which takes a Function) was a mistake and that it should have had the same signature as Collections2.transform [2] (which takes Function). In any case, I don't see it as conceptually the right signature. The map method differs from a typical method that is using the Mapper as a producer of U. What you need to think about here is how the resulting Iterable can be used. Assigning something that is actually an Iterable to Iterable or Iterable doesn't really gain you anything. You're either going to be using the Iterable yourself, in which case you can assign its elements to Object or Number directly if you want, or you're going to be passing it to some other method(s). Assuming those methods use wildcards correctly, you'll be able to pass the Iterable anywhere you could have passed Iterable or Iterable. Also, you can pass a Mapper to map even if it takes Mapper. The result is just going to be an Iterable. That is the actual type of the resulting Iterable and it's no less usable than if you called it an Iterable. If you're returning that result and don't want the wildcard in the return type, you can always use Mapper in which case the result is an Iterable. -- Colin [1] https://groups.google.com/d/msg/guava-discuss/iCW88aubgbc/KuArfyAiIHAJ [2] http://docs.guava-libraries.googlecode.com/git-history/v9.0/javadoc/com/google/common/collect/Collections2.html#transform(java.util.Collection, com.google.common.base.Function) On Thu, Sep 15, 2011 at 8:46 AM, Craig P. Motlin wrote: > It seems like it doesn't matter much, but sometimes that flexibility is > exactly what you need. Guava has the type signature I described [1]. And I > came to the same conclusion on a similar API. And as Maurizio said, it is > conceptually the correct type signature. Functions really are covariant in > their parameter type and contravariant in their return type. > > Another way of looking at it - using wildcards this way may be unusual, but > it should work: > Mapper mapper = ...; > myTypes.map(mapper); > > [1] > http://docs.guava-libraries.googlecode.com/git-history/v9.0/javadoc/com/google/common/collect/Iterables.html#transform(java.lang.Iterable, > com.google.common.base.Function) > > > On Thu, Sep 15, 2011 at 8:36 AM, Maurizio Cimadamore < > maurizio.cimadamore at oracle.com> wrote: > >> On 15/09/11 12:56, Colin Decker wrote: >> >>> "? extends U" isn't necessary for map. All that allows is assigning what >>> is >>> really, say, an Iterable to Iterable or >>> Iterable >>> without casting, which doesn't help anything. >>> >>> I think they are referring to changing the signature of Collection.map >> (and other related methods) from this: >> >> Iterable map(Mapper mapper) ... >> >> to this: >> >> Iterable map(Mapper mapper) ... >> >> Now, while this case the '? extends' is conceptually correct, I kinda >> agree that the outcome won't be too different should the '? extends' be >> omitted. Since U is a method type-parameter (whose bound is Object - >> unrelated to T), that means that most of the times type-inference will be >> able to infer the right type for U; for example: >> >> Mapper moo; >> Mapper mnn; >> Mapper mii; >> >> List li = ... >> li.map(moo) // U == Object >> li.map(mnn) // U == Number >> li.map(mii) // U == Integer >> >> The above will work regardless of whether you put the '? extends' wildcard >> or not. Where things will be different is when type-parameters are >> explicitly specified: >> >> li.map(mii) // ok with wildcards / error w/o wildcards (U == >> Object) >> li.map(mii) // ok with wildcards / error w/o wildcards (U == >> Number) >> >> Note that the above pattern might be common if i.e. you want to assign the >> result of the map operation to a type that is less specific than the type of >> the mapper. I.e. >> >> List lo = li.map(mii) // U == Integer, type-mismatch, >> List not compatible with List >> List lo = li.map(mii) // ok >> >> Maurizio >> >> >> >> >> >> >> > From forax at univ-mlv.fr Thu Sep 15 08:50:08 2011 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Thu, 15 Sep 2011 17:50:08 +0200 Subject: foreach/filter/map/reduce on Iterable & Iterators In-Reply-To: References: <07D92BF2-8AF1-4E79-9287-87450B2AEF0C@oracle.com> <0BF29E4A-53ED-4F73-BED3-CF1F0810686E@oracle.com> <4E71F149.1030008@oracle.com> Message-ID: <4E721EB0.10004@univ-mlv.fr> On 09/15/2011 04:46 PM, Colin Decker wrote: > Also, you can pass a Mapper to map > even if it takes Mapper. The result is just going to be an > Iterable. That is the actual type of the resulting > Iterable and it's no less usable than if you called it an > Iterable. true for Iterable not for Collection, and why the hell do you want to write wildcards in the user code. The idea is to use wildcards in the API code to don't bother the user. R?mi From brian.goetz at oracle.com Thu Sep 15 08:56:01 2011 From: brian.goetz at oracle.com (Brian Goetz) Date: Thu, 15 Sep 2011 08:56:01 -0700 Subject: Mismatch between the order of the type variable and the order of the SAM method formal parameters In-Reply-To: <4E71A97D.4050206@univ-mlv.fr> References: <4E71A97D.4050206@univ-mlv.fr> Message-ID: In general, it is best if methods that have a single lambda parameter have the lambda parameter last. On Sep 15, 2011, at 12:30 AM, R?mi Forax wrote: > Hi all, > > Here is the declaration of a Reducer: > > interface Reducer { > U reduce(U base, T t); > } > > and how to use it: > > Reducer reducer = (Integer i, String s) -> i + > s.length(); > > As you see the order of the type argument is not > the same as the order of the type of the formal parameter of the lambda > (Integer i, String s). > I think it will be simpler if the signature of reduce() was changed to > swap the two > formal parameters. > > R?mi > > From forax at univ-mlv.fr Thu Sep 15 09:00:12 2011 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Thu, 15 Sep 2011 18:00:12 +0200 Subject: Mismatch between the order of the type variable and the order of the SAM method formal parameters In-Reply-To: References: <4E71A97D.4050206@univ-mlv.fr> Message-ID: <4E72210C.2090906@univ-mlv.fr> On 09/15/2011 05:56 PM, Brian Goetz wrote: > In general, it is best if methods that have a single lambda parameter have the lambda parameter last. I agree for Iterable.reduce, but here it's Reducer.reduce(). R?mi > > > On Sep 15, 2011, at 12:30 AM, R?mi Forax wrote: > >> Hi all, >> >> Here is the declaration of a Reducer: >> >> interface Reducer { >> U reduce(U base, T t); >> } >> >> and how to use it: >> >> Reducer reducer = (Integer i, String s) -> i + >> s.length(); >> >> As you see the order of the type argument is not >> the same as the order of the type of the formal parameter of the lambda >> (Integer i, String s). >> I think it will be simpler if the signature of reduce() was changed to >> swap the two >> formal parameters. >> >> R?mi >> >> From mike.duigou at oracle.com Thu Sep 15 11:46:11 2011 From: mike.duigou at oracle.com (mike.duigou at oracle.com) Date: Thu, 15 Sep 2011 18:46:11 +0000 Subject: hg: lambda/lambda/jdk: reorder Reducer type variables to match invocation order. remove ? super from reducer base value in APIs. Message-ID: <20110915184640.B5650476F4@hg.openjdk.java.net> Changeset: 17c44251d64b Author: mduigou Date: 2011-09-15 11:43 -0700 URL: http://hg.openjdk.java.net/lambda/lambda/jdk/rev/17c44251d64b reorder Reducer type variables to match invocation order. remove ? super from reducer base value in APIs. ! src/share/classes/java/lang/Iterable.java ! src/share/classes/java/lang/Iterables.java ! src/share/classes/java/util/Iterators.java ! src/share/classes/java/util/functions/Reducer.java ! src/share/classes/java/util/functions/Reducers.java ! test/java/util/functions/Reducer/ReducersTest.java From forax at univ-mlv.fr Thu Sep 15 11:55:40 2011 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Thu, 15 Sep 2011 20:55:40 +0200 Subject: hg: lambda/lambda/jdk: reorder Reducer type variables to match invocation order. remove ? super from reducer base value in APIs. In-Reply-To: <20110915184640.B5650476F4@hg.openjdk.java.net> References: <20110915184640.B5650476F4@hg.openjdk.java.net> Message-ID: <4E724A2C.30706@univ-mlv.fr> On 09/15/2011 08:46 PM, mike.duigou at oracle.com wrote: > Changeset: 17c44251d64b > Author: mduigou > Date: 2011-09-15 11:43 -0700 > URL: http://hg.openjdk.java.net/lambda/lambda/jdk/rev/17c44251d64b > > reorder Reducer type variables to match invocation order. remove ? super from reducer base value in APIs. > > ! src/share/classes/java/lang/Iterable.java > ! src/share/classes/java/lang/Iterables.java > ! src/share/classes/java/util/Iterators.java > ! src/share/classes/java/util/functions/Reducer.java > ! src/share/classes/java/util/functions/Reducers.java > ! test/java/util/functions/Reducer/ReducersTest.java > > thanks Mike. R?mi From yshavit at akiban.com Thu Sep 15 16:09:53 2011 From: yshavit at akiban.com (Yuval Shavit) Date: Thu, 15 Sep 2011 19:09:53 -0400 Subject: Mismatch between the order of the type variable and the order of the SAM method formal parameters In-Reply-To: <4E72210C.2090906@univ-mlv.fr> References: <4E71A97D.4050206@univ-mlv.fr> <4E72210C.2090906@univ-mlv.fr> Message-ID: Why should the lambda usually come last? I admit I'm fairly new to functional programming, but it seems that functions/lambdas often come first in methods, which can be useful when currying. I realize that currying isn't part of this project, but it's conceivable that Java would have it in the future. On Thu, Sep 15, 2011 at 12:00 PM, R?mi Forax wrote: > On 09/15/2011 05:56 PM, Brian Goetz wrote: > > In general, it is best if methods that have a single lambda parameter > have the lambda parameter last. > > I agree for Iterable.reduce, but here it's Reducer.reduce(). > > R?mi > > > > > > > On Sep 15, 2011, at 12:30 AM, R?mi Forax wrote: > > > >> Hi all, > >> > >> Here is the declaration of a Reducer: > >> > >> interface Reducer { > >> U reduce(U base, T t); > >> } > >> > >> and how to use it: > >> > >> Reducer reducer = (Integer i, String s) -> i + > >> s.length(); > >> > >> As you see the order of the type argument is not > >> the same as the order of the type of the formal parameter of the lambda > >> (Integer i, String s). > >> I think it will be simpler if the signature of reduce() was changed to > >> swap the two > >> formal parameters. > >> > >> R?mi > >> > >> > > > From David.Holmes at oracle.com Thu Sep 15 16:12:37 2011 From: David.Holmes at oracle.com (David Holmes) Date: Fri, 16 Sep 2011 09:12:37 +1000 Subject: hg: lambda/lambda/jdk: reorder Reducer type variables to match invocation order. remove ? super from reducer base value in APIs. In-Reply-To: <4E724A2C.30706@univ-mlv.fr> References: <20110915184640.B5650476F4@hg.openjdk.java.net> <4E724A2C.30706@univ-mlv.fr> Message-ID: <4E728665.6030202@oracle.com> I may be mis-reading this but didn't you (Remi) ask for parameters of the method to be swapped not the type parameters of the interface? Now they may be consistent but the order seems wrong to me. David On 16/09/2011 4:55 AM, R?mi Forax wrote: > On 09/15/2011 08:46 PM, mike.duigou at oracle.com wrote: >> Changeset: 17c44251d64b >> Author: mduigou >> Date: 2011-09-15 11:43 -0700 >> URL: http://hg.openjdk.java.net/lambda/lambda/jdk/rev/17c44251d64b >> >> reorder Reducer type variables to match invocation order. remove ? super from reducer base value in APIs. >> >> ! src/share/classes/java/lang/Iterable.java >> ! src/share/classes/java/lang/Iterables.java >> ! src/share/classes/java/util/Iterators.java >> ! src/share/classes/java/util/functions/Reducer.java >> ! src/share/classes/java/util/functions/Reducers.java >> ! test/java/util/functions/Reducer/ReducersTest.java >> >> > > thanks Mike. > > R?mi > > From cmotlin at gmail.com Thu Sep 15 19:47:43 2011 From: cmotlin at gmail.com (Craig P. Motlin) Date: Thu, 15 Sep 2011 22:47:43 -0400 Subject: foreach/filter/map/reduce on Iterable & Iterators In-Reply-To: <4E721EB0.10004@univ-mlv.fr> References: <07D92BF2-8AF1-4E79-9287-87450B2AEF0C@oracle.com> <0BF29E4A-53ED-4F73-BED3-CF1F0810686E@oracle.com> <4E71F149.1030008@oracle.com> <4E721EB0.10004@univ-mlv.fr> Message-ID: That's very interesting - I didn't know about the inconsistency within Guava. I tried refactoring my codebase to eliminate the "? extends" and to my surprise, there were no breaks. However, it's still not clear to me what the benefit is. Does type inference work better? I couldn't find any examples where it does. If the only argument is that it's really rare to need that kind of flexibility, I don't think that's a very good reason to drop it. On Thu, Sep 15, 2011 at 11:50 AM, R?mi Forax wrote: > On 09/15/2011 04:46 PM, Colin Decker wrote: > > Also, you can pass a Mapper to > map > > even if it takes Mapper. The result is just going to be an > > Iterable. That is the actual type of the resulting > > Iterable and it's no less usable than if you called it an > > Iterable. > > true for Iterable not for Collection, > and why the hell do you want to write wildcards in the user code. > The idea is to use wildcards in the API code to don't bother the user. > > R?mi > > > From forax at univ-mlv.fr Fri Sep 16 01:10:50 2011 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Fri, 16 Sep 2011 10:10:50 +0200 Subject: hg: lambda/lambda/jdk: reorder Reducer type variables to match invocation order. remove ? super from reducer base value in APIs. In-Reply-To: <4E728665.6030202@oracle.com> References: <20110915184640.B5650476F4@hg.openjdk.java.net> <4E724A2C.30706@univ-mlv.fr> <4E728665.6030202@oracle.com> Message-ID: <4E73048A.2020501@univ-mlv.fr> On 09/16/2011 01:12 AM, David Holmes wrote: > I may be mis-reading this but didn't you (Remi) ask for parameters of > the method to be swapped not the type parameters of the interface? Now > they may be consistent but the order seems wrong to me. yes, you're right, I've ask the opposite but I'm not sure it's better. By example, int sum = 0; for(String s: list) { sum = sum + s.length(); } is translated to: int sum = list.reduce(0, sum, s -> sum + s.length()); as you can see the order of the parameters follow the order of the expression. > > David R?mi From forax at univ-mlv.fr Fri Sep 16 01:26:58 2011 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Fri, 16 Sep 2011 10:26:58 +0200 Subject: Mismatch between the order of the type variable and the order of the SAM method formal parameters In-Reply-To: References: <4E71A97D.4050206@univ-mlv.fr> <4E72210C.2090906@univ-mlv.fr> Message-ID: <4E730852.8030108@univ-mlv.fr> On 09/16/2011 01:09 AM, Yuval Shavit wrote: > Why should the lambda usually come last? I admit I'm fairly new to > functional programming, but it seems that functions/lambdas often come > first in methods, which can be useful when currying. I realize that > currying isn't part of this project, but it's conceivable that Java > would have it in the future. We talk about function that takes a lambda, because the lambda can have a body split on several lines, it's usually more readable to put the lambda at the end. You can compare: int sum = list.reduce(0, (sum, s) -> { if ("".equals(s)) { return 0; } return 1; }); with: int sum = list.reduce((sum, s) -> { if ("".equals(s)) { return 0; } return 1; }, 0); The argument after the lambda is too far from the beginning of the method call. R?mi > > On Thu, Sep 15, 2011 at 12:00 PM, R?mi Forax > wrote: > > On 09/15/2011 05:56 PM, Brian Goetz wrote: > > In general, it is best if methods that have a single lambda > parameter have the lambda parameter last. > > I agree for Iterable.reduce, but here it's Reducer.reduce(). > > R?mi > > > > > > > On Sep 15, 2011, at 12:30 AM, R?mi Forax wrote: > > > >> Hi all, > >> > >> Here is the declaration of a Reducer: > >> > >> interface Reducer { > >> U reduce(U base, T t); > >> } > >> > >> and how to use it: > >> > >> Reducer reducer = (Integer i, String s) -> > i + > >> s.length(); > >> > >> As you see the order of the type argument is not > >> the same as the order of the type of the formal parameter of > the lambda > >> (Integer i, String s). > >> I think it will be simpler if the signature of reduce() was > changed to > >> swap the two > >> formal parameters. > >> > >> R?mi > >> > >> > > > From yshavit at akiban.com Fri Sep 16 05:44:20 2011 From: yshavit at akiban.com (Yuval Shavit) Date: Fri, 16 Sep 2011 08:44:20 -0400 Subject: Mismatch between the order of the type variable and the order of the SAM method formal parameters In-Reply-To: <4E730852.8030108@univ-mlv.fr> References: <4E71A97D.4050206@univ-mlv.fr> <4E72210C.2090906@univ-mlv.fr> <4E730852.8030108@univ-mlv.fr> Message-ID: That makes sense, thanks Remi. Of course, if Java had currying *and* named parameters, we could have the best of all possible worlds... :-) On Fri, Sep 16, 2011 at 4:26 AM, R?mi Forax wrote: > On 09/16/2011 01:09 AM, Yuval Shavit wrote: > > Why should the lambda usually come last? I admit I'm fairly new to > functional programming, but it seems that functions/lambdas often come first > in methods, which can be useful when currying. I realize that currying isn't > part of this project, but it's conceivable that Java would have it in the > future. > > > We talk about function that takes a lambda, > because the lambda can have a body split on several lines, > it's usually more readable to put the lambda at the end. > > You can compare: > int sum = list.reduce(0, (sum, s) -> { > if ("".equals(s)) { > return 0; > } > return 1; > }); > > with: > int sum = list.reduce((sum, s) -> { > if ("".equals(s)) { > return 0; > } > return 1; > }, 0); > > The argument after the lambda is too far from the beginning of > the method call. > > R?mi > > > > On Thu, Sep 15, 2011 at 12:00 PM, R?mi Forax wrote: > >> On 09/15/2011 05:56 PM, Brian Goetz wrote: >> > In general, it is best if methods that have a single lambda parameter >> have the lambda parameter last. >> >> I agree for Iterable.reduce, but here it's Reducer.reduce(). >> >> R?mi >> >> > >> > >> > On Sep 15, 2011, at 12:30 AM, R?mi Forax wrote: >> > >> >> Hi all, >> >> >> >> Here is the declaration of a Reducer: >> >> >> >> interface Reducer { >> >> U reduce(U base, T t); >> >> } >> >> >> >> and how to use it: >> >> >> >> Reducer reducer = (Integer i, String s) -> i + >> >> s.length(); >> >> >> >> As you see the order of the type argument is not >> >> the same as the order of the type of the formal parameter of the lambda >> >> (Integer i, String s). >> >> I think it will be simpler if the signature of reduce() was changed to >> >> swap the two >> >> formal parameters. >> >> >> >> R?mi >> >> >> >> >> >> >> > > From forax at univ-mlv.fr Fri Sep 16 05:54:36 2011 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Fri, 16 Sep 2011 14:54:36 +0200 Subject: Mismatch between the order of the type variable and the order of the SAM method formal parameters In-Reply-To: References: <4E71A97D.4050206@univ-mlv.fr> <4E72210C.2090906@univ-mlv.fr> <4E730852.8030108@univ-mlv.fr> Message-ID: <4E73470C.8020307@univ-mlv.fr> On 09/16/2011 02:44 PM, Yuval Shavit wrote: > That makes sense, thanks Remi. Of course, if Java had currying *and* > named parameters, we could have the best of all possible worlds... :-) Java 8 will have no function type so I have some trouble to imagine what you want exactly when you say that Java should have curry. For named parameters, it's a good idea to see if the community want something like that and propose it as an item of Coin2 (the flip side). R?mi > > On Fri, Sep 16, 2011 at 4:26 AM, R?mi Forax > wrote: > > On 09/16/2011 01:09 AM, Yuval Shavit wrote: >> Why should the lambda usually come last? I admit I'm fairly new >> to functional programming, but it seems that functions/lambdas >> often come first in methods, which can be useful when currying. I >> realize that currying isn't part of this project, but it's >> conceivable that Java would have it in the future. > > We talk about function that takes a lambda, > because the lambda can have a body split on several lines, > it's usually more readable to put the lambda at the end. > > You can compare: > int sum = list.reduce(0, (sum, s) -> { > if ("".equals(s)) { > return 0; > } > return 1; > }); > > with: > int sum = list.reduce((sum, s) -> { > if ("".equals(s)) { > return 0; > } > return 1; > }, 0); > > The argument after the lambda is too far from the beginning of > the method call. > > R?mi > > >> >> On Thu, Sep 15, 2011 at 12:00 PM, R?mi Forax > > wrote: >> >> On 09/15/2011 05:56 PM, Brian Goetz wrote: >> > In general, it is best if methods that have a single lambda >> parameter have the lambda parameter last. >> >> I agree for Iterable.reduce, but here it's Reducer.reduce(). >> >> R?mi >> >> > >> > >> > On Sep 15, 2011, at 12:30 AM, R?mi Forax wrote: >> > >> >> Hi all, >> >> >> >> Here is the declaration of a Reducer: >> >> >> >> interface Reducer { >> >> U reduce(U base, T t); >> >> } >> >> >> >> and how to use it: >> >> >> >> Reducer reducer = (Integer i, String >> s) -> i + >> >> s.length(); >> >> >> >> As you see the order of the type argument >> is not >> >> the same as the order of the type of the formal parameter >> of the lambda >> >> (Integer i, String s). >> >> I think it will be simpler if the signature of reduce() >> was changed to >> >> swap the two >> >> formal parameters. >> >> >> >> R?mi >> >> >> >> >> >> >> > > From c.m.bockisch at cs.utwente.nl Fri Sep 16 06:28:46 2011 From: c.m.bockisch at cs.utwente.nl (Christoph Bockisch) Date: Fri, 16 Sep 2011 15:28:46 +0200 Subject: Invitation to attend workshop on Virtual Machines and Intermediate Languages (VMIL) @ SPLASH 2011 Message-ID: <4E734F0E.6060403@cs.utwente.nl> Dear colleagues, we would like to invite you to attend the workshop on Virtual Machines and Intermediate Languages (VMIL 2011), which will be co-located with SPLASH. Please note that the early registration deadline for SPLASH is Sept. 23 and that it is required that you register for the workshop participation. This workshop is a forum for research in virtual machines (VM) and intermediate languages (IL). It is dedicated to identifying programming mechanisms and constructs that are currently realized as code transformations or implemented in libraries but should rather be supported at VM and IL level. Besides the presentation of accepted papers, the workshop features an invited talk by Lars Bak, Google For more details on the format and program of the workshop please see our homepage: http://www.cs.iastate.edu/~design/vmil/ We look forward to meeting you at the workshop. Best regards, Christoph Bockisch, Hridesh Rajan, Michael Haupt and Robert Dyer VMIL 2011 Organizers From yshavit at akiban.com Fri Sep 16 06:32:45 2011 From: yshavit at akiban.com (Yuval Shavit) Date: Fri, 16 Sep 2011 09:32:45 -0400 Subject: Mismatch between the order of the type variable and the order of the SAM method formal parameters In-Reply-To: <4E73470C.8020307@univ-mlv.fr> References: <4E71A97D.4050206@univ-mlv.fr> <4E72210C.2090906@univ-mlv.fr> <4E730852.8030108@univ-mlv.fr> <4E73470C.8020307@univ-mlv.fr> Message-ID: I realize Java 8 won't have currying, but it's conceivable that Java N > 8 may. If Java does get there, it'd be unfortunate if existing code has args are in the "wrong" order for natural currying. Though I wonder if one could work around it in various ways (optionally curry from the right, curry by named params (if those exist at some point), etc). Anyway, at this point I'm just kind of firing up the "what-if" machine. I was originally just wondering if there's a particular reason to put lambdas at the end of the args list, and the answer is yes, so I'm satisfied. :) On Fri, Sep 16, 2011 at 8:54 AM, R?mi Forax wrote: > On 09/16/2011 02:44 PM, Yuval Shavit wrote: > > That makes sense, thanks Remi. Of course, if Java had currying *and* named > parameters, we could have the best of all possible worlds... :-) > > > Java 8 will have no function type so I have some trouble to imagine > what you want exactly when you say that Java should have curry. > For named parameters, it's a good idea to see if the community want > something like that > and propose it as an item of Coin2 (the flip side). > > R?mi > > > > On Fri, Sep 16, 2011 at 4:26 AM, R?mi Forax wrote: > >> On 09/16/2011 01:09 AM, Yuval Shavit wrote: >> >> Why should the lambda usually come last? I admit I'm fairly new to >> functional programming, but it seems that functions/lambdas often come first >> in methods, which can be useful when currying. I realize that currying isn't >> part of this project, but it's conceivable that Java would have it in the >> future. >> >> >> We talk about function that takes a lambda, >> because the lambda can have a body split on several lines, >> it's usually more readable to put the lambda at the end. >> >> You can compare: >> int sum = list.reduce(0, (sum, s) -> { >> if ("".equals(s)) { >> return 0; >> } >> return 1; >> }); >> >> with: >> int sum = list.reduce((sum, s) -> { >> if ("".equals(s)) { >> return 0; >> } >> return 1; >> }, 0); >> >> The argument after the lambda is too far from the beginning of >> the method call. >> >> R?mi >> >> >> >> On Thu, Sep 15, 2011 at 12:00 PM, R?mi Forax wrote: >> >>> On 09/15/2011 05:56 PM, Brian Goetz wrote: >>> > In general, it is best if methods that have a single lambda parameter >>> have the lambda parameter last. >>> >>> I agree for Iterable.reduce, but here it's Reducer.reduce(). >>> >>> R?mi >>> >>> > >>> > >>> > On Sep 15, 2011, at 12:30 AM, R?mi Forax wrote: >>> > >>> >> Hi all, >>> >> >>> >> Here is the declaration of a Reducer: >>> >> >>> >> interface Reducer { >>> >> U reduce(U base, T t); >>> >> } >>> >> >>> >> and how to use it: >>> >> >>> >> Reducer reducer = (Integer i, String s) -> i + >>> >> s.length(); >>> >> >>> >> As you see the order of the type argument is not >>> >> the same as the order of the type of the formal parameter of the >>> lambda >>> >> (Integer i, String s). >>> >> I think it will be simpler if the signature of reduce() was changed to >>> >> swap the two >>> >> formal parameters. >>> >> >>> >> R?mi >>> >> >>> >> >>> >>> >>> >> >> > > From howard.lovatt at gmail.com Fri Sep 16 18:17:15 2011 From: howard.lovatt at gmail.com (Howard Lovatt) Date: Sat, 17 Sep 2011 11:17:15 +1000 Subject: Mismatch between the order of the type variable and the order of the SAM method formal parameters In-Reply-To: References: <4E71A97D.4050206@univ-mlv.fr> <4E72210C.2090906@univ-mlv.fr> <4E730852.8030108@univ-mlv.fr> <4E73470C.8020307@univ-mlv.fr> Message-ID: The method handle api allows binding to any position as does C++. It is feasible that java post 7 will come up with some syntax for binding as opposed to the subset of binding, currying. Therefore I would suggest not worrying about currying [rhyming deliberate!]. On 16 September 2011 23:32, Yuval Shavit wrote: > I realize Java 8 won't have currying, but it's conceivable that Java N > 8 > may. If Java does get there, it'd be unfortunate if existing code has args > are in the "wrong" order for natural currying. Though I wonder if one could > work around it in various ways (optionally curry from the right, curry by > named params (if those exist at some point), etc). > > Anyway, at this point I'm just kind of firing up the "what-if" machine. I > was originally just wondering if there's a particular reason to put lambdas > at the end of the args list, and the answer is yes, so I'm satisfied. :) > > On Fri, Sep 16, 2011 at 8:54 AM, R?mi Forax wrote: > > > On 09/16/2011 02:44 PM, Yuval Shavit wrote: > > > > That makes sense, thanks Remi. Of course, if Java had currying *and* > named > > parameters, we could have the best of all possible worlds... :-) > > > > > > Java 8 will have no function type so I have some trouble to imagine > > what you want exactly when you say that Java should have curry. > > For named parameters, it's a good idea to see if the community want > > something like that > > and propose it as an item of Coin2 (the flip side). > > > > R?mi > > > > > > > > On Fri, Sep 16, 2011 at 4:26 AM, R?mi Forax wrote: > > > >> On 09/16/2011 01:09 AM, Yuval Shavit wrote: > >> > >> Why should the lambda usually come last? I admit I'm fairly new to > >> functional programming, but it seems that functions/lambdas often come > first > >> in methods, which can be useful when currying. I realize that currying > isn't > >> part of this project, but it's conceivable that Java would have it in > the > >> future. > >> > >> > >> We talk about function that takes a lambda, > >> because the lambda can have a body split on several lines, > >> it's usually more readable to put the lambda at the end. > >> > >> You can compare: > >> int sum = list.reduce(0, (sum, s) -> { > >> if ("".equals(s)) { > >> return 0; > >> } > >> return 1; > >> }); > >> > >> with: > >> int sum = list.reduce((sum, s) -> { > >> if ("".equals(s)) { > >> return 0; > >> } > >> return 1; > >> }, 0); > >> > >> The argument after the lambda is too far from the beginning of > >> the method call. > >> > >> R?mi > >> > >> > >> > >> On Thu, Sep 15, 2011 at 12:00 PM, R?mi Forax wrote: > >> > >>> On 09/15/2011 05:56 PM, Brian Goetz wrote: > >>> > In general, it is best if methods that have a single lambda parameter > >>> have the lambda parameter last. > >>> > >>> I agree for Iterable.reduce, but here it's Reducer.reduce(). > >>> > >>> R?mi > >>> > >>> > > >>> > > >>> > On Sep 15, 2011, at 12:30 AM, R?mi Forax wrote: > >>> > > >>> >> Hi all, > >>> >> > >>> >> Here is the declaration of a Reducer: > >>> >> > >>> >> interface Reducer { > >>> >> U reduce(U base, T t); > >>> >> } > >>> >> > >>> >> and how to use it: > >>> >> > >>> >> Reducer reducer = (Integer i, String s) -> i + > >>> >> s.length(); > >>> >> > >>> >> As you see the order of the type argument is not > >>> >> the same as the order of the type of the formal parameter of the > >>> lambda > >>> >> (Integer i, String s). > >>> >> I think it will be simpler if the signature of reduce() was changed > to > >>> >> swap the two > >>> >> formal parameters. > >>> >> > >>> >> R?mi > >>> >> > >>> >> > >>> > >>> > >>> > >> > >> > > > > > > -- -- Howard. From kasperni at gmail.com Sat Sep 17 14:54:03 2011 From: kasperni at gmail.com (Kasper Nielsen) Date: Sat, 17 Sep 2011 23:54:03 +0200 Subject: Reducer interface Message-ID: <4E7516FB.9050000@gmail.com> Hi, Can somebody explain to me how the Reducer interface works in a parallel setting? I'm using something like E reduce(E a, E b) myself. And I fail to understand how you can use two different parameter types unless you force all usage to be serial (non-parallel) application of elements. cheers Kasper From forax at univ-mlv.fr Sat Sep 17 15:23:59 2011 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Sun, 18 Sep 2011 00:23:59 +0200 Subject: Reducer interface In-Reply-To: <4E7516FB.9050000@gmail.com> References: <4E7516FB.9050000@gmail.com> Message-ID: <4E751DFF.6030607@univ-mlv.fr> On 09/17/2011 11:54 PM, Kasper Nielsen wrote: > Hi, > > Can somebody explain to me how the Reducer interface works in a parallel > setting? > I'm using something like E reduce(E a, E b) myself. > And I fail to understand how you can use two different parameter types > unless you force all usage to be serial (non-parallel) application of > elements. > > cheers > Kasper > ooops, very good question, I remember asking myself the same question one year ago contemplating the ParallelArray API [1] of Doug Lea. R?mi [1] http://gee.cs.oswego.edu/dl/jsr166/dist/extra166ydocs/extra166y/ParallelArray.html#reduce%28extra166y.Ops.Reducer,%20T%29 From neal at gafter.com Sat Sep 17 16:43:22 2011 From: neal at gafter.com (Neal Gafter) Date: Sat, 17 Sep 2011 16:43:22 -0700 Subject: Reducer interface In-Reply-To: <4E7516FB.9050000@gmail.com> References: <4E7516FB.9050000@gmail.com> Message-ID: The operation this library calls "reduce" is more properly named "left fold" and, unless you can exploit algebraic properties of the function, is inherently sequential. When the element and output types are the same, and the function is known to be associative, you can use "parallel prefix" to compute the result in O(log n) time using O(n/log n) processors. On Sat, Sep 17, 2011 at 2:54 PM, Kasper Nielsen wrote: > Hi, > > Can somebody explain to me how the Reducer interface works in a parallel > setting? > I'm using something like E reduce(E a, E b) myself. > And I fail to understand how you can use two different parameter types > unless you force all usage to be serial (non-parallel) application of > elements. > > cheers > Kasper > > From mbien at fh-landshut.de Sat Sep 17 17:36:00 2011 From: mbien at fh-landshut.de (Michael Bien) Date: Sun, 18 Sep 2011 02:36:00 +0200 Subject: Reducer interface In-Reply-To: References: <4E7516FB.9050000@gmail.com> Message-ID: <4E753CF0.9030102@fh-landshut.de> in case anybody is interested.. data-parallel implementation which does most work in device cache using OpenCL (JOCL). https://github.com/mbien/jocl/blob/edge/src/com/jogamp/opencl/util/pp/reduce.cl https://github.com/mbien/jocl/blob/edge/src/com/jogamp/opencl/util/pp/Reduction.java written for GPUs but works ok on CPUs. regards, michael -- - - - - http://michael-bien.com On 09/18/2011 01:43 AM, Neal Gafter wrote: > The operation this library calls "reduce" is more properly named "left fold" > and, unless you can exploit algebraic properties of the function, is > inherently sequential. > > When the element and output types are the same, and the function is known to > be associative, you can use "parallel prefix" to compute the result in O(log > n) time using O(n/log n) processors. > > On Sat, Sep 17, 2011 at 2:54 PM, Kasper Nielsen wrote: > >> Hi, >> >> Can somebody explain to me how the Reducer interface works in a parallel >> setting? >> I'm using something like E reduce(E a, E b) myself. >> And I fail to understand how you can use two different parameter types >> unless you force all usage to be serial (non-parallel) application of >> elements. >> >> cheers >> Kasper >> >> > From dl at cs.oswego.edu Sun Sep 18 04:59:10 2011 From: dl at cs.oswego.edu (Doug Lea) Date: Sun, 18 Sep 2011 07:59:10 -0400 Subject: Reducer interface In-Reply-To: References: <4E7516FB.9050000@gmail.com> Message-ID: <4E75DD0E.9060603@cs.oswego.edu> On 09/17/11 19:43, Neal Gafter wrote: > The operation this library calls "reduce" is more properly named "left fold" I think the properness depends on whether you are in the data-parallel vs functional-programming community :-) > and, unless you can exploit algebraic properties of the function, is > inherently sequential. These reduction methods should indeed have specs saying that results are are combined left-associatively. Users can then decide whether this makes sense for their application. I say it in this way because some functions (like most involving floating point operations) are not strictly associative but the results may be acceptable. > > When the element and output types are the same, and the function is known to > be associative, you can use "parallel prefix" to compute the result in O(log > n) time using O(n/log n) processors. (Although in practice, parallel-prefix usually only starts winning when you have more than about 8 cores.) > > On Sat, Sep 17, 2011 at 2:54 PM, Kasper Nielsen wrote: > >> Hi, >> >> Can somebody explain to me how the Reducer interface works in a parallel >> setting? >> I'm using something like E reduce(E a, E b) myself. >> And I fail to understand how you can use two different parameter types >> unless you force all usage to be serial (non-parallel) application of >> elements. The flexibility in first argument type sometimes allows you to do a map step in conjunction with reduce. Not often, but still, there is no reason to preclude it. -Doug From mike.duigou at oracle.com Mon Sep 19 12:17:22 2011 From: mike.duigou at oracle.com (Mike Duigou) Date: Mon, 19 Sep 2011 12:17:22 -0700 Subject: Setup for extension method weaving Message-ID: In order to run the unit tests provided for the lambda functional interfaces it's necessary to pre-link the extension methods aka "weaving" in the JRE rt.jar. The current lambda workspace will weave rt.jar if the defender prototype weaver is located in a peer directory: ~/ code/ jdk8/ defender-prototype/ (http://hg.openjdk.java.net/lambda/defender-prototype/) lambda/ (http://hg.openjdk.java.net/lambda/lambda) I have had inconsistent results with the latest version of the prototype weaver. It seems to work for clean builds but fails for rebuilds. As a result I'm still using hg rev 28 (cdd54432fd05) which still works. [hg update -C -r 28] If you are writing code which uses extension methods you will need to weave before running using current VMs. The weaver can weave either a directory or a jar to another jar or directory. It can't weave in-place. $(BOOT_JAVA_CMD) -cp ../../../../defender-prototype/distrib/jsr335-agent.jar:../../../../defender-prototype/lib/asm-all-4.0.jar jsr335.agent.batch.Main -v -d rt.jar rt-preweave.jar source (-d) is rt-preweave.jar destination (parameter) is rt.jar Mike From jadoth.paigan at googlemail.com Tue Sep 20 09:04:18 2011 From: jadoth.paigan at googlemail.com (Paigan Jadoth) Date: Tue, 20 Sep 2011 18:04:18 +0200 Subject: Expressiveness of function types naming Message-ID: Hi list, May I suggest to refactor the namings in function types like Predicate#eval, Block, etc. to improve expressiveness? For example: Predicate#eval(T) "eval" sounds very quick&dirty-ly decided like in good old C hacking. If at all, it should be named "evaluate". But on a closer look: Does a predicate really evaluate an argument? Not really. A predicate as a whole is evaluated. The predicate can apply to an argument. When thinking/talking about a predicate do we say "if predicate isAdult applies to person p" or do we really say "if evaluating person p with predicate isAdult yields true"? Wether to choose "apply(T)" or "applies(T)" or "appliesTo(T)" may be subject to further discussion (although I'd suggest that if methods in general represent actions, not states, then "apply" would be the best - and also shortest - choice.) Block: Is "Block" really the best name for a piece of code that is effectively an operation which you can execute on an argument? The general conception of a "Block" is this: { ... } Where's the input object in this? Nowhere. Does anyone really talk about an operation like "... and then the printing block is applied to the argument"? Or isn't it more like "... and then the printing operation is executed on the argument"? Hence, I'd suggest renaming "Block" to "Operation" and Block#apply() to Operation#execute() So it would be for example: Person joe = ... ; Operation printPerson = (Person p) -> { ... }; printPerson.execute(joe); A "Block" would be an Operation that takes no parameter at all (may be usefull as well). Like: Block printCurrentTime = () -> { ... }; printCurrentTime.execute(); At least that is the terminology for function types that I use in my work-in-progress next generation collections framework (O.T., but anyway: sadly no real website atm, only a blog [1] and some first simple documents [2]). I planned to replace / merge my local function types with standardized types from JDK once released, of course. But I can hardly in good conscience replace an expressive type "Operation" by a confusing one-argument-"Block" :-(. Of course my personal stuff doesn't matter for Java as a whole, still I think many of people will have an unnecessary hard time internalizing / using / reading the new function types as they are currently named in JDK. Thank you for reading [1] http://jadoth.blogspot.com/ [2] http://www.jadoth.net/files/CollectionContentBehaviourConstraints.pdf From kasperni at gmail.com Tue Sep 20 09:24:42 2011 From: kasperni at gmail.com (Kasper Nielsen) Date: Tue, 20 Sep 2011 18:24:42 +0200 Subject: Expressiveness of function types naming In-Reply-To: References: Message-ID: <4E78BE4A.1050405@gmail.com> On 20-09-2011 18:04, Paigan Jadoth wrote: > Hi list, > > > May I suggest to refactor the namings in function types like Predicate#eval, > Block, etc. to improve expressiveness? > For example: > > > Predicate#eval(T) > > "eval" sounds very quick&dirty-ly decided like in good old C hacking. > If at all, it should be named "evaluate". But on a closer look: Does a > predicate really evaluate an argument? Not really. A predicate as a whole is > evaluated. The predicate can apply to an argument. > When thinking/talking about a predicate do we say "if predicate isAdult > applies to person p" or do we really say "if evaluating person p with > predicate isAdult yields true"? I would prefer the method name accept(). As in "does the predicate accept the specified element." > Block: > > Is "Block" really the best name for a piece of code that is effectively an > operation which you can execute on an argument? > The general conception of a "Block" is this: > { ... } > Where's the input object in this? Nowhere. > Does anyone really talk about an operation like "... and then the printing > block is applied to the argument"? > Or isn't it more like "... and then the printing operation is executed on > the argument"? > > Hence, I'd suggest renaming "Block" to "Operation" and Block#apply() to > Operation#execute() > Yeah I definitely does not like the name Block either. At first I thought it had something to do with blocking/non-blocking IO or functions (as in ForkJoinPool.ManagedBlocker). Operation is one possibility for a name. I would prefer the name Procedure as used in the ParallelArray API. cheers Kasper From mike.duigou at oracle.com Tue Sep 20 09:28:56 2011 From: mike.duigou at oracle.com (Mike Duigou) Date: Tue, 20 Sep 2011 09:28:56 -0700 Subject: Expressiveness of function types naming In-Reply-To: References: Message-ID: <7B654B51-6B31-42BC-8E5B-BD192E9A7724@oracle.com> The current names are not final nor have they been officially proposed to the lambda expert group for final ratification. On Sep 20 2011, at 09:04 , Paigan Jadoth wrote: > Block: The intent for the name Block is that it corresponds to a basic block ie. { [statement;]+ } There is an intended correspondance between for(Foo each : foos) { bar(each); } and foos.forEach(each -> {bar(each);}); > Hence, I'd suggest renaming "Block" to "Operation" and Block#apply() to > Operation#execute() Operation seems too ambiguous to me. Mike From mike.duigou at oracle.com Tue Sep 20 16:31:18 2011 From: mike.duigou at oracle.com (mike.duigou at oracle.com) Date: Tue, 20 Sep 2011 23:31:18 +0000 Subject: hg: lambda/lambda/jdk: import c77b41652266 Message-ID: <20110920233129.278B447839@hg.openjdk.java.net> Changeset: ebf1aa4a7186 Author: mduigou Date: 2011-09-20 16:26 -0700 URL: http://hg.openjdk.java.net/lambda/lambda/jdk/rev/ebf1aa4a7186 import c77b41652266 ! make/netbeans/README ! make/netbeans/common/closed-share-view.ent ! make/netbeans/common/java-data-native.ent ! make/netbeans/common/java-data-no-native.ent ! make/netbeans/common/jtreg-view.ent ! make/netbeans/common/sample-view.ent ! make/netbeans/common/share-view.ent ! make/netbeans/common/unix-view.ent ! make/netbeans/common/windows-view.ent ! make/netbeans/j2se/nbproject/project.xml From stuart.marks at oracle.com Fri Sep 23 11:11:16 2011 From: stuart.marks at oracle.com (Stuart Marks) Date: Fri, 23 Sep 2011 11:11:16 -0700 Subject: summary of point lambdafication survey Message-ID: <4E7CCBC4.7050706@oracle.com> Brian has asked me to summarize the results of the point lambdafication survey he sent out a few weeks ago: http://mail.openjdk.java.net/pipermail/lambda-dev/2011-August/003919.html There were 27 responses. Several responses were from the same individual, and some respondents didn't provide a name (and in at least one case a response was intended to supersede an earlier response) so it's hard to tell how many people responded. Perhaps there were twenty different individuals. Thanks to all who contributed. Below is a brief summary of the responses. For the sake of brevity, I've taken some liberties in this summary; some of you typed a lot of code! My opinions and comments on the results will follow in a separate message. * java.util.logging.Logger -- log(level, Callable) -- 3 requests - pass a function that generates a log message - avoids overhead of string creation if level isn't enabled - variations for finest(), info(), etc. - need to deal with Exception thrown from Callable.call() * BufferedReader.eachLine(block) -- 3 requests - run a block on each line read - variations with filtering * java.util.concurrent.locks.Lock -- withLock(block) -- 2 requests - runs block with lock held, release lock in finally-clause - variations for lock with timeout, tryLock * java.util.regex -- each() on Pattern, Matcher, or String -- 2 requests - run a block on each match, possibly returning a replacement * java.sql.ResultSet -- each(block) -- 2 requests - run a block for each row in a ResultSet * java.nio.Buffer family -- forEach(block) - runs block on each buffer element * Swing/AWT event listeners -- multiple requests - rearrange non-SAM listeners to be suitable for lambdas * SwingUtilities executeAndWait(callable), invokeAndWait(callable) - convenience functions for current APIs, possibly also returning a value * SwingWorker(callable) - convenience method for creating a SwingWorker - callable supplies implementation of doInBackground() * java.nio.channels.FileChannel -- lockDuring(block) - runs block with file lock held, release lock in finally-clause - variation for tryLock * java.nio.file.Files -- eachFile(block) - run block for each file in a directory * Collections.toMap(keyGen) - for each element in a Collection, generate a key, store into a Map - could be a static utility method or an extension method * Process.onExit(block) - execute block when the process exits * Integer.times(block) -- execute block N times * Objects.equals(obj1, obj2, fieldGetters...) - helper method for writing equals() methods - handles identity, casting, field-by-field comparisons * Throwable.visitCauses(block) - run block for each throwable in the chain of causes * ThreadLocal(callable) - callable supplies the implementation of initialValue() - provides lazy initialization of thread-locals s'marks From stuart.marks at oracle.com Fri Sep 23 11:29:39 2011 From: stuart.marks at oracle.com (Stuart Marks) Date: Fri, 23 Sep 2011 11:29:39 -0700 Subject: summary of point lambdafication survey In-Reply-To: <4E7CCBC4.7050706@oracle.com> References: <4E7CCBC4.7050706@oracle.com> Message-ID: <4E7CD013.40304@oracle.com> Here are some comments on the survey results. These are my opinions only; no decisions have been made on any of this stuff yet. > * java.util.logging.Logger -- log(level, Callable) -- 3 requests > - pass a function that generates a log message > - avoids overhead of string creation if level isn't enabled > - variations for finest(), info(), etc. > - need to deal with Exception thrown from Callable.call() The current logging APIs seem to be a sore point; the main concerns seem to be avoiding useless message creation overhead and code clutter. Seems like lambda can help a lot here. This is an instance of using lambda for delayed evaluation. > * BufferedReader.eachLine(block) -- 3 requests > - run a block on each line read > - variations with filtering This was pretty popular too. However, current thinking seems to be to expose the individual items of an aggregate as an Iterable instead of adding forEach(block) APIs. Having an Iterable facilitates use of the enhanced-for statement. It also facilitates passing to the new filter(), map(), etc. functions. This seems quite attractive, as it avoids filtered, extracted, massaged, etc. variations that would seem to be necessary if we were to add a forEach(block) style API. > * java.util.concurrent.locks.Lock -- withLock(block) -- 2 requests > - runs block with lock held, release lock in finally-clause > - variations for lock with timeout, tryLock An example of the execute-around idiom; seems like it would save some code clutter. > * java.util.regex -- each() on Pattern, Matcher, or String -- 2 requests > - run a block on each match, possibly returning a replacement Possibly expose an Iterable instead of forEach(lambda). Seems promising, especially in conjunction with enhanced line processing in BufferedReader. > * java.sql.ResultSet -- each(block) -- 2 requests > - run a block for each row in a ResultSet > > * java.nio.Buffer family -- forEach(block) > - runs block on each buffer element More examples of forEach that are probably better off as Iterables. > * Swing/AWT event listeners -- multiple requests > - rearrange non-SAM listeners to be suitable for lambdas > > * SwingUtilities executeAndWait(callable), invokeAndWait(callable) > - convenience functions for current APIs, possibly also returning a value > > * SwingWorker(callable) > - convenience method for creating a SwingWorker > - callable supplies implementation of doInBackground() I'm kind of distant from AWT/Swing, but those APIs seem to be a fertile ground for improvements using lambda. I'll forward this stuff to the client folks. Of course, anyone is free to suggest these ideas on the appropriate mailing lists (probably swing-dev or awt-dev). > * java.nio.channels.FileChannel -- lockDuring(block) > - runs block with file lock held, release lock in finally-clause > - variation for tryLock Another execute-around. > * java.nio.file.Files -- eachFile(block) > - run block for each file in a directory Another example better expressed via Iterable. This would also be interesting in combination with the nio FileVisitor stuff exposed as an Iterable. > * Collections.toMap(keyGen) > - for each element in a Collection, generate a key, store into a Map > - could be a static utility method or an extension method This is interesting. It's sort-of halfway between two different ideas. One take would be for it to take a value-generating lambda (a Mapper) which would be run over each element in a Set. The result would be a Map object whose keys are the elements from the Collection and whose values are the results from the Mapper. Another take is to generate keys from each element of a Collection; the question then what to do in the case of duplicate keys. We'd want the resulting Map to have multiple values for a single key. This could be expressed as a (hypothetical) MultiMap, or as an ordinary Map whose values are Lists. > * Process.onExit(block) > - execute block when the process exits > > * Integer.times(block) -- execute block N times > > * Objects.equals(obj1, obj2, fieldGetters...) > - helper method for writing equals() methods > - handles identity, casting, field-by-field comparisons > > * Throwable.visitCauses(block) > - run block for each throwable in the chain of causes > > * ThreadLocal(callable) > - callable supplies the implementation of initialValue() > - provides lazy initialization of thread-locals > > s'marks From stuart.marks at oracle.com Fri Sep 23 11:44:51 2011 From: stuart.marks at oracle.com (Stuart Marks) Date: Fri, 23 Sep 2011 11:44:51 -0700 Subject: summary of point lambdafication survey In-Reply-To: <4E7CD013.40304@oracle.com> References: <4E7CCBC4.7050706@oracle.com> <4E7CD013.40304@oracle.com> Message-ID: <76553008-C408-4C7E-ADA4-F26B3038E9FC@oracle.com> >> * Collections.toMap(keyGen) >> - for each element in a Collection, generate a key, store into a Map >> - could be a static utility method or an extension method > > This is interesting. It's sort-of halfway between two different ideas. > > One take would be for it to take a value-generating lambda (a Mapper) which > would be run over each element in a Set. The result would be a Map object whose > keys are the elements from the Collection and whose values are the results from > the Mapper. > > Another take is to generate keys from each element of a Collection; the > question then what to do in the case of duplicate keys. We'd want the resulting > Map to have multiple values for a single key. This could be expressed as a > (hypothetical) MultiMap, or as an ordinary Map whose values are Lists. ... which turns it into groupBy. From yshavit at akiban.com Fri Sep 23 13:39:07 2011 From: yshavit at akiban.com (Yuval Shavit) Date: Fri, 23 Sep 2011 16:39:07 -0400 Subject: summary of point lambdafication survey In-Reply-To: <76553008-C408-4C7E-ADA4-F26B3038E9FC@oracle.com> References: <4E7CCBC4.7050706@oracle.com> <4E7CD013.40304@oracle.com> <76553008-C408-4C7E-ADA4-F26B3038E9FC@oracle.com> Message-ID: Collections.toMap sounds like a convenience function for a fold, is that about right? On Fri, Sep 23, 2011 at 2:44 PM, Stuart Marks wrote: > > >> * Collections.toMap(keyGen) > >> - for each element in a Collection, generate a key, store into a Map > >> - could be a static utility method or an extension method > > > > This is interesting. It's sort-of halfway between two different ideas. > > > > One take would be for it to take a value-generating lambda (a Mapper) > which > > would be run over each element in a Set. The result would be a Map object > whose > > keys are the elements from the Collection and whose values are the > results from > > the Mapper. > > > > Another take is to generate keys from each element of a Collection; the > > question then what to do in the case of duplicate keys. We'd want the > resulting > > Map to have multiple values for a single key. This could be expressed as > a > > (hypothetical) MultiMap, or as an ordinary Map whose values are Lists. > > ... which turns it into groupBy. > > > From stuart.marks at oracle.com Fri Sep 23 14:55:06 2011 From: stuart.marks at oracle.com (Stuart Marks) Date: Fri, 23 Sep 2011 14:55:06 -0700 Subject: summary of point lambdafication survey In-Reply-To: References: <4E7CCBC4.7050706@oracle.com> <4E7CD013.40304@oracle.com> <76553008-C408-4C7E-ADA4-F26B3038E9FC@oracle.com> Message-ID: <4E7D003A.8020500@oracle.com> On 9/23/11 1:39 PM, Yuval Shavit wrote: > Collections.toMap sounds like a convenience function for a fold, is that about > right? I don't think so. This might be because of how heavily I had condensed the original submission. Let me explain. As it stood, the original submission was interesting but not quite right in my view. It seemed to lead in either of two different directions, both of which are potentially very useful in their own right. Perhaps the submitter could post here to clarify, in case I've misinterpreted something. 1) The first direction is, given a Set and a Mapper, return a Map: Map toMap(Set set, Mapper mapper) Conceptually this applies the mapper function to every element K of the set, giving a value V; these (K,V) pairs are stored into a map which is then returned. It's an open question whether this is done immediately, done lazily, whether results are cached, etc. 2) The other direction is, given a collection of values and a Mapper that generates keys, return a Map that maps each key to the values from which it was generated. I've seen this called groupBy elsewhere. The problem is, how to represent multiple values for a single key. Other systems use tuples or multi-valued maps. For this example I'll use List as the value of each map entry: Map> groupBy(Collection coll, Mapper mapper) (Proper wildcards elided.) For each value in the collection, run the mapper on it to get a key; then put this key-value pair into a map. If there are multiple values corresponding to the same key, the values get put into a list. For uniformity you'd always put the values into a list, even if there's only one value. For example, List list = Arrays.asList("Beulah", "Maude", "Gertrude", "Beatrice", "Gladys", "Georgia", "Mildred", "Mabel"); Map map = groupBy(list, s -> s.substring(0, 1)); would result in map containing "B" => ["Beulah", "Beatrice"] "G" => ["Gertrude", "Gladys", "Georgia"] "M" => ["Maude", "Mildred", "Mabel"] s'marks From yshavit at akiban.com Fri Sep 23 16:01:17 2011 From: yshavit at akiban.com (Yuval Shavit) Date: Fri, 23 Sep 2011 19:01:17 -0400 Subject: summary of point lambdafication survey In-Reply-To: <4E7D003A.8020500@oracle.com> References: <4E7CCBC4.7050706@oracle.com> <4E7CD013.40304@oracle.com> <76553008-C408-4C7E-ADA4-F26B3038E9FC@oracle.com> <4E7D003A.8020500@oracle.com> Message-ID: In a world where the result of inserting into a map is the map that you've just inserted into (Java isn't that world, but it can be made into that world in a couple lines), I think both scenarios you describe can be implemented with a fold. That said, in your #2 scenario, if you really have a Map and not a MultiMap, then the fold's function does have to do a bit more work. Forgive me if this is overreaching myself, but since I'm reading up on Haskell, I gave both of your directions a go: import Data.Map as M toMap1 :: (Ord k) => (e->k) -> (e->v) -> Map k v -> [e] -> Map k v toMap1 kf vf = foldr (\e-> M.insert (kf e) (vf e)) toMap2 :: (Ord k) => (e->k) -> (e->v) -> Map k [v] -> [e] -> Map k [v] toMap2 kf vf = foldr (doinsert kf vf) doinsert :: (Ord k) => (e->k) -> (e->v) -> e -> Map k [v] -> Map k [v] doinsert kf vf e m = let k = kf e v = vf e m' = case (M.lookup k m) of Nothing -> M.insert k [v] m (Just vs) -> M.insert k (v:vs) m in m' *Main> toMap1 show (*2) empty [1..5] fromList [("1",2),("2",4),("3",6),("4",8),("5",10)] *Main> toMap2 odd id empty [1..5] fromList [(False,[2,4]),(True,[1,3,5])] -Yuval On Fri, Sep 23, 2011 at 5:55 PM, Stuart Marks wrote: > On 9/23/11 1:39 PM, Yuval Shavit wrote: > >> Collections.toMap sounds like a convenience function for a fold, is that >> about >> right? >> > > I don't think so. This might be because of how heavily I had condensed the > original submission. Let me explain. > > As it stood, the original submission was interesting but not quite right in > my view. It seemed to lead in either of two different directions, both of > which are potentially very useful in their own right. Perhaps the submitter > could post here to clarify, in case I've misinterpreted something. > > 1) The first direction is, given a Set and a Mapper, return a Map: > > Map toMap(Set set, Mapper mapper) > > Conceptually this applies the mapper function to every element K of the > set, giving a value V; these (K,V) pairs are stored into a map which is then > returned. It's an open question whether this is done immediately, done > lazily, whether results are cached, etc. > > 2) The other direction is, given a collection of values and a Mapper that > generates keys, return a Map that maps each key to the values from which it > was generated. > > I've seen this called groupBy elsewhere. The problem is, how to represent > multiple values for a single key. Other systems use tuples or multi-valued > maps. For this example I'll use List as the value of each map entry: > > Map> groupBy(Collection coll, Mapper mapper) > > (Proper wildcards elided.) > > For each value in the collection, run the mapper on it to get a key; then > put this key-value pair into a map. If there are multiple values > corresponding to the same key, the values get put into a list. For > uniformity you'd always put the values into a list, even if there's only one > value. > > For example, > > List list = Arrays.asList("Beulah", "Maude", "Gertrude", > "Beatrice", "Gladys", "Georgia", "Mildred", "Mabel"); > Map map = groupBy(list, s -> s.substring(0, 1)); > > would result in map containing > > "B" => ["Beulah", "Beatrice"] > "G" => ["Gertrude", "Gladys", "Georgia"] > "M" => ["Maude", "Mildred", "Mabel"] > > s'marks > > From ezequielballesi at gmail.com Sat Sep 24 08:26:56 2011 From: ezequielballesi at gmail.com (Ezequiel Ballesi) Date: Sat, 24 Sep 2011 12:26:56 -0300 Subject: summary of point lambdafication survey In-Reply-To: References: <4E7CCBC4.7050706@oracle.com> <4E7CD013.40304@oracle.com> <76553008-C408-4C7E-ADA4-F26B3038E9FC@oracle.com> <4E7D003A.8020500@oracle.com> Message-ID: Hello, The intended direction was the second one that Stuark pointed (but the submission sure did have something not right). But both uses are really useful. As for what Yuval says, it seems that a more general function could benefit more users of the api, mainly depending on it ease of use. As a personal experience, I have had to transform Collections into Maps several times, mostly because of application domains not being properly modeled or to implement some domain logic on large Collections that would require traversing the collection several times if not "mapified" first. Thanks for taking it into account and I hope this add some value. Great work!!! 2011/9/23 Yuval Shavit > In a world where the result of inserting into a map is the map that you've > just inserted into (Java isn't that world, but it can be made into that > world in a couple lines), I think both scenarios you describe can be > implemented with a fold. That said, in your #2 scenario, if you really have > a Map and not a MultiMap, then the fold's function does have to > do > a bit more work. > > Forgive me if this is overreaching myself, but since I'm reading up on > Haskell, I gave both of your directions a go: > > import Data.Map as M > toMap1 :: (Ord k) => (e->k) -> (e->v) -> Map k v -> [e] -> Map k v > toMap1 kf vf = foldr (\e-> M.insert (kf e) (vf e)) > > toMap2 :: (Ord k) => (e->k) -> (e->v) -> Map k [v] -> [e] -> Map k [v] > toMap2 kf vf = foldr (doinsert kf vf) > > doinsert :: (Ord k) => (e->k) -> (e->v) -> e -> Map k [v] -> Map k [v] > doinsert kf vf e m = > let k = kf e > v = vf e > m' = case (M.lookup k m) of > Nothing -> M.insert k [v] m > (Just vs) -> M.insert k (v:vs) m > in m' > > *Main> toMap1 show (*2) empty [1..5] > fromList [("1",2),("2",4),("3",6),("4",8),("5",10)] > > *Main> toMap2 odd id empty [1..5] > fromList [(False,[2,4]),(True,[1,3,5])] > > -Yuval > > On Fri, Sep 23, 2011 at 5:55 PM, Stuart Marks >wrote: > > > On 9/23/11 1:39 PM, Yuval Shavit wrote: > > > >> Collections.toMap sounds like a convenience function for a fold, is that > >> about > >> right? > >> > > > > I don't think so. This might be because of how heavily I had condensed > the > > original submission. Let me explain. > > > > As it stood, the original submission was interesting but not quite right > in > > my view. It seemed to lead in either of two different directions, both of > > which are potentially very useful in their own right. Perhaps the > submitter > > could post here to clarify, in case I've misinterpreted something. > > > > 1) The first direction is, given a Set and a Mapper, return a Map: > > > > Map toMap(Set set, Mapper mapper) > > > > Conceptually this applies the mapper function to every element K of the > > set, giving a value V; these (K,V) pairs are stored into a map which is > then > > returned. It's an open question whether this is done immediately, done > > lazily, whether results are cached, etc. > > > > 2) The other direction is, given a collection of values and a Mapper that > > generates keys, return a Map that maps each key to the values from which > it > > was generated. > > > > I've seen this called groupBy elsewhere. The problem is, how to represent > > multiple values for a single key. Other systems use tuples or > multi-valued > > maps. For this example I'll use List as the value of each map entry: > > > > Map> groupBy(Collection coll, Mapper mapper) > > > > (Proper wildcards elided.) > > > > For each value in the collection, run the mapper on it to get a key; then > > put this key-value pair into a map. If there are multiple values > > corresponding to the same key, the values get put into a list. For > > uniformity you'd always put the values into a list, even if there's only > one > > value. > > > > For example, > > > > List list = Arrays.asList("Beulah", "Maude", "Gertrude", > > "Beatrice", "Gladys", "Georgia", "Mildred", "Mabel"); > > Map map = groupBy(list, s -> s.substring(0, 1)); > > > > would result in map containing > > > > "B" => ["Beulah", "Beatrice"] > > "G" => ["Gertrude", "Gladys", "Georgia"] > > "M" => ["Maude", "Mildred", "Mabel"] > > > > s'marks > > > > > > From stuart.marks at oracle.com Tue Sep 27 10:56:04 2011 From: stuart.marks at oracle.com (Stuart Marks) Date: Tue, 27 Sep 2011 10:56:04 -0700 Subject: summary of point lambdafication survey In-Reply-To: References: <4E7CCBC4.7050706@oracle.com> <4E7CD013.40304@oracle.com> <76553008-C408-4C7E-ADA4-F26B3038E9FC@oracle.com> <4E7D003A.8020500@oracle.com> Message-ID: <4E820E34.1090708@oracle.com> After mulling this over for a couple days, I realized I wasn't getting anywhere staring at the Haskell code you wrote, inasmuch as I don't know Haskell. :-) So I decided to rewrite scenario #2 ("groupBy") in Java, using fold (which is called "reduce" in the current prototype). Map> map = list.reduce(new HashMap>(), (map, str) -> { String initial = str.substring(0, 1); List val = map.get(initial); if (val == null) { val = new ArrayList(); map.put(initial, val); } val.add(str); return map; }); Ugh! So this is what you mean by "a bit more work." Most of this is because Java lacks things like tuples or a MultiMap. So let's assume the existence of some kind of MultiMap: MultiMap map = list.reduce(new MultiMap>(), (map, str) -> { map.put(str.substring(0, 1), str); return map; }); Now as you say if map.put() were to return the map itself (it doesn't in any of the multimaps that I've seen, but let's run with this) we could simply write: MultiMap map = list.reduce(new MultiMap>(), (map, str) -> map.put(str.substring(0, 1), str)); This is nice, but perhaps not quite as nice as: MultiMap map = groupBy(list, s -> s.substring(0, 1)); or even Map> map = groupBy(list, s -> s.substring(0, 1)); So, back to your point. It does seem that a fold ("reduce") operation is fairly general, and that other operations such as toMap and groupBy can be implemented in terms of fold. Does that mean it's not necessary to have these other operations in the library? Or are they common enough that they're worthwhile to have as a convenience? s'marks On 9/23/11 4:01 PM, Yuval Shavit wrote: > In a world where the result of inserting into a map is the map that you've just > inserted into (Java isn't that world, but it can be made into that world in a > couple lines), I think both scenarios you describe can be implemented with a > fold. That said, in your #2 scenario, if you really have a Map and not a > MultiMap, then the fold's function does have to do a bit more work. > > Forgive me if this is overreaching myself, but since I'm reading up on Haskell, > I gave both of your directions a go: > > import Data.Map as M > toMap1 :: (Ord k) => (e->k) -> (e->v) -> Map k v -> [e] -> Map k v > toMap1 kf vf = foldr (\e-> M.insert (kf e) (vf e)) > > toMap2 :: (Ord k) => (e->k) -> (e->v) -> Map k [v] -> [e] -> Map k [v] > toMap2 kf vf = foldr (doinsert kf vf) > > doinsert :: (Ord k) => (e->k) -> (e->v) -> e -> Map k [v] -> Map k [v] > doinsert kf vf e m = > let k = kf e > v = vf e > m' = case (M.lookup k m) of > Nothing -> M.insert k [v] m > (Just vs) -> M.insert k (v:vs) m > in m' > > *Main> toMap1 show (*2) empty [1..5] > fromList [("1",2),("2",4),("3",6),("4",8),("5",10)] > > *Main> toMap2 odd id empty [1..5] > fromList [(False,[2,4]),(True,[1,3,5])] > > -Yuval > > On Fri, Sep 23, 2011 at 5:55 PM, Stuart Marks > wrote: > > On 9/23/11 1:39 PM, Yuval Shavit wrote: > > Collections.toMap sounds like a convenience function for a fold, is > that about > right? > > > I don't think so. This might be because of how heavily I had condensed the > original submission. Let me explain. > > As it stood, the original submission was interesting but not quite right in > my view. It seemed to lead in either of two different directions, both of > which are potentially very useful in their own right. Perhaps the submitter > could post here to clarify, in case I've misinterpreted something. > > 1) The first direction is, given a Set and a Mapper, return a Map: > > Map toMap(Set set, Mapper mapper) > > Conceptually this applies the mapper function to every element K of the > set, giving a value V; these (K,V) pairs are stored into a map which is > then returned. It's an open question whether this is done immediately, done > lazily, whether results are cached, etc. > > 2) The other direction is, given a collection of values and a Mapper that > generates keys, return a Map that maps each key to the values from which it > was generated. > > I've seen this called groupBy elsewhere. The problem is, how to represent > multiple values for a single key. Other systems use tuples or multi-valued > maps. For this example I'll use List as the value of each map entry: > > Map> groupBy(Collection coll, Mapper mapper) > > (Proper wildcards elided.) > > For each value in the collection, run the mapper on it to get a key; then > put this key-value pair into a map. If there are multiple values > corresponding to the same key, the values get put into a list. For > uniformity you'd always put the values into a list, even if there's only > one value. > > For example, > > List list = Arrays.asList("Beulah", "Maude", "Gertrude", > "Beatrice", "Gladys", "Georgia", "Mildred", "Mabel"); > Map map = groupBy(list, s -> s.substring(0, 1)); > > would result in map containing > > "B" => ["Beulah", "Beatrice"] > "G" => ["Gertrude", "Gladys", "Georgia"] > "M" => ["Maude", "Mildred", "Mabel"] > > s'marks > > From brian.goetz at oracle.com Tue Sep 27 12:18:46 2011 From: brian.goetz at oracle.com (Brian Goetz) Date: Tue, 27 Sep 2011 15:18:46 -0400 Subject: Syntax decision In-Reply-To: <4E692067.1080509@oracle.com> References: <4E692067.1080509@oracle.com> Message-ID: <4E822196.10801@oracle.com> Update on syntax: the EG has chosen to stick with the -> form of the arrow that the prototype currently uses, rather than adopt the =>. You could think of this in two ways (I'm sure I'll hear both): - This is much better, as it avoids some really bad interactions with existing operators, such as: x => x.age <= 0; // duelling arrows or Predicate p = x => x.size == 0; // duelling equals - What a bunch of idiots we are, in that we claimed the goal of doing what other languages did, and then made gratuitous changes "just for the sake of doing something different". Obviously we don't think we're idiots, but everyone can have an opinion :) In the end, this was viewed as a small tweak to avoid some undesirable interactions, while preserving the overall goal of "mostly looks like what lambdas look like in other similar languages." On 9/8/2011 4:07 PM, Brian Goetz wrote: > This just in: the EG has (mostly) made a decision on syntax. > > After considering a number of alternatives, we decided to essentially > adopt the C# syntax. We may still deliberate further on the fine points > (e.g., thin arrow vs fat arrow, special nilary form, etc), and have not > yet come to a decision on method reference syntax. > > The C# syntax is: > > lambda = ArgList Arrow Body > ArgList = Identifier > | "(" Identifier [ "," Identifier ]* ")" > | "(" Type Identifier [ "," Type Identifier ]* ")" > Body = Expression > | "{" [ Statement ";" ]+ "}" > > Here are some examples of lambda expressions using this syntax: > > x => x + 1 > (x) => x + 1 > (int x) => x + 1 > (int x, int y) => x + y > (x, y) => x + y > (x, y) => { System.out.printf("%d + %d = %d%n", x, y, x+y); } > () => { System.out.println("I am a Runnable"); } > > The decision to choose this syntax was twofold: > - The syntax scores "pretty well" on most subjective measures (though > has cases where it looks bad, just like all the others do). In > particular, it does well with "small" lambdas that are used as method > arguments (a common case), and also does well with large > (multi-statement) lambdas. > > - Despite extensive searching, there was no clear winner among the > alternatives (each form had some good aspects and some really not very > good aspects, and there was no form that was clearly better than the > others). So, we felt that it was better to choose something that has > already been shown to work well in the two languages that are most like > Java -- C# and Scala -- rather than to invent something new. > > A compiler implementation should be available soon. > > > From yshavit at akiban.com Tue Sep 27 12:51:44 2011 From: yshavit at akiban.com (Yuval Shavit) Date: Tue, 27 Sep 2011 15:51:44 -0400 Subject: summary of point lambdafication survey In-Reply-To: <4E820E34.1090708@oracle.com> References: <4E7CCBC4.7050706@oracle.com> <4E7CD013.40304@oracle.com> <76553008-C408-4C7E-ADA4-F26B3038E9FC@oracle.com> <4E7D003A.8020500@oracle.com> <4E820E34.1090708@oracle.com> Message-ID: I think your're right about everything there. Imho (and the h is important here!), convenience functions are a Good Thing for a few reasons: * they're convenient * they encourage certain paradigms (ie, "use this map function rather than writing a loop yourself") * they provide a common language, which makes it easier to read other people's code * they provide people with example code for "free" By the last point, I mean that someone who wants to understand how map can be written in terms of reduce has an obvious place to look -- the source code for map. This is especially useful when you're trying to teach people a new concept such as functional programming. I realize now that my original email could have been construed as questioning whether you should include a map-written-in-terms-of-reduce convenience. If so, my apologies -- that wasn't my intent. I was just trying to get clarification on whether map would be "its own thing," or whether it would be written in terms of reduce (which I think it should be, if only for that fourth bullet point). On Tue, Sep 27, 2011 at 1:56 PM, Stuart Marks wrote: > After mulling this over for a couple days, I realized I wasn't getting > anywhere staring at the Haskell code you wrote, inasmuch as I don't know > Haskell. :-) So I decided to rewrite scenario #2 ("groupBy") in Java, using > fold (which is called "reduce" in the current prototype). > > Map> map = > list.reduce(new HashMap>()**, (map, str) -> > { > String initial = str.substring(0, 1); > List val = map.get(initial); > if (val == null) { > val = new ArrayList(); > map.put(initial, val); > } > val.add(str); > return map; > }); > > Ugh! So this is what you mean by "a bit more work." Most of this is because > Java lacks things like tuples or a MultiMap. So let's assume the existence > of some kind of MultiMap: > > MultiMap map = > list.reduce(new MultiMap>(**), (map, str) > -> { > map.put(str.substring(0, 1), str); > return map; > }); > > Now as you say if map.put() were to return the map itself (it doesn't in > any of the multimaps that I've seen, but let's run with this) we could > simply write: > > MultiMap map = > list.reduce(new MultiMap>(**), > (map, str) -> map.put(str.substring(0, 1), str)); > > This is nice, but perhaps not quite as nice as: > > MultiMap map = groupBy(list, s -> s.substring(0, 1)); > > or even > > Map> map = groupBy(list, s -> s.substring(0, 1)); > > So, back to your point. It does seem that a fold ("reduce") operation is > fairly general, and that other operations such as toMap and groupBy can be > implemented in terms of fold. Does that mean it's not necessary to have > these other operations in the library? Or are they common enough that > they're worthwhile to have as a convenience? > > s'marks > > > > > > > > On 9/23/11 4:01 PM, Yuval Shavit wrote: > >> In a world where the result of inserting into a map is the map that you've >> just >> inserted into (Java isn't that world, but it can be made into that world >> in a >> couple lines), I think both scenarios you describe can be implemented with >> a >> fold. That said, in your #2 scenario, if you really have a Map and >> not a >> MultiMap, then the fold's function does have to do a bit more work. >> >> Forgive me if this is overreaching myself, but since I'm reading up on >> Haskell, >> I gave both of your directions a go: >> >> import Data.Map as M >> toMap1 :: (Ord k) => (e->k) -> (e->v) -> Map k v -> [e] -> Map k v >> toMap1 kf vf = foldr (\e-> M.insert (kf e) (vf e)) >> >> toMap2 :: (Ord k) => (e->k) -> (e->v) -> Map k [v] -> [e] -> Map k [v] >> toMap2 kf vf = foldr (doinsert kf vf) >> >> doinsert :: (Ord k) => (e->k) -> (e->v) -> e -> Map k [v] -> Map k >> [v] >> doinsert kf vf e m = >> let k = kf e >> v = vf e >> m' = case (M.lookup k m) of >> Nothing -> M.insert k [v] m >> (Just vs) -> M.insert k (v:vs) m >> in m' >> >> *Main> toMap1 show (*2) empty [1..5] >> fromList [("1",2),("2",4),("3",6),("4",**8),("5",10)] >> >> *Main> toMap2 odd id empty [1..5] >> fromList [(False,[2,4]),(True,[1,3,5])] >> >> -Yuval >> >> On Fri, Sep 23, 2011 at 5:55 PM, Stuart Marks > >> wrote: >> >> On 9/23/11 1:39 PM, Yuval Shavit wrote: >> >> Collections.toMap sounds like a convenience function for a fold, is >> that about >> right? >> >> >> I don't think so. This might be because of how heavily I had condensed >> the >> original submission. Let me explain. >> >> As it stood, the original submission was interesting but not quite >> right in >> my view. It seemed to lead in either of two different directions, both >> of >> which are potentially very useful in their own right. Perhaps the >> submitter >> could post here to clarify, in case I've misinterpreted something. >> >> 1) The first direction is, given a Set and a Mapper, return a Map: >> >> Map toMap(Set set, Mapper mapper) >> >> Conceptually this applies the mapper function to every element K of the >> set, giving a value V; these (K,V) pairs are stored into a map which is >> then returned. It's an open question whether this is done immediately, >> done >> lazily, whether results are cached, etc. >> >> 2) The other direction is, given a collection of values and a Mapper >> that >> generates keys, return a Map that maps each key to the values from >> which it >> was generated. >> >> I've seen this called groupBy elsewhere. The problem is, how to >> represent >> multiple values for a single key. Other systems use tuples or >> multi-valued >> maps. For this example I'll use List as the value of each map entry: >> >> Map> groupBy(Collection coll, Mapper mapper) >> >> (Proper wildcards elided.) >> >> For each value in the collection, run the mapper on it to get a key; >> then >> put this key-value pair into a map. If there are multiple values >> corresponding to the same key, the values get put into a list. For >> uniformity you'd always put the values into a list, even if there's >> only >> one value. >> >> For example, >> >> List list = Arrays.asList("Beulah", "Maude", "Gertrude", >> "Beatrice", "Gladys", "Georgia", "Mildred", "Mabel"); >> Map map = groupBy(list, s -> s.substring(0, 1)); >> >> would result in map containing >> >> "B" => ["Beulah", "Beatrice"] >> "G" => ["Gertrude", "Gladys", "Georgia"] >> "M" => ["Maude", "Mildred", "Mabel"] >> >> s'marks >> >> >> From howard.lovatt at gmail.com Tue Sep 27 23:03:38 2011 From: howard.lovatt at gmail.com (Howard Lovatt) Date: Wed, 28 Sep 2011 16:03:38 +1000 Subject: Syntax decision In-Reply-To: <4E822196.10801@oracle.com> References: <4E692067.1080509@oracle.com> <4E822196.10801@oracle.com> Message-ID: Personally I am glad you have decided to go with -> since I have had trouble reading Scala code, however this is not my main point in this post which is have you decided if you require () for no arguments or if you plan to allow a 'naked' -> e.g.: shortCutAnd( -> size >= 0, -> size < max ); // Example equivalent to size >= 0 && size < max, but user written On 28 September 2011 05:18, Brian Goetz wrote: > Update on syntax: the EG has chosen to stick with the -> form of the > arrow that the prototype currently uses, rather than adopt the =>. > > You could think of this in two ways (I'm sure I'll hear both): > > - This is much better, as it avoids some really bad interactions with > existing operators, such as: > > x => x.age <= 0; // duelling arrows > or > Predicate p = x => x.size == 0; // duelling equals > > - What a bunch of idiots we are, in that we claimed the goal of doing > what other languages did, and then made gratuitous changes "just for the > sake of doing something different". > > Obviously we don't think we're idiots, but everyone can have an opinion :) > > In the end, this was viewed as a small tweak to avoid some undesirable > interactions, while preserving the overall goal of "mostly looks like > what lambdas look like in other similar languages." > > > > On 9/8/2011 4:07 PM, Brian Goetz wrote: > > This just in: the EG has (mostly) made a decision on syntax. > > > > After considering a number of alternatives, we decided to essentially > > adopt the C# syntax. We may still deliberate further on the fine points > > (e.g., thin arrow vs fat arrow, special nilary form, etc), and have not > > yet come to a decision on method reference syntax. > > > > The C# syntax is: > > > > lambda = ArgList Arrow Body > > ArgList = Identifier > > | "(" Identifier [ "," Identifier ]* ")" > > | "(" Type Identifier [ "," Type Identifier ]* ")" > > Body = Expression > > | "{" [ Statement ";" ]+ "}" > > > > Here are some examples of lambda expressions using this syntax: > > > > x => x + 1 > > (x) => x + 1 > > (int x) => x + 1 > > (int x, int y) => x + y > > (x, y) => x + y > > (x, y) => { System.out.printf("%d + %d = %d%n", x, y, x+y); } > > () => { System.out.println("I am a Runnable"); } > > > > The decision to choose this syntax was twofold: > > - The syntax scores "pretty well" on most subjective measures (though > > has cases where it looks bad, just like all the others do). In > > particular, it does well with "small" lambdas that are used as method > > arguments (a common case), and also does well with large > > (multi-statement) lambdas. > > > > - Despite extensive searching, there was no clear winner among the > > alternatives (each form had some good aspects and some really not very > > good aspects, and there was no form that was clearly better than the > > others). So, we felt that it was better to choose something that has > > already been shown to work well in the two languages that are most like > > Java -- C# and Scala -- rather than to invent something new. > > > > A compiler implementation should be available soon. > > > > > > > > -- -- Howard. From fyaoxy at gmail.com Wed Sep 28 02:03:41 2011 From: fyaoxy at gmail.com (=?UTF-8?B?5ZCR6ZuF?=) Date: Wed, 28 Sep 2011 17:03:41 +0800 Subject: Syntax decision In-Reply-To: <4E692067.1080509@oracle.com> References: <4E692067.1080509@oracle.com> Message-ID: One question, very simple? If get rid of the Arrow, You can't recognize the lambda, or the Computer cannot? In another words, the code write to programmers, or the dead device? Maybe, answer is: Why not add some context into it? From lieven.lemiengre at gmail.com Wed Sep 28 02:27:06 2011 From: lieven.lemiengre at gmail.com (Lieven Lemiengre) Date: Wed, 28 Sep 2011 11:27:06 +0200 Subject: Syntax decision In-Reply-To: <4E822196.10801@oracle.com> References: <4E692067.1080509@oracle.com> <4E822196.10801@oracle.com> Message-ID: Other languages (such as Scala or Groovy) don't have this problem because they support some placeholder syntax. In reality you don't write "x => x.age <= 0;" But this is very common "someList.partition(x => x.age <= 18)" and I agree this looks bad. Other languages make this clearer using placeholder syntax "someList.partition(_.age <= 18)" or "someList.partition(it.age <= 18)" I hope you are considering something like this, these little closures will be used a lot! (And I don't think replacing '=>' with '->' will help a lot) On Tue, Sep 27, 2011 at 9:18 PM, Brian Goetz wrote: > Update on syntax: the EG has chosen to stick with the -> form of the > arrow that the prototype currently uses, rather than adopt the =>. > > You could think of this in two ways (I'm sure I'll hear both): > > - This is much better, as it avoids some really bad interactions with > existing operators, such as: > > x => x.age <= 0; // duelling arrows > or > Predicate p = x => x.size == 0; // duelling equals > > - What a bunch of idiots we are, in that we claimed the goal of doing > what other languages did, and then made gratuitous changes "just for the > sake of doing something different". > > Obviously we don't think we're idiots, but everyone can have an opinion :) > > In the end, this was viewed as a small tweak to avoid some undesirable > interactions, while preserving the overall goal of "mostly looks like > what lambdas look like in other similar languages." > > > > On 9/8/2011 4:07 PM, Brian Goetz wrote: > > This just in: the EG has (mostly) made a decision on syntax. > > > > After considering a number of alternatives, we decided to essentially > > adopt the C# syntax. We may still deliberate further on the fine points > > (e.g., thin arrow vs fat arrow, special nilary form, etc), and have not > > yet come to a decision on method reference syntax. > > > > The C# syntax is: > > > > lambda = ArgList Arrow Body > > ArgList = Identifier > > | "(" Identifier [ "," Identifier ]* ")" > > | "(" Type Identifier [ "," Type Identifier ]* ")" > > Body = Expression > > | "{" [ Statement ";" ]+ "}" > > > > Here are some examples of lambda expressions using this syntax: > > > > x => x + 1 > > (x) => x + 1 > > (int x) => x + 1 > > (int x, int y) => x + y > > (x, y) => x + y > > (x, y) => { System.out.printf("%d + %d = %d%n", x, y, x+y); } > > () => { System.out.println("I am a Runnable"); } > > > > The decision to choose this syntax was twofold: > > - The syntax scores "pretty well" on most subjective measures (though > > has cases where it looks bad, just like all the others do). In > > particular, it does well with "small" lambdas that are used as method > > arguments (a common case), and also does well with large > > (multi-statement) lambdas. > > > > - Despite extensive searching, there was no clear winner among the > > alternatives (each form had some good aspects and some really not very > > good aspects, and there was no form that was clearly better than the > > others). So, we felt that it was better to choose something that has > > already been shown to work well in the two languages that are most like > > Java -- C# and Scala -- rather than to invent something new. > > > > A compiler implementation should be available soon. > > > > > > > > From henrigerrits at yahoo.com Wed Sep 28 07:25:18 2011 From: henrigerrits at yahoo.com (Henri Gerrits) Date: Wed, 28 Sep 2011 07:25:18 -0700 (PDT) Subject: summary of point lambdafication survey Message-ID: <1317219918.44639.YahooMailNeo@web160716.mail.bf1.yahoo.com> >>>* Collections.toMap(keyGen) >>>- for each element in a Collection, generate a key, store into a Map >>>- could be a static utility method or an extension method >> >>This is interesting. It's sort-of halfway between two different ideas. >> >>One take would be for it to take a value-generating lambda (a Mapper) which >>would be run over each element in a Set. The result would be a Map object whose >>keys are the elements from the Collection and whose values are the results from >>the Mapper. >> >>Another take is to generate keys from each element of a Collection; the >>question then what to do in the case of duplicate keys. We'd want the resulting >>Map to have multiple values for a single key. This could be expressed as a >>(hypothetical) MultiMap, or as an ordinary Map whose values are Lists. > >... which turns it into groupBy.?? ? I have a different interpretation of the "another take".?If the?semantics of toMap are defined such that?the key generated?from the?Collection element?should?be unique, then toMap() would return a simple flat Map, while duplicate keys would be a violation of the semantics and therefore?cause some RuntimeException. ? The following example may illustrate this use case: ? ? Collection customers = datastore.getCustomers(...); ? Map customersByID = customers.toMap(c -> c.id()); ? Map customersByPK = customers.toMap(c -> c.pk()); ? where id() and pk() return String and long, respectively. ? I would use?such map?conversions quite?a lot,?particularly?for caches and the like. ? Map implementations should also have conversion constructors, so that you can choose the exact Map implementation you need: ? ? ConcurrentHashMap(Collection values, Mapper mapper); ? To be used like so: ? ? Map = new ConcurrentHashMap<>(customers, c -> c.id());. ? (Maybe a reversal of constructor arguments would be more intuitive, I'm not sure.) ? Best regards, ? Henri From brian.goetz at oracle.com Wed Sep 28 07:39:01 2011 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 28 Sep 2011 10:39:01 -0400 Subject: Syntax decision In-Reply-To: References: <4E692067.1080509@oracle.com> <4E822196.10801@oracle.com> Message-ID: <4E833185.70306@oracle.com> Yes, wunderbars were considered and (overwhelmingly) rejected by the EG. On 9/28/2011 5:27 AM, Lieven Lemiengre wrote: > Other languages (such as Scala or Groovy) don't have this problem > because they support some placeholder syntax. > > In reality you don't write "x => x.age <= 0;" > But this is very common "someList.partition(x => x.age <= 18)" and I > agree this looks bad. Other languages make this clearer using > placeholder syntax "someList.partition(_.age <= 18)" or > "someList.partition(it.age <= 18)" > I hope you are considering something like this, these little closures > will be used a lot! > (And I don't think replacing '=>' with '->' will help a lot) > > > On Tue, Sep 27, 2011 at 9:18 PM, Brian Goetz > wrote: > > Update on syntax: the EG has chosen to stick with the -> form of the > arrow that the prototype currently uses, rather than adopt the =>. > > You could think of this in two ways (I'm sure I'll hear both): > > - This is much better, as it avoids some really bad interactions with > existing operators, such as: > > x => x.age <= 0; // duelling arrows > or > Predicate p = x => x.size == 0; // duelling equals > > - What a bunch of idiots we are, in that we claimed the goal of doing > what other languages did, and then made gratuitous changes "just for the > sake of doing something different". > > Obviously we don't think we're idiots, but everyone can have an > opinion :) > > In the end, this was viewed as a small tweak to avoid some undesirable > interactions, while preserving the overall goal of "mostly looks like > what lambdas look like in other similar languages." > > > > On 9/8/2011 4:07 PM, Brian Goetz wrote: > > This just in: the EG has (mostly) made a decision on syntax. > > > > After considering a number of alternatives, we decided to essentially > > adopt the C# syntax. We may still deliberate further on the fine > points > > (e.g., thin arrow vs fat arrow, special nilary form, etc), and > have not > > yet come to a decision on method reference syntax. > > > > The C# syntax is: > > > > lambda = ArgList Arrow Body > > ArgList = Identifier > > | "(" Identifier [ "," Identifier ]* ")" > > | "(" Type Identifier [ "," Type Identifier ]* ")" > > Body = Expression > > | "{" [ Statement ";" ]+ "}" > > > > Here are some examples of lambda expressions using this syntax: > > > > x => x + 1 > > (x) => x + 1 > > (int x) => x + 1 > > (int x, int y) => x + y > > (x, y) => x + y > > (x, y) => { System.out.printf("%d + %d = %d%n", x, y, x+y); } > > () => { System.out.println("I am a Runnable"); } > > > > The decision to choose this syntax was twofold: > > - The syntax scores "pretty well" on most subjective measures > (though > > has cases where it looks bad, just like all the others do). In > > particular, it does well with "small" lambdas that are used as method > > arguments (a common case), and also does well with large > > (multi-statement) lambdas. > > > > - Despite extensive searching, there was no clear winner among the > > alternatives (each form had some good aspects and some really not > very > > good aspects, and there was no form that was clearly better than the > > others). So, we felt that it was better to choose something that has > > already been shown to work well in the two languages that are > most like > > Java -- C# and Scala -- rather than to invent something new. > > > > A compiler implementation should be available soon. > > > > > > > > From brian.goetz at oracle.com Wed Sep 28 07:41:17 2011 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 28 Sep 2011 10:41:17 -0400 Subject: Syntax decision In-Reply-To: References: <4E692067.1080509@oracle.com> <4E822196.10801@oracle.com> Message-ID: <4E83320D.8000503@oracle.com> The nilary syntax is still a thorn. But the obvious solution outlined below -- allow elision of the () -- leads to a syntactic ambiguity. If -> { statement; } were a valid lambda, then is: (identifier) -> { statement; } a one-arg lambda with inferred type, or a cast of a nilary lambda? If people have brilliant other suggestions for nilary lambda syntax, we'd consider it. On 9/28/2011 2:03 AM, Howard Lovatt wrote: > Personally I am glad you have decided to go with -> since I have had > trouble reading Scala code, however this is not my main point in this > post which is have you decided if you require () for no arguments or if > you plan to allow a 'naked' -> e.g.: > > shortCutAnd( -> size >= 0, -> size < max ); // Example equivalent > to size >= 0 && size < max, but user written > > On 28 September 2011 05:18, Brian Goetz > wrote: > > Update on syntax: the EG has chosen to stick with the -> form of the > arrow that the prototype currently uses, rather than adopt the =>. > > You could think of this in two ways (I'm sure I'll hear both): > > - This is much better, as it avoids some really bad interactions with > existing operators, such as: > > x => x.age <= 0; // duelling arrows > or > Predicate p = x => x.size == 0; // duelling equals > > - What a bunch of idiots we are, in that we claimed the goal of doing > what other languages did, and then made gratuitous changes "just for the > sake of doing something different". > > Obviously we don't think we're idiots, but everyone can have an > opinion :) > > In the end, this was viewed as a small tweak to avoid some undesirable > interactions, while preserving the overall goal of "mostly looks like > what lambdas look like in other similar languages." > > > > On 9/8/2011 4:07 PM, Brian Goetz wrote: > > This just in: the EG has (mostly) made a decision on syntax. > > > > After considering a number of alternatives, we decided to essentially > > adopt the C# syntax. We may still deliberate further on the fine > points > > (e.g., thin arrow vs fat arrow, special nilary form, etc), and > have not > > yet come to a decision on method reference syntax. > > > > The C# syntax is: > > > > lambda = ArgList Arrow Body > > ArgList = Identifier > > | "(" Identifier [ "," Identifier ]* ")" > > | "(" Type Identifier [ "," Type Identifier ]* ")" > > Body = Expression > > | "{" [ Statement ";" ]+ "}" > > > > Here are some examples of lambda expressions using this syntax: > > > > x => x + 1 > > (x) => x + 1 > > (int x) => x + 1 > > (int x, int y) => x + y > > (x, y) => x + y > > (x, y) => { System.out.printf("%d + %d = %d%n", x, y, x+y); } > > () => { System.out.println("I am a Runnable"); } > > > > The decision to choose this syntax was twofold: > > - The syntax scores "pretty well" on most subjective measures > (though > > has cases where it looks bad, just like all the others do). In > > particular, it does well with "small" lambdas that are used as method > > arguments (a common case), and also does well with large > > (multi-statement) lambdas. > > > > - Despite extensive searching, there was no clear winner among the > > alternatives (each form had some good aspects and some really not > very > > good aspects, and there was no form that was clearly better than the > > others). So, we felt that it was better to choose something that has > > already been shown to work well in the two languages that are > most like > > Java -- C# and Scala -- rather than to invent something new. > > > > A compiler implementation should be available soon. > > > > > > > > > > > -- > -- Howard. > From pbenedict at apache.org Wed Sep 28 07:55:15 2011 From: pbenedict at apache.org (Paul Benedict) Date: Wed, 28 Sep 2011 09:55:15 -0500 Subject: Syntax decision In-Reply-To: <4E83320D.8000503@oracle.com> References: <4E692067.1080509@oracle.com> <4E822196.10801@oracle.com> <4E83320D.8000503@oracle.com> Message-ID: On 9/28/2011 2:03 AM, Howard Lovatt wrote: > Personally I am glad you have decided to go with -> since I have had > trouble reading Scala code, however this is not my main point in this > post which is have you decided if you require () for no arguments or if > you plan to allow a 'naked' -> e.g.: I am glad too. Being consistent with other languages is a laudable goal, but since programming languages aren't identical, the needs for Java can lead to a different conclusion. The fat arrow syntax does look odd; I admit it. So in terms of vanity, I am glad to see that punted. The equals character is just too strongly associated with assignment and equality. Paul From ali.ebrahimi1781 at gmail.com Wed Sep 28 07:58:30 2011 From: ali.ebrahimi1781 at gmail.com (Ali Ebrahimi) Date: Wed, 28 Sep 2011 18:28:30 +0330 Subject: Syntax decision In-Reply-To: <4E83320D.8000503@oracle.com> References: <4E692067.1080509@oracle.com> <4E822196.10801@oracle.com> <4E83320D.8000503@oracle.com> Message-ID: Hi, I think with great support for type inference the need for casting lambas (unless for disambiguating overloaded methods,... ) would be low. And this ambiguity can be solved by applying some precedence in favor of lambdas or versa. Best Regards. On Wed, Sep 28, 2011 at 6:11 PM, Brian Goetz wrote: > The nilary syntax is still a thorn. But the obvious solution outlined > below -- allow elision of the () -- leads to a syntactic ambiguity. If > -> { statement; } were a valid lambda, then is: > > (identifier) -> { statement; } > > a one-arg lambda with inferred type, or a cast of a nilary lambda? > > If people have brilliant other suggestions for nilary lambda syntax, > we'd consider it. > > > > On 9/28/2011 2:03 AM, Howard Lovatt wrote: > > Personally I am glad you have decided to go with -> since I have had > > trouble reading Scala code, however this is not my main point in this > > post which is have you decided if you require () for no arguments or if > > you plan to allow a 'naked' -> e.g.: > > > > shortCutAnd( -> size >= 0, -> size < max ); // Example equivalent > > to size >= 0 && size < max, but user written > > > > On 28 September 2011 05:18, Brian Goetz > > wrote: > > > > Update on syntax: the EG has chosen to stick with the -> form of the > > arrow that the prototype currently uses, rather than adopt the =>. > > > > You could think of this in two ways (I'm sure I'll hear both): > > > > - This is much better, as it avoids some really bad interactions > with > > existing operators, such as: > > > > x => x.age <= 0; // duelling arrows > > or > > Predicate p = x => x.size == 0; // duelling equals > > > > - What a bunch of idiots we are, in that we claimed the goal of > doing > > what other languages did, and then made gratuitous changes "just for > the > > sake of doing something different". > > > > Obviously we don't think we're idiots, but everyone can have an > > opinion :) > > > > In the end, this was viewed as a small tweak to avoid some > undesirable > > interactions, while preserving the overall goal of "mostly looks like > > what lambdas look like in other similar languages." > > > > > > > > On 9/8/2011 4:07 PM, Brian Goetz wrote: > > > This just in: the EG has (mostly) made a decision on syntax. > > > > > > After considering a number of alternatives, we decided to > essentially > > > adopt the C# syntax. We may still deliberate further on the fine > > points > > > (e.g., thin arrow vs fat arrow, special nilary form, etc), and > > have not > > > yet come to a decision on method reference syntax. > > > > > > The C# syntax is: > > > > > > lambda = ArgList Arrow Body > > > ArgList = Identifier > > > | "(" Identifier [ "," Identifier ]* ")" > > > | "(" Type Identifier [ "," Type Identifier ]* ")" > > > Body = Expression > > > | "{" [ Statement ";" ]+ "}" > > > > > > Here are some examples of lambda expressions using this syntax: > > > > > > x => x + 1 > > > (x) => x + 1 > > > (int x) => x + 1 > > > (int x, int y) => x + y > > > (x, y) => x + y > > > (x, y) => { System.out.printf("%d + %d = %d%n", x, y, x+y); } > > > () => { System.out.println("I am a Runnable"); } > > > > > > The decision to choose this syntax was twofold: > > > - The syntax scores "pretty well" on most subjective measures > > (though > > > has cases where it looks bad, just like all the others do). In > > > particular, it does well with "small" lambdas that are used as > method > > > arguments (a common case), and also does well with large > > > (multi-statement) lambdas. > > > > > > - Despite extensive searching, there was no clear winner among > the > > > alternatives (each form had some good aspects and some really not > > very > > > good aspects, and there was no form that was clearly better than > the > > > others). So, we felt that it was better to choose something that > has > > > already been shown to work well in the two languages that are > > most like > > > Java -- C# and Scala -- rather than to invent something new. > > > > > > A compiler implementation should be available soon. > > > > > > > > > > > > > > > > > > > -- > > -- Howard. > > > > From ss at comp.lancs.ac.uk Wed Sep 28 08:04:07 2011 From: ss at comp.lancs.ac.uk (Steven Simpson) Date: Wed, 28 Sep 2011 16:04:07 +0100 Subject: Syntax decision In-Reply-To: <4E83320D.8000503@oracle.com> References: <4E692067.1080509@oracle.com> <4E822196.10801@oracle.com> <4E83320D.8000503@oracle.com> Message-ID: <4E833767.9000208@comp.lancs.ac.uk> On 28/09/11 15:41, Brian Goetz wrote: > The nilary syntax is still a thorn. But the obvious solution outlined > below -- allow elision of the () -- leads to a syntactic ambiguity. If > -> { statement; } were a valid lambda, then is: > > (identifier) -> { statement; } > > a one-arg lambda with inferred type, or a cast of a nilary lambda? What happens if you treat it as an inferred-type unary? If the author intended a casted nilary, will he always get compilation failure?[1] If so, can he fix his error by adding the empty param list?: (identifier) () -> { statement; } IOW, nilary brackets aren't always optional. [1] Hmm, does he get a syntax error or something more obscure? From maurizio.cimadamore at oracle.com Wed Sep 28 08:14:57 2011 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Wed, 28 Sep 2011 16:14:57 +0100 Subject: Syntax decision In-Reply-To: References: <4E692067.1080509@oracle.com> <4E822196.10801@oracle.com> <4E83320D.8000503@oracle.com> Message-ID: <4E8339F1.1080507@oracle.com> On 28/09/11 15:58, Ali Ebrahimi wrote: > Hi, > I think with great support for type inference the need for casting lambas > (unless for disambiguating overloaded methods,... ) would be low. > And this ambiguity can be solved by applying some precedence in favor of > lambdas or versa. But, if you have something like: m((T)-> { ... }); and you want it to be a nilary lambda converted to some target type T, how do you do that? If you exploit precedence as per your suggestion, this will always be a one-ary lambda. Of course, one way out would be to disambiguate using '()', as in: m((T)()-> { ... }); Is the cure worse than the disease? I guess it depends on the frequency of nilary lambdas and how often do you need an explicit target type (as you pointed out, this is closely related to how well inference performs). Maurizio > Best Regards. > > On Wed, Sep 28, 2011 at 6:11 PM, Brian Goetz wrote: > >> The nilary syntax is still a thorn. But the obvious solution outlined >> below -- allow elision of the () -- leads to a syntactic ambiguity. If >> -> { statement; } were a valid lambda, then is: >> >> (identifier) -> { statement; } >> >> a one-arg lambda with inferred type, or a cast of a nilary lambda? >> >> If people have brilliant other suggestions for nilary lambda syntax, >> we'd consider it. >> >> >> >> On 9/28/2011 2:03 AM, Howard Lovatt wrote: >>> Personally I am glad you have decided to go with -> since I have had >>> trouble reading Scala code, however this is not my main point in this >>> post which is have you decided if you require () for no arguments or if >>> you plan to allow a 'naked' -> e.g.: >>> >>> shortCutAnd( -> size>= 0, -> size< max ); // Example equivalent >>> to size>= 0&& size< max, but user written >>> >>> On 28 September 2011 05:18, Brian Goetz>> > wrote: >>> >>> Update on syntax: the EG has chosen to stick with the -> form of the >>> arrow that the prototype currently uses, rather than adopt the =>. >>> >>> You could think of this in two ways (I'm sure I'll hear both): >>> >>> - This is much better, as it avoids some really bad interactions >> with >>> existing operators, such as: >>> >>> x => x.age<= 0; // duelling arrows >>> or >>> Predicate p = x => x.size == 0; // duelling equals >>> >>> - What a bunch of idiots we are, in that we claimed the goal of >> doing >>> what other languages did, and then made gratuitous changes "just for >> the >>> sake of doing something different". >>> >>> Obviously we don't think we're idiots, but everyone can have an >>> opinion :) >>> >>> In the end, this was viewed as a small tweak to avoid some >> undesirable >>> interactions, while preserving the overall goal of "mostly looks like >>> what lambdas look like in other similar languages." >>> >>> >>> >>> On 9/8/2011 4:07 PM, Brian Goetz wrote: >>> > This just in: the EG has (mostly) made a decision on syntax. >>> > >>> > After considering a number of alternatives, we decided to >> essentially >>> > adopt the C# syntax. We may still deliberate further on the fine >>> points >>> > (e.g., thin arrow vs fat arrow, special nilary form, etc), and >>> have not >>> > yet come to a decision on method reference syntax. >>> > >>> > The C# syntax is: >>> > >>> > lambda = ArgList Arrow Body >>> > ArgList = Identifier >>> > | "(" Identifier [ "," Identifier ]* ")" >>> > | "(" Type Identifier [ "," Type Identifier ]* ")" >>> > Body = Expression >>> > | "{" [ Statement ";" ]+ "}" >>> > >>> > Here are some examples of lambda expressions using this syntax: >>> > >>> > x => x + 1 >>> > (x) => x + 1 >>> > (int x) => x + 1 >>> > (int x, int y) => x + y >>> > (x, y) => x + y >>> > (x, y) => { System.out.printf("%d + %d = %d%n", x, y, x+y); } >>> > () => { System.out.println("I am a Runnable"); } >>> > >>> > The decision to choose this syntax was twofold: >>> > - The syntax scores "pretty well" on most subjective measures >>> (though >>> > has cases where it looks bad, just like all the others do). In >>> > particular, it does well with "small" lambdas that are used as >> method >>> > arguments (a common case), and also does well with large >>> > (multi-statement) lambdas. >>> > >>> > - Despite extensive searching, there was no clear winner among >> the >>> > alternatives (each form had some good aspects and some really not >>> very >>> > good aspects, and there was no form that was clearly better than >> the >>> > others). So, we felt that it was better to choose something that >> has >>> > already been shown to work well in the two languages that are >>> most like >>> > Java -- C# and Scala -- rather than to invent something new. >>> > >>> > A compiler implementation should be available soon. >>> > >>> > >>> > >>> >>> >>> >>> >>> -- >>> -- Howard. >>> >> From ali.ebrahimi1781 at gmail.com Wed Sep 28 08:19:09 2011 From: ali.ebrahimi1781 at gmail.com (Ali Ebrahimi) Date: Wed, 28 Sep 2011 18:49:09 +0330 Subject: Syntax decision In-Reply-To: <4E8339F1.1080507@oracle.com> References: <4E692067.1080509@oracle.com> <4E822196.10801@oracle.com> <4E83320D.8000503@oracle.com> <4E8339F1.1080507@oracle.com> Message-ID: Hi, And another way: m((T)(-> { ... })); Best Regards, Ali Ebrahimi On Wed, Sep 28, 2011 at 6:44 PM, Maurizio Cimadamore < maurizio.cimadamore at oracle.com> wrote: > On 28/09/11 15:58, Ali Ebrahimi wrote: > >> Hi, >> I think with great support for type inference the need for casting lambas >> (unless for disambiguating overloaded methods,... ) would be low. >> And this ambiguity can be solved by applying some precedence in favor of >> lambdas or versa. >> > But, if you have something like: > > m((T)-> { ... }); > > and you want it to be a nilary lambda converted to some target type T, how > do you do that? If you exploit precedence as per your suggestion, this will > always be a one-ary lambda. > > Of course, one way out would be to disambiguate using '()', as in: > > m((T)()-> { ... }); > > Is the cure worse than the disease? I guess it depends on the frequency of > nilary lambdas and how often do you need an explicit target type (as you > pointed out, this is closely related to how well inference performs). > > Maurizio > > Best Regards. >> >> On Wed, Sep 28, 2011 at 6:11 PM, Brian Goetz >> wrote: >> >> The nilary syntax is still a thorn. But the obvious solution outlined >>> below -- allow elision of the () -- leads to a syntactic ambiguity. If >>> -> { statement; } were a valid lambda, then is: >>> >>> (identifier) -> { statement; } >>> >>> a one-arg lambda with inferred type, or a cast of a nilary lambda? >>> >>> If people have brilliant other suggestions for nilary lambda syntax, >>> we'd consider it. >>> >>> >>> >>> On 9/28/2011 2:03 AM, Howard Lovatt wrote: >>> >>>> Personally I am glad you have decided to go with -> since I have had >>>> trouble reading Scala code, however this is not my main point in this >>>> post which is have you decided if you require () for no arguments or if >>>> you plan to allow a 'naked' -> e.g.: >>>> >>>> shortCutAnd( -> size>= 0, -> size< max ); // Example equivalent >>>> to size>= 0&& size< max, but user written >>>> >>>> On 28 September 2011 05:18, Brian Goetz>>> > wrote: >>>> >>>> Update on syntax: the EG has chosen to stick with the -> form of >>>> the >>>> arrow that the prototype currently uses, rather than adopt the =>. >>>> >>>> You could think of this in two ways (I'm sure I'll hear both): >>>> >>>> - This is much better, as it avoids some really bad interactions >>>> >>> with >>> >>>> existing operators, such as: >>>> >>>> x => x.age<= 0; // duelling arrows >>>> or >>>> Predicate p = x => x.size == 0; // duelling equals >>>> >>>> - What a bunch of idiots we are, in that we claimed the goal of >>>> >>> doing >>> >>>> what other languages did, and then made gratuitous changes "just for >>>> >>> the >>> >>>> sake of doing something different". >>>> >>>> Obviously we don't think we're idiots, but everyone can have an >>>> opinion :) >>>> >>>> In the end, this was viewed as a small tweak to avoid some >>>> >>> undesirable >>> >>>> interactions, while preserving the overall goal of "mostly looks >>>> like >>>> what lambdas look like in other similar languages." >>>> >>>> >>>> >>>> On 9/8/2011 4:07 PM, Brian Goetz wrote: >>>> > This just in: the EG has (mostly) made a decision on syntax. >>>> > >>>> > After considering a number of alternatives, we decided to >>>> >>> essentially >>> >>>> > adopt the C# syntax. We may still deliberate further on the >>>> fine >>>> points >>>> > (e.g., thin arrow vs fat arrow, special nilary form, etc), and >>>> have not >>>> > yet come to a decision on method reference syntax. >>>> > >>>> > The C# syntax is: >>>> > >>>> > lambda = ArgList Arrow Body >>>> > ArgList = Identifier >>>> > | "(" Identifier [ "," Identifier ]* ")" >>>> > | "(" Type Identifier [ "," Type Identifier ]* ")" >>>> > Body = Expression >>>> > | "{" [ Statement ";" ]+ "}" >>>> > >>>> > Here are some examples of lambda expressions using this syntax: >>>> > >>>> > x => x + 1 >>>> > (x) => x + 1 >>>> > (int x) => x + 1 >>>> > (int x, int y) => x + y >>>> > (x, y) => x + y >>>> > (x, y) => { System.out.printf("%d + %d = %d%n", x, y, >>>> x+y); } >>>> > () => { System.out.println("I am a Runnable"); } >>>> > >>>> > The decision to choose this syntax was twofold: >>>> > - The syntax scores "pretty well" on most subjective measures >>>> (though >>>> > has cases where it looks bad, just like all the others do). In >>>> > particular, it does well with "small" lambdas that are used as >>>> >>> method >>> >>>> > arguments (a common case), and also does well with large >>>> > (multi-statement) lambdas. >>>> > >>>> > - Despite extensive searching, there was no clear winner >>>> among >>>> >>> the >>> >>>> > alternatives (each form had some good aspects and some really >>>> not >>>> very >>>> > good aspects, and there was no form that was clearly better than >>>> >>> the >>> >>>> > others). So, we felt that it was better to choose something >>>> that >>>> >>> has >>> >>>> > already been shown to work well in the two languages that are >>>> most like >>>> > Java -- C# and Scala -- rather than to invent something new. >>>> > >>>> > A compiler implementation should be available soon. >>>> > >>>> > >>>> > >>>> >>>> >>>> >>>> >>>> -- >>>> -- Howard. >>>> >>>> >>> > From henrigerrits at yahoo.com Wed Sep 28 08:24:11 2011 From: henrigerrits at yahoo.com (Henri Gerrits) Date: Wed, 28 Sep 2011 08:24:11 -0700 (PDT) Subject: Syntax decision In-Reply-To: <4E83320D.8000503@oracle.com> References: <4E692067.1080509@oracle.com> <4E822196.10801@oracle.com> <4E83320D.8000503@oracle.com> Message-ID: <1317223451.31622.YahooMailNeo@web160717.mail.bf1.yahoo.com> Since the cast syntax can't be touched, one way out could be to change the arg?delimiters for the lambda, e.g.; |x, y| -> x + y; Personally, I find this?a bit more readable when the lambda is provided?as an argument to a method or constructor: c.sort(|x, y| -> x?> y); instead of: c.sort((x, y) -> x?> y); But I'm sure you will already have considered (and rejected) '|'. ? Henri ----- Original Message ----- > From: Brian Goetz > To: Howard Lovatt > Cc: "lambda-dev at openjdk.java.net" > Sent: Wednesday, September 28, 2011 10:41 AM > Subject: Re: Syntax decision > >T he nilary syntax is still a thorn.? But the obvious solution outlined > below -- allow elision of the () -- leads to a syntactic ambiguity.? If > -> { statement; } were a valid lambda, then is: > > ? (identifier) -> { statement; } > > a one-arg lambda with inferred type, or a cast of a nilary lambda? > > If people have brilliant other suggestions for nilary lambda syntax, > we'd consider it. > > > > On 9/28/2011 2:03 AM, Howard Lovatt wrote: >> Personally I am glad you have decided to go with -> since I have had >> trouble reading Scala code, however this is not my main point in this >> post which is have you decided if you require () for no arguments or if >> you plan to allow a 'naked' -> e.g.: >> >> shortCutAnd( -> size >= 0, -> size < max ); // Example > equivalent >> to size >= 0 && size < max, but user written >> >> On 28 September 2011 05:18, Brian Goetz > > wrote: >> >> ? ? Update on syntax: the EG has chosen to stick with the -> form of the >> ? ? arrow that the prototype currently uses, rather than adopt the =>. >> >> ? ? You could think of this in two ways (I'm sure I'll hear both): >> >> ? ? ? - This is much better, as it avoids some really bad interactions with >> ? ? existing operators, such as: >> >> ? ? ? ? x => x.age <= 0;? ? ? ? ? ? ? ? // duelling arrows >> ? ? or >> ? ? ? ? Predicate p = x => x.size == 0;? // duelling equals >> >> ? ? ? - What a bunch of idiots we are, in that we claimed the goal of doing >> ? ? what other languages did, and then made gratuitous changes "just > for the >> ? ? sake of doing something different". >> >> ? ? Obviously we don't think we're idiots, but everyone can have an >> ? ? opinion :) >> >> ? ? In the end, this was viewed as a small tweak to avoid some undesirable >> ? ? interactions, while preserving the overall goal of "mostly looks > like >> ? ? what lambdas look like in other similar languages." >> >> >> >> ? ? On 9/8/2011 4:07 PM, Brian Goetz wrote: >> ? ? ? > This just in: the EG has (mostly) made a decision on syntax. >> ? ? ? > >> ? ? ? > After considering a number of alternatives, we decided to > essentially >> ? ? ? > adopt the C# syntax.? We may still deliberate further on the fine >> ? ? points >> ? ? ? > (e.g., thin arrow vs fat arrow, special nilary form, etc), and >> ? ? have not >> ? ? ? > yet come to a decision on method reference syntax. >> ? ? ? > >> ? ? ? > The C# syntax is: >> ? ? ? > >> ? ? ? >? ? lambda = ArgList Arrow Body >> ? ? ? >? ? ArgList = Identifier >> ? ? ? >? ? ? ? ? ? ? | "(" Identifier [ "," > Identifier ]* ")" >> ? ? ? >? ? ? ? ? ? ? | "(" Type Identifier [ "," Type > Identifier ]* ")" >> ? ? ? >? ? Body = Expression >> ? ? ? >? ? ? ? ? ? ? | "{" [ Statement ";" ]+ > "}" >> ? ? ? > >> ? ? ? > Here are some examples of lambda expressions using this syntax: >> ? ? ? > >> ? ? ? >? ? x =>? x + 1 >> ? ? ? >? ? (x) =>? x + 1 >> ? ? ? >? ? (int x) =>? x + 1 >> ? ? ? >? ? (int x, int y) =>? x + y >> ? ? ? >? ? (x, y) =>? x + y >> ? ? ? >? ? (x, y) =>? { System.out.printf("%d + %d = %d%n", > x, y, x+y); } >> ? ? ? >? ? () =>? { System.out.println("I am a Runnable"); } >> ? ? ? > >> ? ? ? > The decision to choose this syntax was twofold: >> ? ? ? >? ? - The syntax scores "pretty well" on most subjective > measures >> ? ? (though >> ? ? ? > has cases where it looks bad, just like all the others do).? In >> ? ? ? > particular, it does well with "small" lambdas that are > used as method >> ? ? ? > arguments (a common case), and also does well with large >> ? ? ? > (multi-statement) lambdas. >> ? ? ? > >> ? ? ? >? ? - Despite extensive searching, there was no clear winner among > the >> ? ? ? > alternatives (each form had some good aspects and some really not >> ? ? very >> ? ? ? > good aspects, and there was no form that was clearly better than > the >> ? ? ? > others).? So, we felt that it was better to choose something that > has >> ? ? ? > already been shown to work well in the two languages that are >> ? ? most like >> ? ? ? > Java -- C# and Scala -- rather than to invent something new. >> ? ? ? > >> ? ? ? > A compiler implementation should be available soon. >> ? ? ? > >> ? ? ? > >> ? ? ? > >> >> >> >> >> -- >> ? ? -- Howard. >> > From scolebourne at joda.org Wed Sep 28 08:28:02 2011 From: scolebourne at joda.org (Stephen Colebourne) Date: Wed, 28 Sep 2011 16:28:02 +0100 Subject: Syntax decision In-Reply-To: <4E83320D.8000503@oracle.com> References: <4E692067.1080509@oracle.com> <4E822196.10801@oracle.com> <4E83320D.8000503@oracle.com> Message-ID: On 28 September 2011 15:41, Brian Goetz wrote: > The nilary syntax is still a thorn. ?But the obvious solution outlined > below -- allow elision of the () -- leads to a syntactic ambiguity. ?If > -> { statement; } were a valid lambda, then is: > > ? (identifier) -> { statement; } > > a one-arg lambda with inferred type, or a cast of a nilary lambda? > > If people have brilliant other suggestions for nilary lambda syntax, > we'd consider it. You'll have to allow these anyway for consistency: () -> expr () -> {stmt;} You could use an "extended arrow" for nilary: --> expr --> {stmt;} where the extra dash effectively means "nothing" shortCutAnd(() -> size >= 0, () -> size < max); shortCutAnd(--> size >= 0, --> size < max); Stephen From scolebourne at joda.org Wed Sep 28 08:32:12 2011 From: scolebourne at joda.org (Stephen Colebourne) Date: Wed, 28 Sep 2011 16:32:12 +0100 Subject: Syntax decision In-Reply-To: <1317223451.31622.YahooMailNeo@web160717.mail.bf1.yahoo.com> References: <4E692067.1080509@oracle.com> <4E822196.10801@oracle.com> <4E83320D.8000503@oracle.com> <1317223451.31622.YahooMailNeo@web160717.mail.bf1.yahoo.com> Message-ID: On 28 September 2011 16:24, Henri Gerrits wrote: > Since the cast syntax can't be touched, one way out could be to change the arg?delimiters for the lambda, e.g.; > > |x, y| -> x + y; > > Personally, I find this?a bit more readable when the lambda is provided?as an argument to a method or constructor: > > c.sort(|x, y| -> x?> y); > > instead of: > > c.sort((x, y) -> x?> y); > > But I'm sure you will already have considered (and rejected) '|'. Since the decision is to go away from familiar things in Java (as opposed to #() {stmt}), I might also favour: |x, y| -> x + y It is a lot clearer in many ways in complicated situations, and would be beter for the eye in finding the target of "return" statements. I don't know without looking closer whether this is sufficiently distinguishable from OR however: || -> expr Stephen From brian.goetz at oracle.com Wed Sep 28 08:38:12 2011 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 28 Sep 2011 11:38:12 -0400 Subject: Syntax decision In-Reply-To: References: <4E692067.1080509@oracle.com> <4E822196.10801@oracle.com> <4E83320D.8000503@oracle.com> Message-ID: <4E833F64.9030900@oracle.com> The need for disambiguation in overload resolution is very important. Don't write that off as being of "low" priority. On 9/28/2011 10:58 AM, Ali Ebrahimi wrote: > Hi, > I think with great support for type inference the need for casting > lambas (unless for disambiguating overloaded methods,... ) would be low. > And this ambiguity can be solved by applying some precedence in favor of > lambdas or versa. > > Best Regards. > > On Wed, Sep 28, 2011 at 6:11 PM, Brian Goetz > wrote: > > The nilary syntax is still a thorn. But the obvious solution outlined > below -- allow elision of the () -- leads to a syntactic ambiguity. If > -> { statement; } were a valid lambda, then is: > > (identifier) -> { statement; } > > a one-arg lambda with inferred type, or a cast of a nilary lambda? > > If people have brilliant other suggestions for nilary lambda syntax, > we'd consider it. > > > > On 9/28/2011 2:03 AM, Howard Lovatt wrote: > > Personally I am glad you have decided to go with -> since I have had > > trouble reading Scala code, however this is not my main point in this > > post which is have you decided if you require () for no arguments > or if > > you plan to allow a 'naked' -> e.g.: > > > > shortCutAnd( -> size >= 0, -> size < max ); // Example equivalent > > to size >= 0 && size < max, but user written > > > > On 28 September 2011 05:18, Brian Goetz > > >> > wrote: > > > > Update on syntax: the EG has chosen to stick with the -> form > of the > > arrow that the prototype currently uses, rather than adopt > the =>. > > > > You could think of this in two ways (I'm sure I'll hear both): > > > > - This is much better, as it avoids some really bad > interactions with > > existing operators, such as: > > > > x => x.age <= 0; // duelling arrows > > or > > Predicate p = x => x.size == 0; // duelling equals > > > > - What a bunch of idiots we are, in that we claimed the > goal of doing > > what other languages did, and then made gratuitous changes > "just for the > > sake of doing something different". > > > > Obviously we don't think we're idiots, but everyone can have an > > opinion :) > > > > In the end, this was viewed as a small tweak to avoid some > undesirable > > interactions, while preserving the overall goal of "mostly > looks like > > what lambdas look like in other similar languages." > > > > > > > > On 9/8/2011 4:07 PM, Brian Goetz wrote: > > > This just in: the EG has (mostly) made a decision on syntax. > > > > > > After considering a number of alternatives, we decided to > essentially > > > adopt the C# syntax. We may still deliberate further on the fine > > points > > > (e.g., thin arrow vs fat arrow, special nilary form, etc), and > > have not > > > yet come to a decision on method reference syntax. > > > > > > The C# syntax is: > > > > > > lambda = ArgList Arrow Body > > > ArgList = Identifier > > > | "(" Identifier [ "," Identifier ]* ")" > > > | "(" Type Identifier [ "," Type Identifier ]* ")" > > > Body = Expression > > > | "{" [ Statement ";" ]+ "}" > > > > > > Here are some examples of lambda expressions using this syntax: > > > > > > x => x + 1 > > > (x) => x + 1 > > > (int x) => x + 1 > > > (int x, int y) => x + y > > > (x, y) => x + y > > > (x, y) => { System.out.printf("%d + %d = %d%n", x, y, x+y); } > > > () => { System.out.println("I am a Runnable"); } > > > > > > The decision to choose this syntax was twofold: > > > - The syntax scores "pretty well" on most subjective measures > > (though > > > has cases where it looks bad, just like all the others do). In > > > particular, it does well with "small" lambdas that are used as > method > > > arguments (a common case), and also does well with large > > > (multi-statement) lambdas. > > > > > > - Despite extensive searching, there was no clear winner > among the > > > alternatives (each form had some good aspects and some really not > > very > > > good aspects, and there was no form that was clearly better > than the > > > others). So, we felt that it was better to choose something > that has > > > already been shown to work well in the two languages that are > > most like > > > Java -- C# and Scala -- rather than to invent something new. > > > > > > A compiler implementation should be available soon. > > > > > > > > > > > > > > > > > > > -- > > -- Howard. > > > > From ali.ebrahimi1781 at gmail.com Wed Sep 28 08:44:56 2011 From: ali.ebrahimi1781 at gmail.com (Ali Ebrahimi) Date: Wed, 28 Sep 2011 19:14:56 +0330 Subject: Syntax decision In-Reply-To: <4E833F64.9030900@oracle.com> References: <4E692067.1080509@oracle.com> <4E822196.10801@oracle.com> <4E83320D.8000503@oracle.com> <4E833F64.9030900@oracle.com> Message-ID: Hi, my intend for low is low rate not low priority. On Wed, Sep 28, 2011 at 7:08 PM, Brian Goetz wrote: > The need for disambiguation in overload resolution is very important. Don't > write that off as being of "low" priority. > > > On 9/28/2011 10:58 AM, Ali Ebrahimi wrote: > >> Hi, >> I think with great support for type inference the need for casting >> lambas (unless for disambiguating overloaded methods,... ) would be low. >> And this ambiguity can be solved by applying some precedence in favor of >> lambdas or versa. >> >> Best Regards. >> >> On Wed, Sep 28, 2011 at 6:11 PM, Brian Goetz > > wrote: >> >> The nilary syntax is still a thorn. But the obvious solution outlined >> below -- allow elision of the () -- leads to a syntactic ambiguity. If >> -> { statement; } were a valid lambda, then is: >> >> (identifier) -> { statement; } >> >> a one-arg lambda with inferred type, or a cast of a nilary lambda? >> >> If people have brilliant other suggestions for nilary lambda syntax, >> we'd consider it. >> >> >> >> On 9/28/2011 2:03 AM, Howard Lovatt wrote: >> > Personally I am glad you have decided to go with -> since I have had >> > trouble reading Scala code, however this is not my main point in >> this >> > post which is have you decided if you require () for no arguments >> or if >> > you plan to allow a 'naked' -> e.g.: >> > >> > shortCutAnd( -> size >= 0, -> size < max ); // Example equivalent >> > to size >= 0 && size < max, but user written >> > >> > On 28 September 2011 05:18, Brian Goetz > >> > >> >> >> wrote: >> > >> > Update on syntax: the EG has chosen to stick with the -> form >> of the >> > arrow that the prototype currently uses, rather than adopt >> the =>. >> > >> > You could think of this in two ways (I'm sure I'll hear both): >> > >> > - This is much better, as it avoids some really bad >> interactions with >> > existing operators, such as: >> > >> > x => x.age <= 0; // duelling arrows >> > or >> > Predicate p = x => x.size == 0; // duelling equals >> > >> > - What a bunch of idiots we are, in that we claimed the >> goal of doing >> > what other languages did, and then made gratuitous changes >> "just for the >> > sake of doing something different". >> > >> > Obviously we don't think we're idiots, but everyone can have an >> > opinion :) >> > >> > In the end, this was viewed as a small tweak to avoid some >> undesirable >> > interactions, while preserving the overall goal of "mostly >> looks like >> > what lambdas look like in other similar languages." >> > >> > >> > >> > On 9/8/2011 4:07 PM, Brian Goetz wrote: >> > > This just in: the EG has (mostly) made a decision on syntax. >> > > >> > > After considering a number of alternatives, we decided to >> essentially >> > > adopt the C# syntax. We may still deliberate further on the fine >> > points >> > > (e.g., thin arrow vs fat arrow, special nilary form, etc), and >> > have not >> > > yet come to a decision on method reference syntax. >> > > >> > > The C# syntax is: >> > > >> > > lambda = ArgList Arrow Body >> > > ArgList = Identifier >> > > | "(" Identifier [ "," Identifier ]* ")" >> > > | "(" Type Identifier [ "," Type Identifier ]* ")" >> > > Body = Expression >> > > | "{" [ Statement ";" ]+ "}" >> > > >> > > Here are some examples of lambda expressions using this syntax: >> > > >> > > x => x + 1 >> > > (x) => x + 1 >> > > (int x) => x + 1 >> > > (int x, int y) => x + y >> > > (x, y) => x + y >> > > (x, y) => { System.out.printf("%d + %d = %d%n", x, y, x+y); } >> > > () => { System.out.println("I am a Runnable"); } >> > > >> > > The decision to choose this syntax was twofold: >> > > - The syntax scores "pretty well" on most subjective measures >> > (though >> > > has cases where it looks bad, just like all the others do). In >> > > particular, it does well with "small" lambdas that are used as >> method >> > > arguments (a common case), and also does well with large >> > > (multi-statement) lambdas. >> > > >> > > - Despite extensive searching, there was no clear winner >> among the >> > > alternatives (each form had some good aspects and some really not >> > very >> > > good aspects, and there was no form that was clearly better >> than the >> > > others). So, we felt that it was better to choose something >> that has >> > > already been shown to work well in the two languages that are >> > most like >> > > Java -- C# and Scala -- rather than to invent something new. >> > > >> > > A compiler implementation should be available soon. >> > > >> > > >> > > >> > >> > >> > >> > >> > -- >> > -- Howard. >> > >> >> >> From brian.goetz at oracle.com Wed Sep 28 08:46:18 2011 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 28 Sep 2011 11:46:18 -0400 Subject: Syntax decision In-Reply-To: <4E833767.9000208@comp.lancs.ac.uk> References: <4E692067.1080509@oracle.com> <4E822196.10801@oracle.com> <4E83320D.8000503@oracle.com> <4E833767.9000208@comp.lancs.ac.uk> Message-ID: <4E83414A.3090205@oracle.com> Yes, there are lots of possible hacks like this, including: - forcing unary inferred-type lambdas to not use parens: x -> e instead of allowing (x) -> e - Not allow casting of nilary lambdas without specifying () (T)() -> e instead of allowing (T) -> e But all of these introduce irregularities into the syntax, for the sake of supporting an extra case because people find () -> e to be ugly. This increases the complexity of the syntax and means there are more special cases to learn. With the current approach, there is only one special case: - All lambdas consist of paren-args-paren-arrow-body - For the special case of unary, type-inferred lambdas, you can omit the parens: x -> x+1 Turning that into "you *must* omit the parens" means that all users, even those who don't care about the nilary form, must learn another rule. Better suggestions? On 9/28/2011 11:04 AM, Steven Simpson wrote: > On 28/09/11 15:41, Brian Goetz wrote: >> The nilary syntax is still a thorn. But the obvious solution outlined >> below -- allow elision of the () -- leads to a syntactic ambiguity. If >> -> { statement; } were a valid lambda, then is: >> >> (identifier) -> { statement; } >> >> a one-arg lambda with inferred type, or a cast of a nilary lambda? > > What happens if you treat it as an inferred-type unary? If the author > intended a casted nilary, will he always get compilation failure?[1] If > so, can he fix his error by adding the empty param list?: > > (identifier) () -> { statement; } > > IOW, nilary brackets aren't always optional. > > [1] Hmm, does he get a syntax error or something more obscure? > > From henrigerrits at yahoo.com Wed Sep 28 08:57:50 2011 From: henrigerrits at yahoo.com (Henri Gerrits) Date: Wed, 28 Sep 2011 08:57:50 -0700 (PDT) Subject: Syntax decision In-Reply-To: References: <4E692067.1080509@oracle.com> <4E822196.10801@oracle.com> <4E83320D.8000503@oracle.com> <1317223451.31622.YahooMailNeo@web160717.mail.bf1.yahoo.com> Message-ID: <1317225470.87733.YahooMailNeo@web160706.mail.bf1.yahoo.com> Of course there is also the bitwise OR operator to consider. I think the parser's lookahead should be able to handle these potential syntactical complications. But do you really NEED a no-arg placeholder? BTW: the C# syntax posted by Brian originally does seem to allow the '()' syntax either: >? ? ? > The C# syntax is: >? ? ? > >? ? ? >? ? lambda = ArgList Arrow Body >? ? ? >? ? ArgList = Identifier >? ? ? >? ? ? ? ? ? ? | "(" Identifier [ "," Identifier ]* ")" >? ? ? >? ? ? ? ? ? ? | "(" Type Identifier [ "," Type Identifier ]* ")" >? ? ? >? ? Body = Expression >? ? ? >? ? ? ? ? ? ? | "{" [ Statement ";" ]+ "}" I must add I'm new to this discussion. Henri ----- Original Message ----- > From: Stephen Colebourne > To: lambda-dev > Cc: > Sent: Wednesday, September 28, 2011 11:32 AM > Subject: Re: Syntax decision > > On 28 September 2011 16:24, Henri Gerrits wrote: >> Since the cast syntax can't be touched, one way out could be to change > the arg?delimiters for the lambda, e.g.; >> >> |x, y| -> x + y; >> >> Personally, I find this?a bit more readable when the lambda is provided?as > an argument to a method or constructor: >> >> c.sort(|x, y| -> x?> y); >> >> instead of: >> >> c.sort((x, y) -> x?> y); >> >> But I'm sure you will already have considered (and rejected) > '|'. > > Since? the decision is to go away from familiar things in Java (as > opposed to #() {stmt}), I might also favour: > ? |x, y| -> x + y > > It is a lot clearer in many ways in complicated situations, and would > be beter for the eye in finding the target of "return" statements. > > I don't know without looking closer whether this is sufficiently > distinguishable from OR however: > ? || -> expr > > Stephen > From pbenedict at apache.org Wed Sep 28 08:58:02 2011 From: pbenedict at apache.org (Paul Benedict) Date: Wed, 28 Sep 2011 10:58:02 -0500 Subject: Syntax decision In-Reply-To: <4E83414A.3090205@oracle.com> References: <4E692067.1080509@oracle.com> <4E822196.10801@oracle.com> <4E83320D.8000503@oracle.com> <4E833767.9000208@comp.lancs.ac.uk> <4E83414A.3090205@oracle.com> Message-ID: On Wed, Sep 28, 2011 at 10:46 AM, Brian Goetz wrote: > Yes, there are lots of possible hacks like this, including: > - forcing unary inferred-type lambdas to not use parens: > x -> e instead of allowing (x) -> e > - Not allow casting of nilary lambdas without specifying () > (T)() -> e instead of allowing (T) -> e > > But all of these introduce irregularities into the syntax, for the sake > of supporting an extra case because people find > > () -> e > > to be ugly. This increases the complexity of the syntax and means there > are more special cases to learn. > > With the current approach, there is only one special case: > - All lambdas consist of paren-args-paren-arrow-body > - For the special case of unary, type-inferred lambdas, you can omit > the parens: x -> x+1 > > Turning that into "you *must* omit the parens" means that all users, > even those who don't care about the nilary form, must learn another rule. > > Better suggestions? > > If a lambda needs no arguments and if () looks ugly (nods), is this anymore palatable? (void) -> e From henrigerrits at yahoo.com Wed Sep 28 09:13:00 2011 From: henrigerrits at yahoo.com (Henri Gerrits) Date: Wed, 28 Sep 2011 09:13:00 -0700 (PDT) Subject: Syntax decision In-Reply-To: <1317225470.87733.YahooMailNeo@web160706.mail.bf1.yahoo.com> References: <4E692067.1080509@oracle.com> <4E822196.10801@oracle.com> <4E83320D.8000503@oracle.com> <1317223451.31622.YahooMailNeo@web160717.mail.bf1.yahoo.com> <1317225470.87733.YahooMailNeo@web160706.mail.bf1.yahoo.com> Message-ID: <1317226380.60818.YahooMailNeo@web160717.mail.bf1.yahoo.com> I meant "doesn't" ? ----- Original Message ----- > From: Henri Gerrits > To: Stephen Colebourne ; lambda-dev > Cc: > Sent: Wednesday, September 28, 2011 11:57 AM > Subject: Re: Syntax decision > > Of course there is also the bitwise OR operator to consider. > I think the parser's lookahead should be able to handle these potential > syntactical complications. > > But do you really NEED a no-arg placeholder? > > BTW: the C# syntax posted by Brian originally does seem to allow the > '()' syntax either: > >> ? ? ? > The C# syntax is: >> ? ? ? > >> ? ? ? >? ? lambda = ArgList Arrow Body >> ? ? ? >? ? ArgList = Identifier >> ? ? ? >? ? ? ? ? ? ? | "(" Identifier [ "," > Identifier ]* ")" >> ? ? ? >? ? ? ? ? ? ? | "(" Type Identifier [ "," Type > Identifier ]* ")" >> ? ? ? >? ? Body = Expression >> ? ? ? >? ? ? ? ? ? ? | "{" [ Statement ";" ]+ > "}" > > I must add I'm new to this discussion. > > Henri > > ----- Original Message ----- >> From: Stephen Colebourne >> To: lambda-dev >> Cc: >> Sent: Wednesday, September 28, 2011 11:32 AM >> Subject: Re: Syntax decision >> >> On 28 September 2011 16:24, Henri Gerrits > wrote: >>> Since the cast syntax can't be touched, one way out could be to > change >> the arg?delimiters for the lambda, e.g.; >>> >>> |x, y| -> x + y; >>> >>> Personally, I find this?a bit more readable when the lambda is > provided?as >> an argument to a method or constructor: >>> >>> c.sort(|x, y| -> x?> y); >>> >>> instead of: >>> >>> c.sort((x, y) -> x?> y); >>> >>> But I'm sure you will already have considered (and rejected) >> '|'. >> >> Since? the decision is to go away from familiar things in Java (as >> opposed to #() {stmt}), I might also favour: >> ? |x, y| -> x + y >> >> It is a lot clearer in many ways in complicated situations, and would >> be beter for the eye in finding the target of "return" > statements. >> >> I don't know without looking closer whether this is sufficiently >> distinguishable from OR however: >> ? || -> expr >> >> Stephen >> > From Robert.Field at oracle.com Wed Sep 28 09:47:17 2011 From: Robert.Field at oracle.com (Robert Field) Date: Wed, 28 Sep 2011 09:47:17 -0700 Subject: Syntax decision In-Reply-To: <4E83414A.3090205@oracle.com> References: <4E692067.1080509@oracle.com> <4E822196.10801@oracle.com> <4E83320D.8000503@oracle.com> <4E833767.9000208@comp.lancs.ac.uk> <4E83414A.3090205@oracle.com> Message-ID: <4E834F95.6020504@oracle.com> Regularity in language design... good. Regularity in new language features... very good. Saving a couple characters... not very important. -Robert On 9/28/11 8:46 AM, Brian Goetz wrote: > Yes, there are lots of possible hacks like this, including: > - forcing unary inferred-type lambdas to not use parens: > x -> e instead of allowing (x) -> e > - Not allow casting of nilary lambdas without specifying () > (T)() -> e instead of allowing (T) -> e > > But all of these introduce irregularities into the syntax, for the sake > of supporting an extra case because people find > > () -> e > > to be ugly. This increases the complexity of the syntax and means there > are more special cases to learn. > > With the current approach, there is only one special case: > - All lambdas consist of paren-args-paren-arrow-body > - For the special case of unary, type-inferred lambdas, you can omit > the parens: x -> x+1 > > Turning that into "you *must* omit the parens" means that all users, > even those who don't care about the nilary form, must learn another rule. > > Better suggestions? > > On 9/28/2011 11:04 AM, Steven Simpson wrote: >> On 28/09/11 15:41, Brian Goetz wrote: >>> The nilary syntax is still a thorn. But the obvious solution outlined >>> below -- allow elision of the () -- leads to a syntactic ambiguity. If >>> -> { statement; } were a valid lambda, then is: >>> >>> (identifier) -> { statement; } >>> >>> a one-arg lambda with inferred type, or a cast of a nilary lambda? >> What happens if you treat it as an inferred-type unary? If the author >> intended a casted nilary, will he always get compilation failure?[1] If >> so, can he fix his error by adding the empty param list?: >> >> (identifier) () -> { statement; } >> >> IOW, nilary brackets aren't always optional. >> >> [1] Hmm, does he get a syntax error or something more obscure? >> >> From yshavit at akiban.com Wed Sep 28 10:35:41 2011 From: yshavit at akiban.com (Yuval Shavit) Date: Wed, 28 Sep 2011 13:35:41 -0400 Subject: Syntax decision In-Reply-To: <4E83414A.3090205@oracle.com> References: <4E692067.1080509@oracle.com> <4E822196.10801@oracle.com> <4E83320D.8000503@oracle.com> <4E833767.9000208@comp.lancs.ac.uk> <4E83414A.3090205@oracle.com> Message-ID: Fwiw, I don't find () -> e to be all that ugly... On Wed, Sep 28, 2011 at 11:46 AM, Brian Goetz wrote: > Yes, there are lots of possible hacks like this, including: > - forcing unary inferred-type lambdas to not use parens: > x -> e instead of allowing (x) -> e > - Not allow casting of nilary lambdas without specifying () > (T)() -> e instead of allowing (T) -> e > > But all of these introduce irregularities into the syntax, for the sake > of supporting an extra case because people find > > () -> e > > to be ugly. This increases the complexity of the syntax and means there > are more special cases to learn. > > With the current approach, there is only one special case: > - All lambdas consist of paren-args-paren-arrow-body > - For the special case of unary, type-inferred lambdas, you can omit > the parens: x -> x+1 > > Turning that into "you *must* omit the parens" means that all users, > even those who don't care about the nilary form, must learn another rule. > > Better suggestions? > > On 9/28/2011 11:04 AM, Steven Simpson wrote: > > On 28/09/11 15:41, Brian Goetz wrote: > >> The nilary syntax is still a thorn. But the obvious solution outlined > >> below -- allow elision of the () -- leads to a syntactic ambiguity. If > >> -> { statement; } were a valid lambda, then is: > >> > >> (identifier) -> { statement; } > >> > >> a one-arg lambda with inferred type, or a cast of a nilary lambda? > > > > What happens if you treat it as an inferred-type unary? If the author > > intended a casted nilary, will he always get compilation failure?[1] If > > so, can he fix his error by adding the empty param list?: > > > > (identifier) () -> { statement; } > > > > IOW, nilary brackets aren't always optional. > > > > [1] Hmm, does he get a syntax error or something more obscure? > > > > > > From brian.goetz at oracle.com Wed Sep 28 11:05:40 2011 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 28 Sep 2011 14:05:40 -0400 Subject: Syntax decision In-Reply-To: References: <4E692067.1080509@oracle.com> <4E822196.10801@oracle.com> <4E83320D.8000503@oracle.com> <4E833767.9000208@comp.lancs.ac.uk> <4E83414A.3090205@oracle.com> Message-ID: <4E8361F4.5030709@oracle.com> And, I think that after a few months, none of us will. I think the initial reaction is "wahh, different!" Let's see whether we still hate it as much as we think in six months. On 9/28/2011 1:35 PM, Yuval Shavit wrote: > Fwiw, I don't find () -> e to be all that ugly... > > On Wed, Sep 28, 2011 at 11:46 AM, Brian Goetz > wrote: > > Yes, there are lots of possible hacks like this, including: > - forcing unary inferred-type lambdas to not use parens: > x -> e instead of allowing (x) -> e > - Not allow casting of nilary lambdas without specifying () > (T)() -> e instead of allowing (T) -> e > > But all of these introduce irregularities into the syntax, for the sake > of supporting an extra case because people find > > () -> e > > to be ugly. This increases the complexity of the syntax and means there > are more special cases to learn. > > With the current approach, there is only one special case: > - All lambdas consist of paren-args-paren-arrow-body > - For the special case of unary, type-inferred lambdas, you can omit > the parens: x -> x+1 > > Turning that into "you *must* omit the parens" means that all users, > even those who don't care about the nilary form, must learn another > rule. > > Better suggestions? > > On 9/28/2011 11:04 AM, Steven Simpson wrote: > > On 28/09/11 15:41, Brian Goetz wrote: > >> The nilary syntax is still a thorn. But the obvious solution > outlined > >> below -- allow elision of the () -- leads to a syntactic > ambiguity. If > >> -> { statement; } were a valid lambda, then is: > >> > >> (identifier) -> { statement; } > >> > >> a one-arg lambda with inferred type, or a cast of a nilary lambda? > > > > What happens if you treat it as an inferred-type unary? If the > author > > intended a casted nilary, will he always get compilation > failure?[1] If > > so, can he fix his error by adding the empty param list?: > > > > (identifier) () -> { statement; } > > > > IOW, nilary brackets aren't always optional. > > > > [1] Hmm, does he get a syntax error or something more obscure? > > > > > > From jadoth.paigan at googlemail.com Wed Sep 28 11:13:38 2011 From: jadoth.paigan at googlemail.com (Paigan Jadoth) Date: Wed, 28 Sep 2011 20:13:38 +0200 Subject: Syntax decision In-Reply-To: <4E83320D.8000503@oracle.com> References: <4E692067.1080509@oracle.com> <4E822196.10801@oracle.com> <4E83320D.8000503@oracle.com> Message-ID: What about: 1.) one-arg lambda with inferred type: (identifier) -> { statement; } 2.) really wanting to cast a nilary "-> { statement; }" lambda: (type) (-> { statement; }) This is similar (familiar, regular, consistent, if you will) to already additional required parens for casts like ((type)identifier).method() Even if it ends up being ((type) (-> { statement; })) it's (in my humble developer opinion) still better to have this and an uncluttered short "->{...}" nilary lambdas than always having those dangling empty parens "()->[...}" and a slightly nicer cast-construct. I may also add that since properly applying generics everywhere where reasonable, I hardly write any cast anymore. Only for polymorphic stuff like reflection where really only Object is returned API-wise. So I dare to say that given todays's already existing Java syntax capabilities, future nice nilary lambdas are more important that future little-bit-nicer-casts-for-nilary-lambdas. I gladly admit that I'm no compiler expert, so I may miss important stuff, of course :). Oh on a side note on the original post: I find the "->" much better than "=>". If arrowlings at all instead of the more regular "#(){...}" pattern, then something definitely distinct from the gte/lte tokens is clearly better. And "because the others do that" has never been a good argument, anyway :D. I also think the EG did right to refuse those "_" and "it" magic tokens, I find those Scala sample codes containing them absolutely horrible to read. Scala very much is one of those hype languages that are only "easy" once you have memorized and internalized it's extremely weird syntax character. Noone can tell me that "def sum(l: List[int]): int = (0/:l){_+_}" is anything even remotely near to expressive, concise, readable. Please never add such trickery to Java. As they say, reading is more important that writing ... ultra compressed hacker-geek code. Btw: Are they really called "wunderbar"? That's German for "wonderful" :DD On Wed, Sep 28, 2011 at 4:41 PM, Brian Goetz wrote: > The nilary syntax is still a thorn. But the obvious solution outlined > below -- allow elision of the () -- leads to a syntactic ambiguity. If > -> { statement; } were a valid lambda, then is: > > (identifier) -> { statement; } > > a one-arg lambda with inferred type, or a cast of a nilary lambda? > > If people have brilliant other suggestions for nilary lambda syntax, > we'd consider it. > > > > On 9/28/2011 2:03 AM, Howard Lovatt wrote: > > Personally I am glad you have decided to go with -> since I have had > > trouble reading Scala code, however this is not my main point in this > > post which is have you decided if you require () for no arguments or if > > you plan to allow a 'naked' -> e.g.: > > > > shortCutAnd( -> size >= 0, -> size < max ); // Example equivalent > > to size >= 0 && size < max, but user written > > > > On 28 September 2011 05:18, Brian Goetz > > wrote: > > > > Update on syntax: the EG has chosen to stick with the -> form of the > > arrow that the prototype currently uses, rather than adopt the =>. > > > > You could think of this in two ways (I'm sure I'll hear both): > > > > - This is much better, as it avoids some really bad interactions > with > > existing operators, such as: > > > > x => x.age <= 0; // duelling arrows > > or > > Predicate p = x => x.size == 0; // duelling equals > > > > - What a bunch of idiots we are, in that we claimed the goal of > doing > > what other languages did, and then made gratuitous changes "just for > the > > sake of doing something different". > > > > Obviously we don't think we're idiots, but everyone can have an > > opinion :) > > > > In the end, this was viewed as a small tweak to avoid some > undesirable > > interactions, while preserving the overall goal of "mostly looks like > > what lambdas look like in other similar languages." > > > > > > > > On 9/8/2011 4:07 PM, Brian Goetz wrote: > > > This just in: the EG has (mostly) made a decision on syntax. > > > > > > After considering a number of alternatives, we decided to > essentially > > > adopt the C# syntax. We may still deliberate further on the fine > > points > > > (e.g., thin arrow vs fat arrow, special nilary form, etc), and > > have not > > > yet come to a decision on method reference syntax. > > > > > > The C# syntax is: > > > > > > lambda = ArgList Arrow Body > > > ArgList = Identifier > > > | "(" Identifier [ "," Identifier ]* ")" > > > | "(" Type Identifier [ "," Type Identifier ]* ")" > > > Body = Expression > > > | "{" [ Statement ";" ]+ "}" > > > > > > Here are some examples of lambda expressions using this syntax: > > > > > > x => x + 1 > > > (x) => x + 1 > > > (int x) => x + 1 > > > (int x, int y) => x + y > > > (x, y) => x + y > > > (x, y) => { System.out.printf("%d + %d = %d%n", x, y, x+y); } > > > () => { System.out.println("I am a Runnable"); } > > > > > > The decision to choose this syntax was twofold: > > > - The syntax scores "pretty well" on most subjective measures > > (though > > > has cases where it looks bad, just like all the others do). In > > > particular, it does well with "small" lambdas that are used as > method > > > arguments (a common case), and also does well with large > > > (multi-statement) lambdas. > > > > > > - Despite extensive searching, there was no clear winner among > the > > > alternatives (each form had some good aspects and some really not > > very > > > good aspects, and there was no form that was clearly better than > the > > > others). So, we felt that it was better to choose something that > has > > > already been shown to work well in the two languages that are > > most like > > > Java -- C# and Scala -- rather than to invent something new. > > > > > > A compiler implementation should be available soon. > > > > > > > > > > > > > > > > > > > -- > > -- Howard. > > > > From ss at comp.lancs.ac.uk Wed Sep 28 11:23:10 2011 From: ss at comp.lancs.ac.uk (Steven Simpson) Date: Wed, 28 Sep 2011 19:23:10 +0100 Subject: Syntax decision In-Reply-To: <4E83414A.3090205@oracle.com> References: <4E692067.1080509@oracle.com> <4E822196.10801@oracle.com> <4E83320D.8000503@oracle.com> <4E833767.9000208@comp.lancs.ac.uk> <4E83414A.3090205@oracle.com> Message-ID: <4E83660E.1040803@comp.lancs.ac.uk> On 28/09/11 16:46, Brian Goetz wrote: > With the current approach, there is only one special case: > - All lambdas consist of paren-args-paren-arrow-body > - For the special case of unary, type-inferred lambdas, you can omit > the parens: x -> x+1 > > Turning that into "you *must* omit the parens" means that all users, > even those who don't care about the nilary form, must learn another rule. "must omit"? I don't see where either of us have suggested that. Cheers! From ss at comp.lancs.ac.uk Wed Sep 28 11:30:27 2011 From: ss at comp.lancs.ac.uk (Steven Simpson) Date: Wed, 28 Sep 2011 19:30:27 +0100 Subject: Syntax decision In-Reply-To: <4E83660E.1040803@comp.lancs.ac.uk> References: <4E692067.1080509@oracle.com> <4E822196.10801@oracle.com> <4E83320D.8000503@oracle.com> <4E833767.9000208@comp.lancs.ac.uk> <4E83414A.3090205@oracle.com> <4E83660E.1040803@comp.lancs.ac.uk> Message-ID: <4E8367C3.80707@comp.lancs.ac.uk> On 28/09/11 19:23, Steven Simpson wrote: > "must omit"? I don't see where either of us have suggested that. Ignore me - I've seen it now! ;-) > - forcing unary inferred-type lambdas to not use parens: > x -> e instead of allowing (x) -> e From howard.lovatt at gmail.com Wed Sep 28 18:39:00 2011 From: howard.lovatt at gmail.com (Howard Lovatt) Date: Thu, 29 Sep 2011 11:39:00 +1000 Subject: Syntax decision In-Reply-To: <4E833185.70306@oracle.com> References: <4E692067.1080509@oracle.com> <4E822196.10801@oracle.com> <4E833185.70306@oracle.com> Message-ID: Brian, Can the -> be treated like a + operator and have different precedence for unary and binary forms, i.e. binary form has precedence between ternary and assignment and the unary form between cast and prefix unary (both forms binding right to left)? Then: (T) -> x Would be an error, like (Integer)+i is. You would need to write: (T)(-> x) Again, like you would write (Integer)(+i). Similarly to +, both: (x) -> x + 1 and: x -> x + 1 Would be legal. -- Howard. On 29 September 2011 00:39, Brian Goetz wrote: > Yes, wunderbars were considered and (overwhelmingly) rejected by the EG. > > On 9/28/2011 5:27 AM, Lieven Lemiengre wrote: > > Other languages (such as Scala or Groovy) don't have this problem > > because they support some placeholder syntax. > > > > In reality you don't write "x => x.age <= 0;" > > But this is very common "someList.partition(x => x.age <= 18)" and I > > agree this looks bad. Other languages make this clearer using > > placeholder syntax "someList.partition(_.age <= 18)" or > > "someList.partition(it.age <= 18)" > > I hope you are considering something like this, these little closures > > will be used a lot! > > (And I don't think replacing '=>' with '->' will help a lot) > > > > > > On Tue, Sep 27, 2011 at 9:18 PM, Brian Goetz > > wrote: > > > > Update on syntax: the EG has chosen to stick with the -> form of the > > arrow that the prototype currently uses, rather than adopt the =>. > > > > You could think of this in two ways (I'm sure I'll hear both): > > > > - This is much better, as it avoids some really bad interactions > with > > existing operators, such as: > > > > x => x.age <= 0; // duelling arrows > > or > > Predicate p = x => x.size == 0; // duelling equals > > > > - What a bunch of idiots we are, in that we claimed the goal of > doing > > what other languages did, and then made gratuitous changes "just for > the > > sake of doing something different". > > > > Obviously we don't think we're idiots, but everyone can have an > > opinion :) > > > > In the end, this was viewed as a small tweak to avoid some > undesirable > > interactions, while preserving the overall goal of "mostly looks like > > what lambdas look like in other similar languages." > > > > > > > > On 9/8/2011 4:07 PM, Brian Goetz wrote: > > > This just in: the EG has (mostly) made a decision on syntax. > > > > > > After considering a number of alternatives, we decided to > essentially > > > adopt the C# syntax. We may still deliberate further on the fine > > points > > > (e.g., thin arrow vs fat arrow, special nilary form, etc), and > > have not > > > yet come to a decision on method reference syntax. > > > > > > The C# syntax is: > > > > > > lambda = ArgList Arrow Body > > > ArgList = Identifier > > > | "(" Identifier [ "," Identifier ]* ")" > > > | "(" Type Identifier [ "," Type Identifier ]* ")" > > > Body = Expression > > > | "{" [ Statement ";" ]+ "}" > > > > > > Here are some examples of lambda expressions using this syntax: > > > > > > x => x + 1 > > > (x) => x + 1 > > > (int x) => x + 1 > > > (int x, int y) => x + y > > > (x, y) => x + y > > > (x, y) => { System.out.printf("%d + %d = %d%n", x, y, x+y); } > > > () => { System.out.println("I am a Runnable"); } > > > > > > The decision to choose this syntax was twofold: > > > - The syntax scores "pretty well" on most subjective measures > > (though > > > has cases where it looks bad, just like all the others do). In > > > particular, it does well with "small" lambdas that are used as > method > > > arguments (a common case), and also does well with large > > > (multi-statement) lambdas. > > > > > > - Despite extensive searching, there was no clear winner among > the > > > alternatives (each form had some good aspects and some really not > > very > > > good aspects, and there was no form that was clearly better than > the > > > others). So, we felt that it was better to choose something that > has > > > already been shown to work well in the two languages that are > > most like > > > Java -- C# and Scala -- rather than to invent something new. > > > > > > A compiler implementation should be available soon. > > > > > > > > > > > > > > > -- -- Howard. From howard.lovatt at gmail.com Wed Sep 28 18:46:24 2011 From: howard.lovatt at gmail.com (Howard Lovatt) Date: Thu, 29 Sep 2011 11:46:24 +1000 Subject: Syntax decision In-Reply-To: References: <4E692067.1080509@oracle.com> <4E822196.10801@oracle.com> <4E833185.70306@oracle.com> Message-ID: I will answer my own question, yes but has an undesirable side effect. You would have to write: -> (x + 1) which is not significantly better than: () -> x + 1 Therefore current solution is probably the best if () are to be used. -- Howard. On 29 September 2011 11:39, Howard Lovatt wrote: > Brian, > > Can the -> be treated like a + operator and have different precedence for > unary and binary forms, i.e. binary form has precedence between ternary and > assignment and the unary form between cast and prefix unary (both forms > binding right to left)? Then: > > (T) -> x > > Would be an error, like (Integer)+i is. You would need to write: > > (T)(-> x) > > Again, like you would write (Integer)(+i). > > Similarly to +, both: > > (x) -> x + 1 > > and: > > x -> x + 1 > > Would be legal. > > -- Howard. > > > On 29 September 2011 00:39, Brian Goetz wrote: > >> Yes, wunderbars were considered and (overwhelmingly) rejected by the EG. >> >> On 9/28/2011 5:27 AM, Lieven Lemiengre wrote: >> > Other languages (such as Scala or Groovy) don't have this problem >> > because they support some placeholder syntax. >> > >> > In reality you don't write "x => x.age <= 0;" >> > But this is very common "someList.partition(x => x.age <= 18)" and I >> > agree this looks bad. Other languages make this clearer using >> > placeholder syntax "someList.partition(_.age <= 18)" or >> > "someList.partition(it.age <= 18)" >> > I hope you are considering something like this, these little closures >> > will be used a lot! >> > (And I don't think replacing '=>' with '->' will help a lot) >> > >> > >> > On Tue, Sep 27, 2011 at 9:18 PM, Brian Goetz > > > wrote: >> > >> > Update on syntax: the EG has chosen to stick with the -> form of the >> > arrow that the prototype currently uses, rather than adopt the =>. >> > >> > You could think of this in two ways (I'm sure I'll hear both): >> > >> > - This is much better, as it avoids some really bad interactions >> with >> > existing operators, such as: >> > >> > x => x.age <= 0; // duelling arrows >> > or >> > Predicate p = x => x.size == 0; // duelling equals >> > >> > - What a bunch of idiots we are, in that we claimed the goal of >> doing >> > what other languages did, and then made gratuitous changes "just for >> the >> > sake of doing something different". >> > >> > Obviously we don't think we're idiots, but everyone can have an >> > opinion :) >> > >> > In the end, this was viewed as a small tweak to avoid some >> undesirable >> > interactions, while preserving the overall goal of "mostly looks >> like >> > what lambdas look like in other similar languages." >> > >> > >> > >> > On 9/8/2011 4:07 PM, Brian Goetz wrote: >> > > This just in: the EG has (mostly) made a decision on syntax. >> > > >> > > After considering a number of alternatives, we decided to >> essentially >> > > adopt the C# syntax. We may still deliberate further on the fine >> > points >> > > (e.g., thin arrow vs fat arrow, special nilary form, etc), and >> > have not >> > > yet come to a decision on method reference syntax. >> > > >> > > The C# syntax is: >> > > >> > > lambda = ArgList Arrow Body >> > > ArgList = Identifier >> > > | "(" Identifier [ "," Identifier ]* ")" >> > > | "(" Type Identifier [ "," Type Identifier ]* ")" >> > > Body = Expression >> > > | "{" [ Statement ";" ]+ "}" >> > > >> > > Here are some examples of lambda expressions using this syntax: >> > > >> > > x => x + 1 >> > > (x) => x + 1 >> > > (int x) => x + 1 >> > > (int x, int y) => x + y >> > > (x, y) => x + y >> > > (x, y) => { System.out.printf("%d + %d = %d%n", x, y, x+y); >> } >> > > () => { System.out.println("I am a Runnable"); } >> > > >> > > The decision to choose this syntax was twofold: >> > > - The syntax scores "pretty well" on most subjective measures >> > (though >> > > has cases where it looks bad, just like all the others do). In >> > > particular, it does well with "small" lambdas that are used as >> method >> > > arguments (a common case), and also does well with large >> > > (multi-statement) lambdas. >> > > >> > > - Despite extensive searching, there was no clear winner among >> the >> > > alternatives (each form had some good aspects and some really not >> > very >> > > good aspects, and there was no form that was clearly better than >> the >> > > others). So, we felt that it was better to choose something that >> has >> > > already been shown to work well in the two languages that are >> > most like >> > > Java -- C# and Scala -- rather than to invent something new. >> > > >> > > A compiler implementation should be available soon. >> > > >> > > >> > > >> > >> > >> >> > > > -- > -- Howard. > > -- -- Howard. From brian.goetz at oracle.com Wed Sep 28 18:50:49 2011 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 28 Sep 2011 21:50:49 -0400 Subject: Syntax decision In-Reply-To: References: <4E692067.1080509@oracle.com> <4E822196.10801@oracle.com> <4E833185.70306@oracle.com> Message-ID: <4E83CEF9.5050700@oracle.com> Its probably possible to use precedence to enable -> e to be the nilary form, but no matter how you slice it, it creates an irregularity somewhere. Here, the irregularity is requiring the extra parens in a cast, which wouldn't be required around lambdas in other situations. We've already discussed some other possible irregularities that could enable the same result. At present, it doesn't seem worth it to introduce an irregularity just to support this syntax. As I said earlier, while () -> expr may look really weird to us now, its not obvious it will look so bad after some experience. So let's see what we think in six months. On 9/28/2011 9:39 PM, Howard Lovatt wrote: > Brian, > > Can the -> be treated like a + operator and have > different precedence for unary and binary forms, i.e. binary form > has precedence between ternary and assignment and the unary form between > cast and prefix unary (both forms binding right to left)? Then: > > (T) -> x > > Would be an error, like (Integer)+i is. You would need to write: > > (T)(-> x) > > Again, like you would write (Integer)(+i). > > Similarly to +, both: > > (x) -> x + 1 > > and: > > x -> x + 1 > > Would be legal. > > -- Howard. > > On 29 September 2011 00:39, Brian Goetz > wrote: > > Yes, wunderbars were considered and (overwhelmingly) rejected by the EG. > > On 9/28/2011 5:27 AM, Lieven Lemiengre wrote: > > Other languages (such as Scala or Groovy) don't have this problem > > because they support some placeholder syntax. > > > > In reality you don't write "x => x.age <= 0;" > > But this is very common "someList.partition(x => x.age <= 18)" and I > > agree this looks bad. Other languages make this clearer using > > placeholder syntax "someList.partition(_.age <= 18)" or > > "someList.partition(it.age <= 18)" > > I hope you are considering something like this, these little closures > > will be used a lot! > > (And I don't think replacing '=>' with '->' will help a lot) > > > > > > On Tue, Sep 27, 2011 at 9:18 PM, Brian Goetz > > > >> > wrote: > > > > Update on syntax: the EG has chosen to stick with the -> form > of the > > arrow that the prototype currently uses, rather than adopt > the =>. > > > > You could think of this in two ways (I'm sure I'll hear both): > > > > - This is much better, as it avoids some really bad > interactions with > > existing operators, such as: > > > > x => x.age <= 0; // duelling arrows > > or > > Predicate p = x => x.size == 0; // duelling equals > > > > - What a bunch of idiots we are, in that we claimed the > goal of doing > > what other languages did, and then made gratuitous changes > "just for the > > sake of doing something different". > > > > Obviously we don't think we're idiots, but everyone can have an > > opinion :) > > > > In the end, this was viewed as a small tweak to avoid some > undesirable > > interactions, while preserving the overall goal of "mostly > looks like > > what lambdas look like in other similar languages." > > > > > > > > On 9/8/2011 4:07 PM, Brian Goetz wrote: > > > This just in: the EG has (mostly) made a decision on syntax. > > > > > > After considering a number of alternatives, we decided to > essentially > > > adopt the C# syntax. We may still deliberate further on the fine > > points > > > (e.g., thin arrow vs fat arrow, special nilary form, etc), and > > have not > > > yet come to a decision on method reference syntax. > > > > > > The C# syntax is: > > > > > > lambda = ArgList Arrow Body > > > ArgList = Identifier > > > | "(" Identifier [ "," Identifier ]* ")" > > > | "(" Type Identifier [ "," Type Identifier ]* ")" > > > Body = Expression > > > | "{" [ Statement ";" ]+ "}" > > > > > > Here are some examples of lambda expressions using this syntax: > > > > > > x => x + 1 > > > (x) => x + 1 > > > (int x) => x + 1 > > > (int x, int y) => x + y > > > (x, y) => x + y > > > (x, y) => { System.out.printf("%d + %d = %d%n", x, y, x+y); } > > > () => { System.out.println("I am a Runnable"); } > > > > > > The decision to choose this syntax was twofold: > > > - The syntax scores "pretty well" on most subjective measures > > (though > > > has cases where it looks bad, just like all the others do). In > > > particular, it does well with "small" lambdas that are used as > method > > > arguments (a common case), and also does well with large > > > (multi-statement) lambdas. > > > > > > - Despite extensive searching, there was no clear winner > among the > > > alternatives (each form had some good aspects and some really not > > very > > > good aspects, and there was no form that was clearly better > than the > > > others). So, we felt that it was better to choose something > that has > > > already been shown to work well in the two languages that are > > most like > > > Java -- C# and Scala -- rather than to invent something new. > > > > > > A compiler implementation should be available soon. > > > > > > > > > > > > > > > > > > -- > -- Howard. > From mark.reinhold at oracle.com Thu Sep 29 21:40:40 2011 From: mark.reinhold at oracle.com (mark.reinhold at oracle.com) Date: Thu, 29 Sep 2011 21:40:40 -0700 Subject: JEP 107: Bulk Data Operations for Collections Message-ID: <20110930044040.459AF9DB@eggemoggin.niobe.net> Posted: http://openjdk.java.net/jeps/107 - Mark From zhong.j.yu at gmail.com Thu Sep 29 22:11:28 2011 From: zhong.j.yu at gmail.com (Zhong Yu) Date: Fri, 30 Sep 2011 00:11:28 -0500 Subject: Syntax decision Message-ID: Since 0-arg case is quite common, as in Runnable and Callable, we'll have many use cases like cache.get(key, ()->load(key)); tasks.add(()->{ doSomething(arg);}); transaction(()->{ statement1; statement2; }); Not bad after staring at them for 30 minutes. But too many consecutive punctuation marks are there... quite dizzy at first sight. How about a single punctuation mark, currently unused, as syntax sugar for "()->". Too cheesy? - Zhong Yu From ryanm128 at gmail.com Thu Sep 29 22:26:33 2011 From: ryanm128 at gmail.com (Ryan Musgrave) Date: Fri, 30 Sep 2011 13:26:33 +0800 Subject: summary of point lambdafication survey In-Reply-To: <11216_1317360053_4E8551B5_11216_3359_1_EC2D3AAAA2308F4EA3813FD3D3A3A5D41DBDF4110F@GISVWE-EX02.Area04.grp> References: <11216_1317360053_4E8551B5_11216_3359_1_EC2D3AAAA2308F4EA3813FD3D3A3A5D41DBDF4110F@GISVWE-EX02.Area04.grp> Message-ID: Stuart Marks wrote: > * Process.onExit(block) - execute block when the process exits Would this include the relevant addition to ProcessBuilder? Regards, Ryan Musgrave From howard.lovatt at gmail.com Fri Sep 30 00:22:39 2011 From: howard.lovatt at gmail.com (Howard Lovatt) Date: Fri, 30 Sep 2011 17:22:39 +1000 Subject: JEP 107: Bulk Data Operations for Collections In-Reply-To: <20110930044040.459AF9DB@eggemoggin.niobe.net> References: <20110930044040.459AF9DB@eggemoggin.niobe.net> Message-ID: Are you calling for input? Happy to post my experiences with a parallel filter/map/reduce (though I call it retain/recycle/reduce) library that I use for my own projects that is built upon fork/join, if that is what you are asking for. -- Howard. On 30 September 2011 14:40, wrote: > Posted: http://openjdk.java.net/jeps/107 > > - Mark > > From Klaus.Malorny at knipp.de Fri Sep 30 00:33:53 2011 From: Klaus.Malorny at knipp.de (Klaus Malorny) Date: Fri, 30 Sep 2011 09:33:53 +0200 Subject: Syntax decision Message-ID: <4E8570E1.3050700@knipp.de> > Here are some examples of lambda expressions using this syntax: > > [...] > > () => { System.out.println("I am a Runnable"); } Hi, for the no-args case, wouldn't it be nice just to write a block with curly braces? I.e. Executor ex = ... ex.execute ({ System.out.println ("Hello world!"); }); Or would it be in syntactical conflict with other language constructs? Regards, Klaus From fweimer at bfk.de Fri Sep 30 00:48:04 2011 From: fweimer at bfk.de (Florian Weimer) Date: Fri, 30 Sep 2011 07:48:04 +0000 Subject: Syntax decision In-Reply-To: (Stephen Colebourne's message of "Wed, 28 Sep 2011 16:28:02 +0100") References: <4E692067.1080509@oracle.com> <4E822196.10801@oracle.com> <4E83320D.8000503@oracle.com> Message-ID: <82vcsav5cb.fsf@mid.bfk.de> * Stephen Colebourne: > You could use an "extended arrow" for nilary: > --> expr > --> {stmt;} > > where the extra dash effectively means "nothing" The arrow goes into the wrong direction, though. The value comes from expr, it is not applied to it. The "() -> expr" syntax doesn't have this problem. -- Florian Weimer BFK edv-consulting GmbH http://www.bfk.de/ Kriegsstra?e 100 tel: +49-721-96201-1 D-76133 Karlsruhe fax: +49-721-96201-99 From zhong.j.yu at gmail.com Fri Sep 30 02:53:12 2011 From: zhong.j.yu at gmail.com (Zhong Yu) Date: Fri, 30 Sep 2011 04:53:12 -0500 Subject: Syntax decision In-Reply-To: <4E8556E7.2020206@gmail.com> References: <4E8556E7.2020206@gmail.com> Message-ID: After even longer stare, ()-> looks fine to me; it fades in the background. I was actually thinking about a case like (http://gafter.blogspot.com/2006/12/super-type-tokens.html) TypeReference> x = new TypeReference>() {}; => TypeReference> x = ()->{}; which looks *really* bizzare. But now I know abstract class is not supported, so the case is moot. Zhong Yu On Fri, Sep 30, 2011 at 12:43 AM, Brenden Towey wrote: > Actually the way you've formatted it here, I don't mind ()-> as a nullity > lambda. ?Even the () looks a bit like a zero, which is a pretty good > "nullity" if you ask me. ?Formatting it so it runs together makes it stand > out. ?Trying to separate it with spaces might confuse the reader more. > > And I'm honestly uncertain of the value of some other symbol. ?Do you have a > proposal? > > > > On 9/29/2011 10:11 PM, Zhong Yu wrote: >> >> Since 0-arg case is quite common, as in Runnable and Callable, we'll >> have many use cases like >> >> ? ? cache.get(key, ()->load(key)); >> >> Not bad after staring at them for 30 minutes. But too many consecutive >> punctuation marks are there... quite dizzy at first sight. > > > > From fyaoxy at gmail.com Fri Sep 30 03:14:41 2011 From: fyaoxy at gmail.com (=?UTF-8?B?5ZCR6ZuF?=) Date: Fri, 30 Sep 2011 18:14:41 +0800 Subject: Syntax decision In-Reply-To: <82vcsav5cb.fsf@mid.bfk.de> References: <4E692067.1080509@oracle.com> <4E822196.10801@oracle.com> <4E83320D.8000503@oracle.com> <82vcsav5cb.fsf@mid.bfk.de> Message-ID: Happy to see the thread like fair:-) It should be. for sake of your eye, the post converted to DM html, (Through at this moment it's not DM). What I emphasize again and again, is CONTEXT. Almost all compiler or cc, is Context-Free. just like latin-s languages. I will say rudely, it's wrong. You should learn the Chinish, my mother language, she is context-relative. BTW, I'm a Chinan, to European descendant, the words Chinish and Chinan, from your ancestor. AIK, there are some my brothers in java team, maybe they can teach some basic, through I not sure they catch me about the post. Let me make a explain why CF style is wrong, just oriented the lamda. What's lamda use case? One main, invocation parameters. Only one, or multiple? both! what's form? expression, or statement. How may parameters for lamda self? *. OK, conclusion, in java, lamda will used as method parameter by expression or statement way, and lamda has any number of parameters. Lets see one parameter case: //OO parameter cases: collection.filter(x<3); collection.filter(x<3 && y>5); collection.filter(checkX(x)); collection.filter(checkX(x, y)); //more complicated: int ctxJ; coolection.filter(ctxJ>0? x<3: y>5); collection.filter(x){ if(ctxJ>0) return x100) return x>ctxJ && y>5; doCheckingForX(x); return y>5; }; //Last parameter cases: collection.filter("condition", ..., x<3); collection.filter("condition", ..., checkX(x)); collection.filter("condition", ..., x<3 && y>5); collection.filter("condition", ..., checkX(x, y)); //Multiple parameter lamdas collection.filter(x<3, y<5, z>2); collection.filter(checkX(x), checkY(y)); collection.filter(x, y){ checkX(x); return x>2;}{ checkY(y); return y<3;}; collection.filter(x, (x,y)){ lamda.implements(x)}{lamda.implements(x,y)}; //BTW, x, or (x,y) cannot infer? it's to put off pants to fart! //it's form collection.filter(expression, expression) collection.filter({statement;+}{statememt;+}); //BTW, dose any still need a comma between blocks? collection.filter({statement;+}+); Object other; collection.filter(expression, other, expression) collection.filter({statement;+}{statememt;+}, other); //BTW, dose any still need a comma between blocks? collection.filter({statement;+}+, other, ....); Look, it's easy? OK, I stop, just like tiger head and snake tail, just be it. As to assign case, not true case, dont make a wrong direction. it exampled at follow snippets. Hint, if some difficult, rethink your compiler arch. Lexer should not do more thing, it's should be just a simple scanner. most work must within context. that some like early binding and later binding. I think you know its problem. If by this way, all is APOC. Trust me, I did develop a c-structure super set by this way, very success. there have some example by my way, origin from M$ c# msdn page snippet1: delegate int del(int i); static void main(String[] args){ del(x)=x*x; int j=del(5); } s2: using System.Linq.Expressions; namespace ConsoleApplication1{ class Program{ static void Main(string[] args){ Expression myET(x)= x * x; } } } s3: delegate void TestDelegate(string s); ? TestDelegate myDel(n){ string s = n + " " + "World"; Console.WriteLine(s); }; myDel("Hello"); s4: Func myFunc(x) = x == 5; bool result = myFunc(4); // returns false of course s5: int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; int oddNumbers = numbers.Count(n % 2 == 1); int oddNumbers = numbers.Count(n){n % 2 == 1}; s6: var firstSmallNumbers = numbers.TakeWhile(n >= index); var firstSmallNumbers = numbers.TakeWhile(n, index) {n >= index;} s7: customers.Where(c){c.City == "London"}; customers.Where(c.City == "London"); s8: delegate bool D(); delegate bool D2(int i); class Test{ D del; D2 del2; public void TestMethod(int input){ int j = 0; // Initialize the delegates with lambda expressions. // Note access to 2 outer variables. // del will be invoked within this method. del{ j = 10; return j > input; }; del(){ j = 10; return j > input; }; // del2 will be invoked after TestMethod goes out of scope. del2(x){return x == j; }; // Demonstrate value of j: // Output: j = 0 // The delegate has not been invoked yet. Console.WriteLine("j = {0}", j); // Invoke the delegate. bool boolResult = del(); // Output: j = 10 b = True Console.WriteLine("j = {0}. b = {1}", j, boolResult); } static void Main(){ Test test = new Test(); test.TestMethod(5); // Prove that del2 still has a copy of // local variable j from TestMethod. bool result = test.del2(10); // Output: True Console.WriteLine(result); Console.ReadKey(); } } From brian.goetz at oracle.com Fri Sep 30 07:33:31 2011 From: brian.goetz at oracle.com (Brian Goetz) Date: Fri, 30 Sep 2011 10:33:31 -0400 Subject: JEP 107: Bulk Data Operations for Collections In-Reply-To: References: <20110930044040.459AF9DB@eggemoggin.niobe.net> Message-ID: <4E85D33B.5020804@oracle.com> This is part of the new process that was announced recently for collecting, reviewing, sorting, and recording proposals for enhancements, as outlined here: http://openjdk.java.net/jeps/1 On 9/30/2011 3:22 AM, Howard Lovatt wrote: > Are you calling for input? > > Happy to post my experiences with a parallel filter/map/reduce (though I > call it retain/recycle/reduce) library that I use for my own projects that > is built upon fork/join, if that is what you are asking for. > > -- Howard. > > On 30 September 2011 14:40, wrote: > >> Posted: http://openjdk.java.net/jeps/107 >> >> - Mark >> >> > From stuart.marks at oracle.com Fri Sep 30 14:48:04 2011 From: stuart.marks at oracle.com (Stuart Marks) Date: Fri, 30 Sep 2011 14:48:04 -0700 Subject: summary of point lambdafication survey In-Reply-To: References: <11216_1317360053_4E8551B5_11216_3359_1_EC2D3AAAA2308F4EA3813FD3D3A3A5D41DBDF4110F@GISVWE-EX02.Area04.grp> Message-ID: <4E863914.1090104@oracle.com> On 9/29/11 10:26 PM, Ryan Musgrave wrote: > Stuart Marks wrote: >> * Process.onExit(block) > - execute block when the process exits > Would this include the relevant addition to ProcessBuilder? I imagine that it would. The survey response didn't have much more than what I had listed here. It was pretty informal. I also note that a JEP to update the Process API has just been posted: http://openjdk.java.net/jeps/102 Presumably some kind of process-state-changed callback would be included with that update, possibly using lambda. (To see other JEPs and to learn more about the JEP process, look here:) http://openjdk.java.net/jeps/0 s'marks From stuart.marks at oracle.com Fri Sep 30 15:04:31 2011 From: stuart.marks at oracle.com (Stuart Marks) Date: Fri, 30 Sep 2011 15:04:31 -0700 Subject: Syntax decision In-Reply-To: References: <4E8556E7.2020206@gmail.com> Message-ID: <4E863CEF.6000005@oracle.com> On 9/30/11 2:53 AM, Zhong Yu wrote: > After even longer stare, ()-> looks fine to me; it fades in the background. I think this is an important point, one that Brian Goetz has made a couple times. A large component of syntax like/dislike is what one is used to. I had a similar experience when I updated the lambda prototypes to the new syntax: http://hg.openjdk.java.net/lambda/lambda/jdk/rev/d9e4e3c106a7 Initially I liked the #{...} syntax and I was opposed to the C#/Scala style syntax when it was proposed. But after having worked with the new style syntax for just a couple hours, I got used to it. Yes, there are weird things about it, but there are weird things about any syntax. At this point the #{...} syntax looks old and clunky. Another thing I do not miss about the old syntax is that #{ -> expr; } was a statement whereas #{ -> stmt } was an expression. A missing or extra semicolon could even change overload resolution! The new syntax uses { } to distinguish statement lambdas, which is perfectly sensible to me. Using the new syntax, I went through several phases of using extra parentheses in order to highlight the lambda, but I eventually pulled them all out. You can see the results in the code: there are very few places with parentheses where they aren't required. It's a bit unfortunate that the nilary lambda requires an empty pair of parens, but (as others have noted) making them optional seems to introduce a bunch of problems and special cases, and having them isn't really all that bad, so why not just live with them. s'marks From int19h at gmail.com Fri Sep 30 15:18:45 2011 From: int19h at gmail.com (Pavel Minaev) Date: Fri, 30 Sep 2011 15:18:45 -0700 Subject: Syntax decision In-Reply-To: References: Message-ID: Note that most such special cases also have 1) a single lambda that 2) occurs in the final argument position. So I think that this is an argument for some kind of syntactic sugar akin to what Ruby has - where you can write: foo.bar(1, 2, 3) {|x,y,z| ...} instead of: foo.bar(1, 2, 3, {|x,y,z| ...}) i.e. moving the lambda outside the parentheses, and making it look more like a statement with a body than a function call. I don't think this is something worth pursuing for the first version, though. ()->{} is good enough in practice, and extra syntactic sugar can always be slapped on top when and if needed. On Thu, Sep 29, 2011 at 10:11 PM, Zhong Yu wrote: > Since 0-arg case is quite common, as in Runnable and Callable, we'll > have many use cases like > > cache.get(key, ()->load(key)); > > tasks.add(()->{ doSomething(arg);}); > > transaction(()->{ > statement1; > statement2; > }); > > Not bad after staring at them for 30 minutes. But too many consecutive > punctuation marks are there... quite dizzy at first sight. > > How about a single punctuation mark, currently unused, as syntax sugar > for "()->". Too cheesy? > > - Zhong Yu > > From zhong.j.yu at gmail.com Fri Sep 30 16:17:37 2011 From: zhong.j.yu at gmail.com (Zhong Yu) Date: Fri, 30 Sep 2011 18:17:37 -0500 Subject: Syntax decision In-Reply-To: <4E863CEF.6000005@oracle.com> References: <4E8556E7.2020206@gmail.com> <4E863CEF.6000005@oracle.com> Message-ID: On Fri, Sep 30, 2011 at 5:04 PM, Stuart Marks wrote: > On 9/30/11 2:53 AM, Zhong Yu wrote: >> >> After even longer stare, ()-> ?looks fine to me; it fades in the >> background. > > I think this is an important point, one that Brian Goetz has made a couple > times. A large component of syntax like/dislike is what one is used to. I > had a similar experience when I updated the lambda prototypes to the new > syntax: > > http://hg.openjdk.java.net/lambda/lambda/jdk/rev/d9e4e3c106a7 > > Initially I liked the #{...} syntax and I was opposed to the C#/Scala style > syntax when it was proposed. But after having worked with the new style > syntax for just a couple hours, I got used to it. Yes, there are weird > things about it, but there are weird things about any syntax. Arguably Java method declaration syntax is weird too: name(args){body} for anyone new to programming. But the syntax has been in mainstream for 4 decades, so everybody is accustomed to it. That's why I don't really understand why the strawman syntax, closest to method declaration, is killed; I read the archive and couldn't find any objection to it. (I have no intention to argue about syntax, just curious to learn what's wrong with strawman syntax; ignore me if you would) - Zhong Yu > At this point the #{...} syntax looks old and clunky. Another thing I do not > miss about the old syntax is that #{ -> expr; } was a statement whereas #{ > -> stmt } was an expression. A missing or extra semicolon could even change > overload resolution! The new syntax uses { } to distinguish statement > lambdas, which is perfectly sensible to me. > > Using the new syntax, I went through several phases of using extra > parentheses in order to highlight the lambda, but I eventually pulled them > all out. You can see the results in the code: there are very few places with > parentheses where they aren't required. It's a bit unfortunate that the > nilary lambda requires an empty pair of parens, but (as others have noted) > making them optional seems to introduce a bunch of problems and special > cases, and having them isn't really all that bad, so why not just live with > them. > > s'marks > From brian.goetz at oracle.com Fri Sep 30 17:25:37 2011 From: brian.goetz at oracle.com (Brian Goetz) Date: Fri, 30 Sep 2011 20:25:37 -0400 Subject: Syntax decision In-Reply-To: References: <4E8556E7.2020206@gmail.com> <4E863CEF.6000005@oracle.com> Message-ID: <4E865E01.9030900@oracle.com> > Arguably Java method declaration syntax is weird too: > name(args){body} > for anyone new to programming. But the syntax has been in mainstream > for 4 decades, so everybody is accustomed to it. That's why I don't > really understand why the strawman syntax, closest to method > declaration, is killed; I read the archive and couldn't find any > objection to it. (I have no intention to argue about syntax, just > curious to learn what's wrong with strawman syntax; ignore me if you > would) The only thing going for the strawman syntax was that if you squinted and pronounced # as "method", it looked like the method declaration syntax. But, it was broadly hated for so many reasons, including: - Some people just hated the #, it felt like being hit over the head with a hammer labeled "watch out, something new and different here!" - Some people had a hard time seeing #(x)(x) as one expression, rather than two - Visual confusion with casts. While all the options had supporters and detractors, strawman elicited the strongest negative reaction from its detractors. If you look at the "too terse and too alien" thread from June 2010, you'll see some initial reactions from this group. While people later softened their stance (likely through familiarity), the negative reactions were just too strong. Basically, while it might have been the most "logical" syntax, we're not logical beings. From neal at gafter.com Fri Sep 30 17:58:14 2011 From: neal at gafter.com (Neal Gafter) Date: Fri, 30 Sep 2011 17:58:14 -0700 Subject: Syntax decision In-Reply-To: References: Message-ID: On Fri, Sep 30, 2011 at 3:18 PM, Pavel Minaev wrote: > Note that most such special cases also have 1) a single lambda that 2) > occurs in the final argument position. So I think that this is an argument > for some kind of syntactic sugar akin to what Ruby has - where you can > write: > > foo.bar(1, 2, 3) {|x,y,z| ...} > > instead of: > > foo.bar(1, 2, 3, {|x,y,z| ...}) > > i.e. moving the lambda outside the parentheses, and making it look more > like > a statement with a body than a function call. > > I don't think this is something worth pursuing for the first version, > though. ()->{} is good enough in practice, and extra syntactic sugar can > always be slapped on top when and if needed. Without control transparency (which Ruby has), this would create a brand new world of confusion. From int19h at gmail.com Fri Sep 30 18:19:31 2011 From: int19h at gmail.com (Pavel Minaev) Date: Fri, 30 Sep 2011 18:19:31 -0700 Subject: Syntax decision In-Reply-To: References: Message-ID: Yes, this would require proper treatment, similar to what is there in CfJ 0.6b. On Fri, Sep 30, 2011 at 5:58 PM, Neal Gafter wrote: > On Fri, Sep 30, 2011 at 3:18 PM, Pavel Minaev wrote: > >> Note that most such special cases also have 1) a single lambda that 2) >> occurs in the final argument position. So I think that this is an argument >> for some kind of syntactic sugar akin to what Ruby has - where you can >> write: >> >> foo.bar(1, 2, 3) {|x,y,z| ...} >> >> instead of: >> >> foo.bar(1, 2, 3, {|x,y,z| ...}) >> >> i.e. moving the lambda outside the parentheses, and making it look more >> like >> a statement with a body than a function call. >> >> I don't think this is something worth pursuing for the first version, >> though. ()->{} is good enough in practice, and extra syntactic sugar can >> always be slapped on top when and if needed. > > > Without control transparency (which Ruby has), this would create a brand new world of confusion. > > >