My lambda leftovers

forax at univ-mlv.fr forax at univ-mlv.fr
Mon Oct 9 09:32:26 UTC 2017


There is plenty of types that are only know by the compiler, so i don't think it's a real issue.

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.

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