<p>After upgrading to Java 21, I realized that the promised switch expression has several surprising properties. The most surprising part is the <code>yield</code> keyword which must be inserted if a block is used in a branch. Like in</p>
<pre><code>int x = switch (y) {
   ...
   case 7 -&gt; {
     assert ...;
     8; // this is not allowed; a yield must be added in front
   }
};
</code></pre>
<p>While digging for a reason, I found <a href="https://openjdk.org/jeps/354" rel="noreferrer">JEP 354</a> which apparently introduced the syntax. Now, the obscure part is, that the very last paragraph of that documents indicates that such a move would be a bad idea. Are there any insights, why this contradiction was ignored and the <code>yield</code> syntax was introduced? Are there any reasons that would prevent using either a break expr syntax or having expressions at the end of a block in that context as a result?</p>

<syntax><implementation><history><syntactic-sugar><backwards-compatibility>
What's the rationale behind switch/yield in Java?
CC BY-SA 4.0
2024-07-27T13:03:32.387Z
Maybe a second question: Are there any ambiguities preventing an IDE from just inserting the yield as a quick fix? Since return also doesn't seem to be allowed there are only obscure other alternatives.
feldentm
CC BY-SA 4.0
2024-07-27T21:53:22.890Z
`break expr` seems to conflict with ordinary labelled break statements, so if anything it's more surprising that it made it *into* JEP 325 than that it wasn't used in the end.
Michael Homer
CC BY-SA 4.0
2024-07-27T22:00:29.630Z
“the very last paragraph of that documents indicates that such a move would be a bad idea.” I don’t understand this sentence. What paragraph are you referring to? What do you mean by “such a move”? I looked at JEP 354, and I have no idea what you’re talking about.
Alexis King
CC BY-SA 4.0
2024-07-28T06:17:12.020Z
@AlexisKing "The greater the divergence between switch..."; it's actually what made me ask this question, because it literally took me 15min to figure what all the error messages meant. It feels as if they have taken a complex route that is also different to what most others did if I'm not mistaken.
feldentm
CC BY-SA 4.0
2024-07-28T06:18:53.543Z
@MichaelHomer wouldn't there be an easy fix by adding braces and extending the break label code to hint that a brace might be required if this really is ambiguous?
feldentm
CC BY-SA 4.0
2024-07-29T16:31:27.600Z
Why would it be a bad idea? It's just like Java doesn't automatically return the result of the last expression in a function but rather requires the "return" keyword to indicate that it is being returned.
Criticize SE actions means ban
CC BY-SA 4.0
2024-07-30T14:45:55.767Z
If they have to add a new keyword, how can it be in line with what existed otherwise?
feldentm
<p>It’s more to do with precedent elsewhere in the language than any technical difficulties.</p>
<p>Like most Algol descendants, Java maintains the somewhat artificial distinction between expressions and statements, in which an expression can evaluate to a value, but a statement cannot, and even if an expression is allowed to appear where a statement is expected, its value is discarded.  A block of statements is considered a statement, so it would have been awkward to introduce a place where the value of an expression statement is <em>not</em> discarded and a block suddenly evaluates to a value on its own.  It’s not like functions return the last expression evaluated either.</p>
<p>But other design choices are possible.  In <s>JavaScript</s> ECMAScript, there is already some precedent for statement lists to evaluate to values as well – an <code>eval</code> call accepts a series of statements as a string and returns the value of the last expression statement evaluated, so perhaps it would have been an easier pill to swallow.  In fact, in the <a href="https://github.com/tc39/proposal-do-expressions" rel="nofollow noreferrer"><code>do</code> expressions proposal</a> which would bridge the gap between statements and expressions, implicitly returning the last evaluated expression is currently one of the contenders, although it has some disadvantages and other possibilities are still being explored.</p>
<p>Languages like Scala and Rust eliminate a separate syntactic category of “statements” entirely: even constructs that are executed only for their side effects have a return type (though sometimes it may be a unit type or an empty type, when there is nothing to be returned), while blocks are <em>expressions</em> that evaluate to their last value.  This means that blocks in <code>match</code> expression arms work exactly as in your <a href="/q/3974/799#comment12911_3979">somewhat perverted proposal</a>:</p>
<pre class="lang-scala prettyprint-override"><code>val x = y match {
   ...
   case 7 =&gt; {
     assert(...)
     8 // this is allowed; suck it, Java
   }
};
</code></pre>

CC BY-SA 4.0
2024-12-27T11:52:28.257Z
2024-12-27T11:52:28.257Z
user3840170
<p>It's more consistent to require the <code>yield</code> keyword than for it to be auto-inserted into the final expression.  Consider the need to differentiate between the following two cases:</p>
<pre><code>//Version 1
default -&gt; {
    if(cond) {
        z=0;
    }
    yield 15;
}

//Version 2
default -&gt; {
    if(cond) {
        yield z=0;
    }
    yield 15;
}
</code></pre>

