From dtrebbien at gmail.com Sat Nov 11 14:52:06 2017 From: dtrebbien at gmail.com (Daniel Trebbien) Date: Sat, 11 Nov 2017 08:52:06 -0600 Subject: Fwd: JEP 305: Forcing a pattern match In-Reply-To: References: Message-ID: Working on a particular file in Apache NetBeans' source repository, I came across the following code: for (Tree member : node.getMembers()) { if (member.getKind() == Kind.BLOCK) { if (((BlockTree) member).isStatic()) { staticInitializers.add(member); } else { instanceInitializers.add(member); } } else if (member.getKind() == Kind.VARIABLE && ((VariableTree) member).getInitializer() != null) { if (((VariableTree) member).getModifiers(). getFlags().contains(Modifier.STATIC)) { staticInitializers.add((VariableTree) member); } else { instanceInitializers.add((VariableTree) member); } } else if (isConstructor(new TreePath(getCurrentPath(), member))) { constructors.add((MethodTree) member); } else { others.add(member); } } With respect to the first else if, notice that there are four casts of member to VariableTree. It turns out that the last two casts are not necessary, but let's pretend that they are for a moment. I think that it would be useful to be able to define a new variable to hold the result of casting member to VariableTree, whose scope is restricted to the else if. With JEP 305 , this can be accomplished via a matches expression, as in: for (Tree member : node.getMembers()) { if (member.getKind() == Kind.BLOCK) { if (((BlockTree) member).isStatic()) { staticInitializers.add(member); } else { instanceInitializers.add(member); } } else if (member.getKind() == Kind.VARIABLE && member matches VariableTree varMember && varMember.getInitializer() != null) { if (varMember.getModifiers().getFlags().contains(Modifier.STATIC)) { staticInitializers.add(varMember); } else { instanceInitializers.add(varMember); } } else if (isConstructor(new TreePath(getCurrentPath(), member))) { constructors.add((MethodTree) member); } else { others.add(member); } } However, the matches operator would perform an unnecessary instanceof check; here, we know that member is an instance of VariableTree. Perhaps another operator should be added, say asmatch, which would attempt to force the pattern match, without performing additional checks. In the case of a type test pattern, this would declare a variable set to a type cast. One quirk of such an operator is that it would always result in true. Any cases where the expression does not match the pattern would result in some runtime exception such as ClassCastException. From dtrebbien at gmail.com Sat Nov 25 03:58:36 2017 From: dtrebbien at gmail.com (Daniel Trebbien) Date: Fri, 24 Nov 2017 19:58:36 -0800 Subject: Proposal: single-expression method bodies In-Reply-To: References: Message-ID: Hello Zheka, I personally like your idea of supporting expression lambda syntax with methods. Being able to write simple getters as public int getSomeField() -> someField; would be very useful, in my opinion. I don't like the idea of expression lambda syntax support for switch cases, though, because I think that it wouldn't work well with fall-through support. By way of example, consider: String s = switch (o) { case Integer n: case Double n: return n.toString(); } (I believe that reusing bound variable names like this is anticipated to be supported, but I could be wrong.) Allowing expression lambda syntax with that might look like: String s = switch (o) { case Integer n -> case Double n -> n.toString(); } Or maybe: String s = switch (o) { case Integer n, case Double n -> n.toString(); } Or: String s = switch (o) { case Integer n, Double n -> n.toString(); } All three seem a bit strange and potentially confusing to me. Daniel On Wed, Nov 22, 2017 at 11:24 PM, Zheka Kozlov wrote: > Sorry if I'm repeating what was already discussed before. I didn't find > anything about this in the old threads. > > Currently, lambdas support two forms of bodies: > > 1. Function func = (Integer i) -> i.toString(); > 2. Function func = (Integer i) -> { > return i.toString(); > }; > > But for methods only the second form is supported: > > public String func(Integer i) { > return i.toString(); > } > > This seems unfair to me, and I think the first form should be supported > too: > > public String func(Integer i) -> i.toString() > > > Single-expression method bodies can reduce the amount of boilerplate: > > public static int square(int x) -> x * x > > // Simple getter > public int getSomeField() -> someField; > > > This will also be consistent with the two forms of switch (regular switch > and expression switch): > > switch (o) { > case Integer i: return i.toString(); > } > > vs. > > String s = switch (o) { > case Integer i -> i.toString(); > } > > What do you think? > From brian.goetz at oracle.com Mon Nov 27 15:08:59 2017 From: brian.goetz at oracle.com (Brian Goetz) Date: Mon, 27 Nov 2017 10:08:59 -0500 Subject: Proposal: single-expression method bodies In-Reply-To: References: Message-ID: <7228A205-C604-4F45-9F71-61AC7C221E6D@oracle.com> As a reminder, the spec-comments list is not for ongoing discussions; it is for self-contained comment submissions which are guaranteed to get to the attention of the Expert Group. Discussions can happen on amber-dev or amber-spec-observers. > On Nov 24, 2017, at 10:58 PM, Daniel Trebbien wrote: > > Hello Zheka, > > I personally like your idea of supporting expression lambda syntax with > methods. Being able to write simple getters as public int getSomeField() > -> someField; would be very useful, in my opinion. > > I don't like the idea of expression lambda syntax support for switch cases, > though, because I think that it wouldn't work well with fall-through > support. By way of example, consider: > > String s = switch (o) { > case Integer n: > case Double n: > return n.toString(); > } > > (I believe that reusing bound variable names like this is anticipated to be > supported, but I could be wrong.) > > Allowing expression lambda syntax with that might look like: > > String s = switch (o) { > case Integer n -> > case Double n -> n.toString(); > } > > Or maybe: > > String s = switch (o) { > case Integer n, > case Double n -> n.toString(); > } > > Or: > > String s = switch (o) { > case Integer n, Double n -> n.toString(); > } > > All three seem a bit strange and potentially confusing to me. > > Daniel > > On Wed, Nov 22, 2017 at 11:24 PM, Zheka Kozlov > wrote: > >> Sorry if I'm repeating what was already discussed before. I didn't find >> anything about this in the old threads. >> >> Currently, lambdas support two forms of bodies: >> >> 1. Function func = (Integer i) -> i.toString(); >> 2. Function func = (Integer i) -> { >> return i.toString(); >> }; >> >> But for methods only the second form is supported: >> >> public String func(Integer i) { >> return i.toString(); >> } >> >> This seems unfair to me, and I think the first form should be supported >> too: >> >> public String func(Integer i) -> i.toString() >> >> >> Single-expression method bodies can reduce the amount of boilerplate: >> >> public static int square(int x) -> x * x >> >> // Simple getter >> public int getSomeField() -> someField; >> >> >> This will also be consistent with the two forms of switch (regular switch >> and expression switch): >> >> switch (o) { >> case Integer i: return i.toString(); >> } >> >> vs. >> >> String s = switch (o) { >> case Integer i -> i.toString(); >> } >> >> What do you think? >> From pablogrisafi1975 at gmail.com Thu Nov 30 16:40:10 2017 From: pablogrisafi1975 at gmail.com (Pablo Grisafi) Date: Thu, 30 Nov 2017 13:40:10 -0300 Subject: Named parameters in data classes Message-ID: I don't know if this was already discussed, but it will be nice to have named parameters on data classes. I see a future with things like datum class Charges( BigDecimal gross; BigDecimal stateTaxes; BigDecimal federalTaxes; BigDecimal discount; ) become common, it will be really less error prone to write (and more clear to read) var charges = new Charges(gross = a, stateTaxes = b, federalTaxes = c,discount = BigDecimal.ONE) instead of var charges = new Charges(a, b, c,BigDecimal.ONE) I think (but I may be wrong) the main issue with named parameters is that they don't play well with inheritance, but since data classes will not have inheritance, it could be possible in this case Also, default values would also be nice to have datum class Charges( BigDecimal gross; BigDecimal stateTaxes; BigDecimal federalTaxes; BigDecimal discount = BigDecimal.ONE; ) and then var charges = new Charges(gross = a, stateTaxes = b, federalTaxes = c) Pablo Grisafi pablogrisafi1975 at gmail.com