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