break seen as a C archaism
Peter Levart
peter.levart at gmail.com
Fri Mar 16 08:50:29 UTC 2018
Hi,
May I jump in as an outsider and someone who's just using the language...
On 03/15/18 22:58, John Rose wrote:
> On Mar 15, 2018, at 2:13 PM, Maurizio Cimadamore
> <maurizio.cimadamore at oracle.com
> <mailto:maurizio.cimadamore at oracle.com>> wrote:
>>
>> So, from a language design perspective, 'return x' is wrong - but, as
>> you point out, we already committed the original sin of having
>> 'return == local return' for lambdas, so I'm not too convinced that
>> we couldn't use the same story again here. E.g. when you say
>> 'return', what you really mean is 'returning from the innermost
>> context'. This could be a method (as usual), or a nested expression
>> e.g. a lambda or a switch expression.
>>
>>
> We have method bodies and lambda bodies on one hand,
> and we have switches and loops on the other.
Yes, and my intuitive distinction between those two kinds of constructs
is that the first are just "declarations" of code blobs, while the
second are code blobs that execute in-line with the surrounding code. It
is therefore very intuitive for me to have two kinds of syntax for
exiting the constructs - "return" for the first and "break" for the second.
I don't know why others find break so archaic. When I 1st saw this
proposal, I thought that break was very intuitive choice for e-switch.
>
> We use return to escape from the former, and break to
> escape from the latter.
>
> Note that return may or may not take an expression,
> while break never does, at present.
>
> So far so good. Now we stir in expression switches.
> Which side of the fence do they belong on?
>
> It seems to me that your position needs to argue
> that e-switches belong with methods and lambdas,
> because only return can take an expression.
> If you can pull this off, then break doesn't need
> to take an expression.
>
> Likewise, my position need to argue that giving "break" an
> expression is reasonable. I don't need to argue
> that expression switches are similar to legacy
> switches. (But I'm trying to spike the argument
> that it's hard to unify e-switches and s-switches,
> so let's just fork the language with a new switch-like
> feature for expressions.)
>
> But there are two reasons why e-switch doesn't
> belong with method body and lambda body,
> a shallow but strong one, and a deep one.
>
> Shallow but strong: e-switches are obviously switches.
>
> Deep: Lambda bodies and method bodies execute
> in their own stack frames. Any up-level references
> must be to final locals (or fields). Lambda bodies
> and methods can execute at most one "return",
> which tears down their frame. Expressions,
> including expression switches, execute in the
> frame of the containing lambda body or method
> and can read *and write* local variables.
> Expressions are inherently local to a frame
> and can imperatively side effect it.
That's another, more technical way of saying: methods and lambdas are
declarations of code, switches and loops are in-line constructs that
execute "immediately" in the surrounding context. Lambdas do "capture"
surrounding context, but they don't execute in it (they can't modify
locals, do long returns etc.).
Speaking of long returns...
If return was used for "yielding" a result from e-switch, how is one
supposed to do a return from a method inside the e-switch:
int m(int x) {
int y = switch (x) {
case 1: return 12; // I want to return from m() here!
}
}
>
> A "return" which in some contexts keeps the
> stack frame and jumps somewhere is a weaker
> return than today's return. (Weaker meaning
> less can be concluded by observing it in code.)
>
> So I can't group e-switch cases with lambda bodies.
> I know some have performed this feat to their own
> satisfaction, but it's hard for me, in a way that
> seems deeper than just learning curve.
>
> By now we recognize that adding an expression
> to "break" is no big deal; it's a new overloading.
> I agree that it is open to the accusation that it's not
> thrifty, that "return" already does that job.
> But it seems to me the shallow and deep points
> above answer the accusation.
>
> For me, the cost of making "break" do a new
> trick is paid for by the benefit of not inventing
> a new switch-like expression (like ?: for if/else),
> and not having to weaken "return".
>
> — John
I totally agree. There are some caveats though. What to do in situations
like this, for example:
int var_or_label = 13;
int y = switch (x) {
case 1:
var_or_label: {
break var_or_label;
}
// do we reach here?
};
The standard means that Java took to avoid ambiguities caused by new
features was to prioritize old behavior (varargs for example). In above
sample, label would take precedence. It is easy to choose the var:
break (var_or_label);
And now for something completely different...
I think that with introduction of e-switch, we might soon see it being
"abused" for things like:
doSomething(
par1,
switch (1) { case 1:
// compute result...
break resut;
},
par3
);
Are there any plans for such construct "without the boilerplate" ?-)
Among existing reserved words, "do" seems most appropriate:
doSomething(
par1,
do {
// compute result...
break resut;
} while (false),
par3
);
And if "while (false)" could be optional, we get:
doSomething(
par1,
do {
// compute result...
break resut;
},
par3
);
Combining with lambdas, we get 3 ways to do the same thing:
x -> y
x -> { return y; }
x -> do { break y; }
Regards, Peter
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/amber-spec-experts/attachments/20180316/d11906a7/attachment.html>
More information about the amber-spec-experts
mailing list