Hi John, 
it's perhaps me, but i think that Kevin saying that he wants to discourage side 
effects, not disable them, avoiding side effects like it.next() is not possible 
in Java. 

We already have this kind of discussion when we have discussed about lambdas, 
lambdas allow side effects but it's discouraged to use lambdas for that. 
And We already have agree that case expressions do not need to capture 
variables, so expression in a case are like expressions in a ?:, you can do 
side effect in them but it's discouraged. 

Rémi 

> De: "John Rose" <john.r.r...@oracle.com>
> À: "Kevin Bourrillion" <kev...@google.com>
> Cc: "amber-spec-experts" <amber-spec-experts@openjdk.java.net>
> Envoyé: Mardi 13 Mars 2018 22:21:37
> Objet: Re: expression switch vs. procedural switch

> On Mar 13, 2018, at 1:02 PM, Kevin Bourrillion < [ mailto:kev...@google.com |
> kev...@google.com ] > wrote:

>> The more I have thought about it, the more I believe that 95% of the entire
>> value of expression switch is that it isn't procedural switch , and is easier
>> to reason about than procedural switch because of all things it can't do:

>>     * can't miss cases
>>     * can't return
>>     * can't break/continue a containing construct
>>     * can't fall through
>>     * (for constants or other disjoint patterns) can't depend on the order 
>> of cases.

>> As far as I can tell, its limitations are exactly what make it useful. (It 
>> isn't
>> really a large savings of code bulk, and it's not that we really want to see
>> switches appearing in expression contexts in general besides the key ones 
>> `var
>> = ??` and `return ??`.)

>> I also believe that all these limitations work to support the notion that an
>> expression switch is functional in nature. It is a function defined "in 
>> parts"
>> (and immediately executed). As such, I believe we should discourage using
>> expression switch in side-effecting ways. More to the point, I suggest that
>> side-effecting use cases should not be seen as especially motivating for our
>> design decisions (see e.g. my message 30 minutes ago in "break seen as a C
>> archaism").

> These are all real issues but they don't all cut so uniformly in
> the direction you are seeking to uphold. I would refactor your
> list as:

> A. must complete with a value or throw; cannot complete with control flow
> (covers return/break/continue)
> B. is exhaustive (can't miss cases, can't fall through)
> C. when patterns are disjoint, case order is insignificant
> D. acts like a lambda body (is functional, no external side effects)

> For expression switches, A is truly a unique requirement. In Java expressions
> cannot complete with a branch; they must complete with a value or throw.
> I don't think any of us want to add a new kind of expression which suddenly
> can branch to a visible label or return, without the help of an enclosing 
> branch
> statement. As for statements, they can branch, within limits (lambda bodies
> and method bodies).

> B is a requirement that is necessary for expression switches also, but it is
> also a desirable property of *some* statement switches. So there's some
> design work to do motivated by e-switches that will benefit s-switches.
> I'm thinking in particular of some simple way to certify that a switch
> (either kind) is intended to be exhaustive, asking the static and runtime
> systems to give suitable diagnostics if that ever fails.

> (Or is "fallthrough" the phenomenon where several case labels converge
> to one statement? I am doubtful that is what you mean because it seems
> expression switches are very likely to need to reply to several target
> values with one expression, just as with statement switches.)

> C is a tautology, so I'm not sure what it tells us. Are you saying that
> order-invariance is an important property for expressions but not
> statements? When we get to overlapping case labels (patterns)
> they will be equally welcome in s-switches and e-switches.

> D is an extension of A, upgrading the branch-free property to the
> absence of all side effects, making s-switches like lambdas. I do
> *not* think this is a realistic goal, not even for a highly disciplined
> shop like Google. Why? Because in Java expressions have lots
> of side effects. Consider:

> Object x = i < len ? a[i++] : null;
> Object x = it.hasNext() ? it.next() : null;

> Those expressions are two-branch conditionals (disguised
> if-statements) with side effects. They are not "functional" in any
> robust sense (the iterator is a shallow container for non-functional
> state just like a and i++).

> As soon as you have more than two branches to your conditional,
> you want a switch expression, and it may very well operate on
> ambient state, just like many other Java expressions:

> Object x = switch (len - i) {
> case 0 -> null;
> case 1 -> a[i++];
> default:
> case 2 -> (a[i++] << 8) + a[i++];
> };

> The way I see it, D is undesirable, A is necessary to the physics
> of expressions but doesn't tell us anything about the nature of
> e-switch, and B and C apply to both kinds of switches. So
> there's nothing here that teaches us to treat e-switch as
> something with its own special mission defined by its limitations.

> Instead, I very much believe in Brian's design heuristic of
> running a refactoring exercise over switch use cases, to make
> sure that there is (when possible) an easy transition between
> s-switch and e-switch. The effect of this heuristic is to keep
> both switches aligned in their capabilities (where physics allow)
> lowering the learning burden, and making it easy for programmers
> to convert between the forms as needs and tastes require.

> — John

Reply via email to