My lambda leftovers

forax at univ-mlv.fr forax at univ-mlv.fr
Mon Oct 9 14:08:41 UTC 2017


----- Mail original -----
> De: "Maurizio Cimadamore" <maurizio.cimadamore at oracle.com>
> À: forax at univ-mlv.fr
> Cc: "Brian Goetz" <brian.goetz at oracle.com>, "Tagir Valeev" <amaembo at gmail.com>, "amber-spec-experts"
> <amber-spec-experts at openjdk.java.net>
> Envoyé: Lundi 9 Octobre 2017 12:38:58
> Objet: Re: My lambda leftovers

> 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 = 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.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