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