My lambda leftovers

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Mon Oct 9 10:38:58 UTC 2017



On 09/10/17 10:32, forax at 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 = throws xyz

:-)
>
> 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').

Maurizio
>
> Rémi
>
> ----- Mail original -----
>> De: "Maurizio Cimadamore" <maurizio.cimadamore at oracle.com>
>> À: "Brian Goetz" <brian.goetz at oracle.com>, "Tagir Valeev" <amaembo at gmail.com>, "Remi Forax" <forax at univ-mlv.fr>
>> Cc: "amber-spec-experts" <amber-spec-experts at 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 <forax at 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



More information about the amber-spec-experts mailing list