----- Mail original ----- > De: "Maurizio Cimadamore" <maurizio.cimadam...@oracle.com> > À: fo...@univ-mlv.fr > Cc: "Brian Goetz" <brian.go...@oracle.com>, "Tagir Valeev" > <amae...@gmail.com>, "amber-spec-experts" > <amber-spec-experts@openjdk.java.net> > Envoyé: Lundi 9 Octobre 2017 12:38:58 > Objet: Re: My lambda leftovers
> On 09/10/17 10:32, fo...@univ-mlv.fr wrote: >> There is plenty of types that are only know by the compiler, so i don't think >> it's a real issue. > Heh - until the compiler 'throws' them into your face with a diagnostic. > Also: > > var x = throw xyz > > :-) the other solution is to said that the typecheking of 'throw Foo' as an expression is equivalent to typecheck a call to a method <any V> V throwMethod() throws Foo. >> >> There is another issue >> { >> throw ...; >> } >> as now two possible representations in term of parser tree (the throw as >> statement or throw as exception + expression statement), given that the Tree >> is >> visible in term of API, that's why i have limited the proposal to throw >> inside >> a lambda. > Well, yes, the AST would change a bit, but the API exposing ASTs is > compiler-specific (for method bodies at least) so it's not a big big big > constraint. We're considering similar small tweaks for switch and > patterns, where we're revamping the AST of a case so that the case > expression will become a pattern (which can be a constant pattern in > which case you get the old good 'case'). yes, very true. > > Maurizio Rémi >> >> Rémi >> >> ----- Mail original ----- >>> De: "Maurizio Cimadamore" <maurizio.cimadam...@oracle.com> >>> À: "Brian Goetz" <brian.go...@oracle.com>, "Tagir Valeev" >>> <amae...@gmail.com>, >>> "Remi Forax" <fo...@univ-mlv.fr> >>> Cc: "amber-spec-experts" <amber-spec-experts@openjdk.java.net> >>> Envoyé: Lundi 9 Octobre 2017 11:02:26 >>> Objet: Re: My lambda leftovers >>> While I sympathize with the proposal, I think making 'throw' an >>> expression is trickier than it seems; in Java expression have types - if >>> we make 'throw' an expression, then we must state what type does it >>> have. In Scala the Nothing type is used for this purpose; Java doesn't >>> have such a type. This is evident in cases like this: >>> >>> <Z> m(Z z) { ... } >>> >>> m(throw xyz) >>> >>> So, while I agree this would be a nice-to-have from an usability >>> perspective, this feature has a cost w.r.t. type system - e.g. it's not >>> a simple toggle flag on the parser. >>> >>> Maurizio >>> >>> >>> >>> On 08/10/17 22:54, Brian Goetz wrote: >>>> +1. >>>> >>>> On 10/6/2017 7:51 AM, Tagir Valeev wrote: >>>>> Hello! >>>>> >>>>> As for throw, I think it should just be converted to an expression, >>>>> probably of the same type as a null literal (thus throw statement will >>>>> become an expression statement). In this case it could be useful not >>>>> only in lambdas, like: >>>>> >>>>> return list.isEmpty() ? throw new NoSuchElementException() : >>>>> list.get(0); >>>>> >>>>> I believe, it was discussed in context of pattern matching. >>>>> >>>>> With best regards, >>>>> Tagir Valeev. >>>>> >>>>> On Fri, Oct 6, 2017 at 6:16 PM, Remi Forax <fo...@univ-mlv.fr> wrote: >>>>>> Hi all, >>>>>> The JEP 302 list some improvements but I think some are missing, >>>>>> obviously, it's up to debate :) >>>>>> >>>>>> So here is my list of left leftovers: >>>>>> - support throw statement as a lambda expression >>>>>> >>>>>> I think we have already discussed informally about this one. >>>>>> The compiler should allow to have a lambda expression that starts >>>>>> with throw. >>>>>> >>>>>> so a code like this will become valid >>>>>> merge(key, value, (_, _) -> throw new IllegalStateException("key >>>>>> " + key + " already present)); >>>>>> >>>>>> >>>>>> - allow void to be converted to Void (by returning null) >>>>>> >>>>>> This proposal is perhaps more controversial, currently there is >>>>>> no way to simply convert a lambda statement to a lambda expression. >>>>>> So a code like will compile >>>>>> >>>>>> <T, R> R sync(T initial, Function<? super T, ? extends R> fun) { >>>>>> synchronized(lock) { >>>>>> return fun.apply(initial); >>>>>> } >>>>>> } >>>>>> >>>>>> Consumer<String> c = System.out::println; >>>>>> sync("foo", c::accept); // the compiler should generate a >>>>>> synthetic static method that returns null >>>>>> >>>>>> This proposal is problematic because: >>>>>> - it implicitly produces a null, which is a bad idea >>>>>> - if there are several overloads, a lambda statement can now >>>>>> match more methods so the compiler may reject code that was >>>>>> previously working or worst call another method that the one that >>>>>> was originally selected. >>>>>> >>>>>> >>>>>> The other question is should the conversion be extended to work >>>>>> with non lambda code, >>>>>> i.e. consider that 'return' or an implcit 'return' can be >>>>>> trasformed to a return null by the compiler. >>>>>> >>>>>> Void m() { >>>>>> return; // the compiler generates return null; >>>>>> } >>>>>> >>>>>> Void m() { } // the compiler generates return null; >>>>>> >>>>>> >>>>>> On the positive side, it mix well with the switch expression >>>>>> proposed in the Pattern Matching JEP. >>>>>> >>>>>> Supplier<Void> supplier = >>>>>> () -> switchexpr(someValue) { >>>>>> case 0 -> System.out.println("foo"); >>>>>> default -> { /* empty */ } >>>>>> }; >>>>>> >>>>>> >>>>>> regards, >>>>>> Rémi >>>>>> > >>>>> [1] http://openjdk.java.net/jeps/302