CC BY-SA 4.0
2024-07-29T20:46:01.687Z
2024-07-29T20:46:01.687Z
Brian
CC BY-SA 4.0
2024-07-30T14:49:52.620Z
Yes, but you could equally do it by exchanging yield with break and reuse the existing keyword. Modulo ambiguity with break label expressions. My somewhat perverted proposal would be to leave out the ';' because it must be at the end of a block anyway.
feldentm
CC BY-SA 4.0
2024-07-30T17:24:41.297Z
@feldentm: I'll note that the very bottom of the JEP contrasts switch statements (default fall-through) with switch expressions.  I think being a bit explicit about this contrast is necessary when you're working with two very similar constructs being available in the same language, especially given the possibility of refactoring from one to the other. That said, I'm only addressing your proposal to elide the keyword at the end of the block.
Brian
# What's the rationale behind switch/yield in Java?
Posted by: username_0 on 2024-07-27
After upgrading to Java 21, I realized that the promised switch expression has several surprising properties. The most surprising part is the yield keyword which must be inserted if a block is used in a branch. Like in
int x = switch (y) {
   ...
   case 7 -> {
     assert ...;
     8; // this is not allowed; a yield must be added in front
   }
};

While digging for a reason, I found JEP 354 which apparently introduced the syntax. Now, the obscure part is, that the very last paragraph of that documents indicates that such a move would be a bad idea. Are there any insights, why this contradiction was ignored and the yield syntax was introduced? Are there any reasons that would prevent using either a break expr syntax or having expressions at the end of a block in that context as a result?
**Tags:** syntax implementation history syntactic-sugar backwards-compatibility
> **Comments:**
> **username_0**: Maybe a second question: Are there any ambiguities preventing an IDE from just inserting the yield as a quick fix? Since return also doesn't seem to be allowed there are only obscure other alternatives.  
> **username_1**: `break expr` seems to conflict with ordinary labelled break statements, so if anything it's more surprising that it made it *into* JEP 325 than that it wasn't used in the end.  
> **username_2**: “the very last paragraph of that documents indicates that such a move would be a bad idea.” I don’t understand this sentence. What paragraph are you referring to? What do you mean by “such a move”? I looked at JEP 354, and I have no idea what you’re talking about.  
> **username_0**: @AlexisKing "The greater the divergence between switch..."; it's actually what made me ask this question, because it literally took me 15min to figure what all the error messages meant. It feels as if they have taken a complex route that is also different to what most others did if I'm not mistaken.  
> **username_0**: @MichaelHomer wouldn't there be an easy fix by adding braces and extending the break label code to hint that a brace might be required if this really is ambiguous?  
> **username_3**: Why would it be a bad idea? It's just like Java doesn't automatically return the result of the last expression in a function but rather requires the "return" keyword to indicate that it is being returned.  
> **username_0**: If they have to add a new keyword, how can it be in line with what existed otherwise?  
---
## 2 answers
### Answer by username_4 on 2024-12-27. Score: 2
It’s more to do with precedent elsewhere in the language than any technical difficulties.
Like most Algol descendants, Java maintains the somewhat artificial distinction between expressions and statements, in which an expression can evaluate to a value, but a statement cannot, and even if an expression is allowed to appear where a statement is expected, its value is discarded.  A block of statements is considered a statement, so it would have been awkward to introduce a place where the value of an expression statement is not discarded and a block suddenly evaluates to a value on its own.  It’s not like functions return the last expression evaluated either.
But other design choices are possible.  In JavaScript ECMAScript, there is already some precedent for statement lists to evaluate to values as well – an eval call accepts a series of statements as a string and returns the value of the last expression statement evaluated, so perhaps it would have been an easier pill to swallow.  In fact, in the do expressions proposal which would bridge the gap between statements and expressions, implicitly returning the last evaluated expression is currently one of the contenders, although it has some disadvantages and other possibilities are still being explored.
Languages like Scala and Rust eliminate a separate syntactic category of “statements” entirely: even constructs that are executed only for their side effects have a return type (though sometimes it may be a unit type or an empty type, when there is nothing to be returned), while blocks are expressions that evaluate to their last value.  This means that blocks in match expression arms work exactly as in your somewhat perverted proposal:
val x = y match {
   ...
   case 7 => {
     assert(...)
     8 // this is allowed; suck it, Java
   }
};
---
### Answer by username_5 on 2024-07-29. Score: 0
It's more consistent to require the yield keyword than for it to be auto-inserted into the final expression.  Consider the need to differentiate between the following two cases:
//Version 1
default -> {
    if(cond) {
        z=0;
    }
    yield 15;
}

//Version 2
default -> {
    if(cond) {
        yield z=0;
    }
    yield 15;
}
> **Comments:**
> **username_0** (2024-07-30): Yes, but you could equally do it by exchanging yield with break and reuse the existing keyword. Modulo ambiguity with break label expressions. My somewhat perverted proposal would be to leave out the ';' because it must be at the end of a block anyway.  
> **username_5** (2024-07-30): @feldentm: I'll note that the very bottom of the JEP contrasts switch statements (default fall-through) with switch expressions.  I think being a bit explicit about this contrast is necessary when you're working with two very similar constructs being available in the same language, especially given the possibility of refactoring from one to the other. That said, I'm only addressing your proposal to elide the keyword at the end of the block.  
---
