Re: JEP325: Switch expressions spec
On 5/10/2018 10:36 AM, Dan Smith wrote: On May 10, 2018, at 6:28 AM, Gavin Biermanwrote: 15.29 "the switch expression completes normally": More conventionally, "the value of the switch expression is …" That phrase occurs in several places, so you’ll have to tell me which one you don’t like. "If execution of the Statement completes abruptly for the reason of a break with a value, then the switch expression completes normally with that value." I'd suggest changing to "for the reason of a break with a value _V_, then the value of the switch expression is _V_." For comparison, in all of Chapter 15, I only find four usages of the phrase "complete[s] normally". Lots of usages of "complete[s] abruptly", though. Switch _bodies_ are special, because they contain statements, so it makes sense to say "completes normally" here. But once we've left the body and we're talking about the switch expression as a whole, it's better to use the expression-oriented terminology. I agree that expressions completing normally has rarely been spelled out in Ch.15, and that the value resulting from evaluation of the expression is usually more interesting. However, JEP 325 is the first time that the JLS will explicitly pend an expression's evalation on a statement's completion. Usually it's the other way round, per 14.1: "If a statement evaluates an expression, abrupt completion of the expression always causes ...". And lambda expressions, with bodies containing statements, didn't need to do it explicitly in 15.27.2 or 15.27.4. So, since a value-break statement is a common way out of a switch expression, I would like the JLS to put the completes-abruptly side by side with a completes-normally. The abrupt completion of `break e;` is "swallowed" by the normal completion of the enclosing switch expression. (This appeals to the disrupted completion that `catch` and `finally` clauses arrange.) AND, the JLS should specify the value of the switch expression, based on evaluating the argument of the value-break statement, as you have proposed. Alex
Re: JEP325: Switch expressions spec
> On May 10, 2018, at 6:28 AM, Gavin Biermanwrote: > >> SwitchStatementClause is probably too general. I don't think we want to >> allow arbitrary statements to occur on the RHS without braces. It's unweildy >> (think about a chain of if-else, for example), inconsistent with others uses >> of "->", and ambiguous: does "case foo -> switch (expr) { ... }" describe a >> switch statement or a switch expression? > > Actually the opposite was argued for - that requiring braces would be too > much clutter. It is inconsistent with statement lambda though, as you point > out. Here's a roughly-prioritized list of reasons I think allowing an arbitrary statement after '->' is bad: - There's a grammatical ambiguity between "-> SwitchStatement" and "-> SwitchExpression" - It's inconsistent with SwitchExpression (which does not allow a statement after the arrow) - It allows lots of confusing constructs, like "case Foo -> bar: if (cond) m();" - It's inconsistent with LambdaExpression The last three are subjective complaints, YMMV. >> I also have concerns about the heavy duplication between the specs for >> switch statements and switch expressions. Wasn't this design motivated by >> wanting to have a single, unified construct packaged in expression and >> statement forms? > > At the time it was felt that the symmetry was not what was wanted. The new > forms of case labels would strongly push the user to the comma separated > form, rather than the multiple case label form. Allowing both forms seems > messy. But I think it’s a matter of taste. [You will have read Guy’s emails > on this elsewhere also.] Wrong dimension. I endorse separate arrow and colon switch body productions. I'm saying I'd like to avoid separate expression and statement switch body productions. >> With or without 'null', there's a good argument that the arrow clauses need >> a way to syntactically combine specific cases and 'default'. Where are we at >> on this? > > We’ve dropped null patterns for now. That's why I said "with or without 'null'". :-) I think people will miss "case 3, 4, default ->" (or the equivalent) if we don't give it to them, and maybe end up shifting to the colon body syntax as a workaround. It's not crucial, though. >> Throughout: for other specs, people have expressed interest in seeing a >> complete before-and-after diff. No shortcuts. (And they're probably >> right—it's a lot easier to see what's going on that way.) So any words that >> have been removed should be indicated explicitly as deletions, rather than >> just leaving the old words out and highlighting the new words as additions. > > I started with doing just the diff, but as so many changes were being made it > started looking rather unhelpful, so I went with the “here’s what the section > will look like” with the additions and deletions there. I tried to flag all > deletions - but sounds like I might have missed a few. Not clear to me what you mean by "just the diff" (maybe output from an automated tool?). What I'm describing is that while it's sometimes a helpful shortcut to do this: A **widget** is a kind of expression Readers want to see the removal, too: A ~~wingding~~ **widget** is a kind of expression Sometimes this gets fiddly, and I find it easiest to strikeout a whole sentence or paragraph, then insert the new and improved version, even though there are some shared words. So, yes, exercise editorial discretion in deciding how to present things. But a reader should be able to reconstruct the original section text using only what you've given them. >> 14.11: somewhat arbitrarily, '->' is considered an "operator" while ':' is >> considered a "separator". Should match that terminology. > > Where is ‘:’ called a separator? I used the word ‘operator’ which is the > terminology from JLS§3.12. I’d be happy to use other terminology (I wanted to > avoid saying token.) My mistake, I misread section 3.11. >> 14.11: Use of the term "pattern" is premature. These are really just >> ConstantExpressions (plus, maybe, null). As is, we have lots of undefined >> concepts: When is a pattern "assignment compatible with" a type? When does a >> pattern "have the same value" as another? > > Yes, I wanted to start weaving in pattern terminology ahead of time. On > reflection maybe it’s not the right thing to do. [As an aside, I think it’s > pretty obvious what the definition of the “undefined” concepts are. Don’t we > do a similar pun with constant expressions and expressions? For example, do > we define a notion of value for constant expressions distinct from > expressions?] Okay, fair. As long as "pattern" refers to a subset of "expression", maybe you can get away with that. >> 14.11 "A Java compiler is encouraged": after much discussion about >> exhaustiveness, I think the consensus is that we would very much not like >> for a Java compiler to do this. Silently doing nothing for
Re: JEP325: Switch expressions spec
> On May 10, 2018, at 11:03 AM, Guy Steelewrote: > > >> On May 10, 2018, at 10:11 AM, Brian Goetz wrote: >> >> This was the thinking behind UA1; that sometimes you were going to want to >> "fall into" an arrow case > > "What I propose IS NOT FALLTHROUGH!” he continues to howl into the darkness > (but otherwise keeps his mouth zipped, because he is done arguing** :-). Didn’t mean to step on that landmine; my comment was merely syntactic. > The introduction of patterns may disrupt that model. If so, so be it, but > that is a big-deal change, and it will need to be explained carefully. It does in at least one degree. Once you have nested patterns, or guards, or explicit `continue`, you need a way to “re-run” the switch starting somewhere other than the beginning.
Re: JEP325: Switch expressions spec
> On May 10, 2018, at 10:11 AM, Brian Goetzwrote: > > This was the thinking behind UA1; that sometimes you were going to want to > "fall into" an arrow case "What I propose IS NOT FALLTHROUGH!” he continues to howl into the darkness (but otherwise keeps his mouth zipped, because he is done arguing** :-). —Guy ** As promised, I will offer no further argument as to what syntax should be adopted (that's policy); but I will continue to proclaim firmly that multiple labels in a SwitchBlockStatementGroup are not, and never have been, an example of fallthrough (that’s a fact, supported by textual evidence in the JLS from the very beginning). Here’s why we (Bill Joy and I) did that: If you look at the underlying implementation in the JVM, when you use a “lookupswitch” instruction, if two int values happen to take you to the code for the same statement, then for either int value the lookup table takes you straight there; there is no “fallthrough” at the JVM level, and the terminology used in the source language documentation reflects that intent, the better to convey the intended execution and cost model. When you write “case 3: case 4: S” it means EXACTLY the same thing as “case 4: case 3: S” and ought to have exactly the same cost, no matter what the run-time distribution of occurrences of “3” and “4” as actual dispatch values. The labels “case 3:” and “case 4:” are co-equal labels of S. There is no extra execution step of any kind when the dispatch value equals the case label that happened to be written first, compared to what happens when the dispatch value equals the case label that happened to be written second. And of course the intent was that the same thing would be going on at the machine level: there would simply be a jump instruction to an address pulled from a table. The introduction of patterns may disrupt that model. If so, so be it, but that is a big-deal change, and it will need to be explained carefully.
Re: JEP325: Switch expressions spec
> On May 10, 2018, at 8:28 AM, Gavin Biermanwrote: > > >> On 9 May 2018, at 00:08, Dan Smith wrote: >> . . . >> 14.11: somewhat arbitrarily, '->' is considered an "operator" while ':' is >> considered a "separator". Should match that terminology. > > Where is ‘:’ called a separator? I used the word ‘operator’ which is the > terminology from JLS§3.12. I’d be happy to use other terminology (I wanted to > avoid saying token.) Section 3.11 lists the separators, which include ; and :: but NOT :. As Gavin points out, plain : is listed as an operator in Section 3.12. (It must be admitted that this distinction was originally somewhat arbitrary. Back in 1995, we listed plain : as an operator because it is part of the ternary operator ? :, even though it also functions more as a separator in constructions such as statement labels and case labels.) —Guy
Re: JEP325: Switch expressions spec
This was the thinking behind UA1; that sometimes you were going to want to "fall into" an arrow case, and one of the reasons that UA1 allowed mixing: case B: case L -> S; But, people hated that, so we went another way. As John points out, the one place where it gets ugly is "case null, default". Which we don't have to deal with yet, now that we've pushed case null onto the next switch bus. On 5/9/2018 10:43 PM, Guy Steele wrote: I completely agree with John’s careful analysis, including the more speculative parts about symbol connotations. I too find "case B -> case L -> S” distasteful. But on the other hand I also find ”case B: case L: S” distasteful. What I find acceptable is either case B -> case L -> S or case B: case L: S As a matter of style I strongly prefer the keyword “case” to appear only at the start of a line. This makes them easier to spot when reading code. What I am arguing for is to have a choice: when you want to put more than one pattern on a line, by all means use the keyword “case” just once and separate the patterns with commas. But if you want to string them out vertically, I would like to have the option of repeating the “case” keyword once per line, whether using colons or arrows. And I argue that the latter style leads to more readable code in the “case null / default” situation; I prefer case null -> default -> E to case null, default -> E because I don’t like to bury that “default” keyword—I think it merits the same start-of-line visibility as the “case” keyword. In addition, it really bugs me to treat “default” as if it were syntactically a pattern—it isn’t. However, if others prefer "case null, default -> E”, I would be okay with supporting that also. But I would not want to write it. There is a tension or tradeoff between (a) the difference in connotations of arrow and colon, and (b) the simplicity of the theory that in principle they are more or less interchangeable syntactically, and we should make conversion from one to the other as easy as possible. I may value (b) more than other people do. And now, having laid out my complete case (so to speak), I think I am done with arguing this, and am perfectly prepared to be outvoted or overruled. —Guy On May 9, 2018, at 10:20 PM, John Rosewrote: A quick $0.02 on one bit of the switch syntax-alooza: I tried hard to like Guy's theory that -> and : are two flavors of the same SwitchLabel syntax. It is the most economical way to spread the good parts from colonform to arrowform, including the need (on occasion) to label one of the switch clauses as the "default", even while it *also* has a "case N". But I agree with others who find it too strange looking. If we can't buy Guy's clean syntax idea, we *do* need an ad hoc way to combine multiple cases in arrowform and an *even more* ad hoc way to fold in "default". And of all the possibilities, I think Brian's (below) is the least surprising and most acceptable. Please, let's not drop the ball and damage arrowform clauses by forbidding multiple ClauseLabel inputs for them. Here's my take on formalizing Brian's suggestion: CasePattern: case Pattern { , Pattern } [ , default ] default (Note that default comes last in the CasePattern, no matter what.) That's $0.0199. The rest of it is why I think I can't like Guy's proposal. The colonform and arrowform just look too different; colons and arrows have drastically different connotations. Arrow says "go from here to there" (e.g., from lambda parameter to lambda result). Colon says, "I'm telling you something about the following thing." Chained arrows seem to say something like "I'm going to breakfast, then to lunch, then to supper", not "red and blue are the colors of this shoe", as colons would. I know that's really subjective, but I think *something* like that, some folk model or perception, is behind people's distaste for "case B -> case L -> S" when the same people are content with "case R: case B: S". It's not that arrow is heavier than colon, exactly; it's that arrow really means something different than colon. At least, arrow and colon differ in the context of Java. In some parts of some languages "a:b" does mean "from a to b". But in those places "a:b:c" doesn't mean "from a or b to c" as in Java. In any case, "a -> b -> c" never means "from either a or b to c", as Guy's syntactic deductions would lead us to try in Java. — John On Apr 23, 2018, at 11:20 AM, Guy Steele wrote: I argue that there is no need to make the special-case exception for `default`. When you need to play that game (usually because null needs to be addressed), you cannot use the comma-separation syntax. Instead, just say either case null: default: s; (or, if you prefer, `default: case null: s;`) or case null -> default -> s;
Re: JEP325: Switch expressions spec
Hah! Yes, good catch. Let me think about this one. Thanks, Gavin > On 30 Apr 2018, at 17:13, Éamonn McManuswrote: > > I believe the grammar is ambiguous regarding `->`. If you have > case a -> b -> c > then in principle it could mean (1) when the selector expression equals `a` > the value is `b -> c`, or (2) when the selector expression equals `a -> b` > the value is `c`. Of course (2) is excluded semantically but I think it > could be excluded syntactically just by changing the definition of > ConstantExpression from > > ConstantExpression: > Expression > > to > > ConstantExpression: > AssignmentExpression > > On Fri, 27 Apr 2018 at 08:14, Gavin Bierman > wrote: > >> I have uploaded the latest draft of the spec for JEP 325 at > http://cr.openjdk.java.net/~gbierman/switch-expressions.html > >> Changes from the last version: >> * Supports new -> label form in both switch expressions and switch > statements >> * Added typing rules for switch expression >> * Restrict the type of a selector expression to not include long, double > and float as previously proposed >> * Misc smaller changes from community feedback (thanks!) > >> Comments welcomed! >> Gavin > >>> On 12 Apr 2018, at 22:27, Gavin Bierman > wrote: >>> >>> I have uploaded a draft spec for JEP 325: Switch expressions at > http://cr.openjdk.java.net/~gbierman/switch-expressions.html >>> >>> Note there are still three things missing: >>> >>> * There is no text about typing a switch expression, as this is still > being discussed on this list. >>> * There is no name given for the exception raised at runtime when a > switch expression fails to find a matching pattern label, as this is still > being discussed on this list. >>> * The spec currently permits fall through from a "case pattern:” > statement group into a "case pattern ->" clause. We are still working > through the consequences of removing this possibility. >>> >>> Comments welcomed! >>> Gavin
Re: JEP325: Switch expressions spec
[Apologies for slow reply. Now going through the latest batch of feedback.] Ack. Thanks. Gavin > On 27 Apr 2018, at 22:55, Alex Buckleywrote: > > On 4/27/2018 8:03 AM, Gavin Bierman wrote: >> I have uploaded the latest draft of the spec for JEP 325 at >> http://cr.openjdk.java.net/~gbierman/switch-expressions.html > > 14.16 is right to say that: > > A break statement with value Expression ***attempts to cause the > evaluation of the immediately enclosing switch expression*** > to complete normally ... > > because the following is legal (x will become 200) : > > int x = switch (e) { >case 1 -> { > try { break 100; } finally { break 200; } >} >default -> 0; > }; > > Therefore, in the discussion section, please say that: > > The preceding descriptions say "attempts to transfer control" > ***and "attempts to cause evaluation to complete normally",*** > rather than just "transfers control" ***and "causes evaluation > to complete normally",*** because if there are any try statements ... > > ... innermost to outermost, before control is transferred to the > break target ***or evaluation of the break target completes***. > > [Notice we don't yet know if evaluation of the break target > will complete normally or abruptly. If the finally clause above > was to throw an exception instead of break-200, then the > switch expression would complete abruptly by reason of the > exception, rather than completing normally with the value 100.] > > (Separately: Please flag the new text in 15.15's opening line.) > > Alex
Re: JEP325: Switch expressions spec
I completely agree with John’s careful analysis, including the more speculative parts about symbol connotations. I too find "case B -> case L -> S” distasteful. But on the other hand I also find ”case B: case L: S” distasteful. What I find acceptable is either case B -> case L -> S or case B: case L: S As a matter of style I strongly prefer the keyword “case” to appear only at the start of a line. This makes them easier to spot when reading code. What I am arguing for is to have a choice: when you want to put more than one pattern on a line, by all means use the keyword “case” just once and separate the patterns with commas. But if you want to string them out vertically, I would like to have the option of repeating the “case” keyword once per line, whether using colons or arrows. And I argue that the latter style leads to more readable code in the “case null / default” situation; I prefer case null -> default -> E to case null, default -> E because I don’t like to bury that “default” keyword—I think it merits the same start-of-line visibility as the “case” keyword. In addition, it really bugs me to treat “default” as if it were syntactically a pattern—it isn’t. However, if others prefer "case null, default -> E”, I would be okay with supporting that also. But I would not want to write it. There is a tension or tradeoff between (a) the difference in connotations of arrow and colon, and (b) the simplicity of the theory that in principle they are more or less interchangeable syntactically, and we should make conversion from one to the other as easy as possible. I may value (b) more than other people do. And now, having laid out my complete case (so to speak), I think I am done with arguing this, and am perfectly prepared to be outvoted or overruled. —Guy > On May 9, 2018, at 10:20 PM, John Rosewrote: > > A quick $0.02 on one bit of the switch syntax-alooza: > > I tried hard to like Guy's theory that -> and : are two flavors > of the same SwitchLabel syntax. It is the most economical > way to spread the good parts from colonform to arrowform, > including the need (on occasion) to label one of the switch > clauses as the "default", even while it *also* has a "case N". > But I agree with others who find it too strange looking. > > If we can't buy Guy's clean syntax idea, we *do* need an > ad hoc way to combine multiple cases in arrowform and > an *even more* ad hoc way to fold in "default". > And of all the possibilities, I think Brian's (below) is > the least surprising and most acceptable. Please, > let's not drop the ball and damage arrowform clauses > by forbidding multiple ClauseLabel inputs for them. > > Here's my take on formalizing Brian's suggestion: > > CasePattern: > case Pattern { , Pattern } [ , default ] > default > > (Note that default comes last in the CasePattern, no > matter what.) > > That's $0.0199. The rest of it is why I think I can't like > Guy's proposal. The colonform and arrowform just look > too different; colons and arrows have drastically different > connotations. Arrow says "go from here to there" (e.g., > from lambda parameter to lambda result). Colon says, > "I'm telling you something about the following thing." > Chained arrows seem to say something like "I'm going > to breakfast, then to lunch, then to supper", not > "red and blue are the colors of this shoe", as colons > would. > > I know that's really subjective, but I think *something* like > that, some folk model or perception, is behind people's > distaste for "case B -> case L -> S" when the same people > are content with "case R: case B: S". It's not that arrow > is heavier than colon, exactly; it's that arrow really means > something different than colon. > > At least, arrow and colon differ in the context of Java. > In some parts of some languages "a:b" does mean > "from a to b". But in those places "a:b:c" doesn't mean > "from a or b to c" as in Java. In any case, "a -> b -> c" > never means "from either a or b to c", as Guy's syntactic > deductions would lead us to try in Java. > > — John > > On Apr 23, 2018, at 11:20 AM, Guy Steele wrote: >> >> I argue that there is no need to make the special-case exception for >> `default`. When you need to play that game (usually because null needs to >> be addressed), you cannot use the comma-separation syntax. Instead, just >> say either >> >> case null: default: s; (or, if you prefer, `default: >> case null: s;`) >> >> or >> >> case null -> default -> s; (or, if you prefer, `default -> >> case null -> s;`) > > On Apr 20, 2018, at 11:40 AM, Brian Goetz wrote: >> >> One thing that is relevant to the short term is that now that we killed >> mixed labels, we'd have to have a way to say "case null or default" in arrow >> world. The least
Re: JEP325: Switch expressions spec
A quick $0.02 on one bit of the switch syntax-alooza: I tried hard to like Guy's theory that -> and : are two flavors of the same SwitchLabel syntax. It is the most economical way to spread the good parts from colonform to arrowform, including the need (on occasion) to label one of the switch clauses as the "default", even while it *also* has a "case N". But I agree with others who find it too strange looking. If we can't buy Guy's clean syntax idea, we *do* need an ad hoc way to combine multiple cases in arrowform and an *even more* ad hoc way to fold in "default". And of all the possibilities, I think Brian's (below) is the least surprising and most acceptable. Please, let's not drop the ball and damage arrowform clauses by forbidding multiple ClauseLabel inputs for them. Here's my take on formalizing Brian's suggestion: CasePattern: case Pattern { , Pattern } [ , default ] default (Note that default comes last in the CasePattern, no matter what.) That's $0.0199. The rest of it is why I think I can't like Guy's proposal. The colonform and arrowform just look too different; colons and arrows have drastically different connotations. Arrow says "go from here to there" (e.g., from lambda parameter to lambda result). Colon says, "I'm telling you something about the following thing." Chained arrows seem to say something like "I'm going to breakfast, then to lunch, then to supper", not "red and blue are the colors of this shoe", as colons would. I know that's really subjective, but I think *something* like that, some folk model or perception, is behind people's distaste for "case B -> case L -> S" when the same people are content with "case R: case B: S". It's not that arrow is heavier than colon, exactly; it's that arrow really means something different than colon. At least, arrow and colon differ in the context of Java. In some parts of some languages "a:b" does mean "from a to b". But in those places "a:b:c" doesn't mean "from a or b to c" as in Java. In any case, "a -> b -> c" never means "from either a or b to c", as Guy's syntactic deductions would lead us to try in Java. — John On Apr 23, 2018, at 11:20 AM, Guy Steelewrote: > > I argue that there is no need to make the special-case exception for > `default`. When you need to play that game (usually because null needs to be > addressed), you cannot use the comma-separation syntax. Instead, just say > either > > case null: default: s; (or, if you prefer, `default: > case null: s;`) > > or > > case null -> default -> s; (or, if you prefer, `default -> > case null -> s;`) On Apr 20, 2018, at 11:40 AM, Brian Goetz wrote: > > One thing that is relevant to the short term is that now that we killed mixed > labels, we'd have to have a way to say "case null or default" in arrow world. > The least stupid thing seems to be to allow default to be tacked on to a > comma-separated case list as if it were a pattern: > > case A -> s1; > case null, default -> s2; > > since you can no longer say: > > case A -> s1; > case null: > default: > s2; >
Re: JEP325: Switch expressions spec
Here are my notes from a pass over the spec. Significant items: --- SwitchStatementClause is probably too general. I don't think we want to allow arbitrary statements to occur on the RHS without braces. It's unweildy (think about a chain of if-else, for example), inconsistent with others uses of "->", and ambiguous: does "case foo -> switch (expr) { ... }" describe a switch statement or a switch expression? I also have concerns about the heavy duplication between the specs for switch statements and switch expressions. Wasn't this design motivated by wanting to have a single, unified construct packaged in expression and statement forms? Proposed fix: rename SwitchStatementBlock and SwitchExpressionBlock to a single SwitchBlock. Merge the two grammars, with SwitchClause being defined like SwitchExpressionClause, not SwitchStatementClause. Follow lambda expressions in stating a semantic rule that, in the statement form, the Expression be a StatementExpression. Discuss switch blocks in a subsection of 14.11 (maybe two subsections, for arrow and colon bodies, with a certain amount of sharing). Define matching, compile-time checks, and runtime behavior. (Like lambda expressions, the treatment of Expression clauses will be context-dependent.) The remaining spec for switch statements and switch expressions should be small. While we're at it, add 'throw' to the set of legal bodies for lambda expressions. (Or we can spin this off into a separate RFE, but I'd like to ship it in parallel.) --- After previous discussion about enum names, I think we should relax the requirement that an enum-typed switch must use (unqualified) enum constant names. The behavior I'd like is: if the type of the selector expression is an enum type, and the pattern is an unqualified name, resolve it as a member of the enum type; otherwise, handle a ConstantExpression pattern just like any other. (I might also drop the grammar's distinction between EnumConstantName and ConstantExpression, which is ambiguous. And I might also push this special-case logic about name resolution into Chapter 6.) --- I have concerns about the 'break' rules; see separate thread. --- With or without 'null', there's a good argument that the arrow clauses need a way to syntactically combine specific cases and 'default'. Where are we at on this? --- Missing stuff (not necessarily a comprehensive list): - 15.6, evaluation of a switch expression may throw (I hate maintaining these lists, but it's here, so we must maintain it) - 15.12.2.1, define "potentially compatible" - 15.12.2.5, define "more specific" - 15.25, categorization of conditionals with switch expression operands (ugh, one more motivation to abandon the categorization scheme) - 16, definite assignment (including how does a boolean selector/result get treated?) - 18.2.1, inference reduction - 18.5.2.2, searching for additional inference constraints - 18.5.4, "more specific" inference --- And some notes about presentational issues: Throughout: for other specs, people have expressed interest in seeing a complete before-and-after diff. No shortcuts. (And they're probably right—it's a lot easier to see what's going on that way.) So any words that have been removed should be indicated explicitly as deletions, rather than just leaving the old words out and highlighting the new words as additions. 5.6.3 needs a better title than "numeric promotion", which is a broad term introduced in 5.6; and it needs to be properly introduced in 5.6. The conditional expression spec should be updated to re-use the new flavor of numeric promotion. 14.11: somewhat arbitrarily, '->' is considered an "operator" while ':' is considered a "separator". Should match that terminology. 14.11: "consists of zero or more statements" is not quite right in either case. A clause block consists of clauses, which are pattern/clause body pairs. A group block consists of statement groups, which are lists of statements prefixed by a list of labels. 14.11: "It should be clear from that grammar ..." should be green 14.11: Use of the term "pattern" is premature. These are really just ConstantExpressions (plus, maybe, null). As is, we have lots of undefined concepts: When is a pattern "assignment compatible with" a type? When does a pattern "have the same value" as another? 14.11: The discussion explaining why we don't silently complete a switch when the selector is null is worth keeping, as an explanation for why, in the absense of an explicit 'case null', the statement will throw. (Better than just saying "historical reasons" or "compatibility".) 14.11 "A Java compiler is encouraged": after much discussion about exhaustiveness, I think the consensus is that we would very much not like for a Java compiler to do this. Silently doing nothing for some inputs is a feature of switch statements. 14.11: I'm pretty down on explaining features via translation to other features. It's often
Re: JEP325: Switch expressions spec
> On Apr 27, 2018, at 11:03 AM, Gavin Biermanwrote: > > I have uploaded the latest draft of the spec for JEP 325 at > http://cr.openjdk.java.net/~gbierman/switch-expressions.html > > Changes from the last version: > * Supports new -> label form in both switch expressions and switch statements > * Added typing rules for switch expression > * Restrict the type of a selector expression to not include long, double and > float as previously proposed > * Misc smaller changes from community feedback (thanks!) > > Comments welcomed! Note the (certainly currently intentional) lack of structural parallelism in these two parts of the BNF in Section 4.11: __ SwitchStatementClause: ClauseLabel Statement ClauseLabel: CasePattern -> __ SwitchBlockStatementGroup: GroupLabels BlockStatements GroupLabels: GroupLabel {GroupLabel} GroupLabel: CasePattern : __ They can easily be made structurally parallel by changing the first two cited rules to: __ SwitchStatementClause: ClauseLabels Statement ClauseLabels: ClauseLabel {ClauseLabel} ClauseLabel: CasePattern -> __ which of course results in precisely my earlier proposal to allow multiple clause labels on a single statement—this note is merely to point out that it is an easy and unsurprising change to the BNF. Then in Section 15.29 one need only change __ SwitchExpressionClause: ClauseLabel Expression ; ClauseLabel Block ClauseLabel ThrowStatement __ to __ SwitchExpressionClause: ClauseLabels Expression ; ClauseLabels Block ClauseLabels ThrowStatement __ “It’s not fallthrough—it’s multiple labels.” —Guy
Re: JEP325: Switch expressions spec
Good point, Rémi. However, note that case pat1, pat2 -> s is equally too close to case pat1 -> pat2 -> s and again they have very different meanings. We have to admit that there is room to blunder with this syntax. One way out would be to use a different arrow for `switch` statements: switch (x) { case pat1 => case pat2 => s1; case pat3 => pat4 -> s2; case pat5, pat6 => s2; case pat 7, pat8 => pat9 -> s4; } > On Apr 23, 2018, at 2:29 PM, Remi Foraxwrote: > > I agree with Kevin, > case pat1 -> case pat2 -> s > is too close to > case pat1 -> pat2 -> s > which has a very different meaning (the result is a lambda). > > Rémi
Re: JEP325: Switch expressions spec
All good points. Minor comments inline. |Were we considering allowing `case /something/, default:` or `default, case /something/:`? Of course you would never ever actually /need/ this... except in the one case that /something/ is null. In a switch expression it would be sad to be forced to revert to the old syntax for only this reason.| |This may well be needed, especially if we prohibit fallthrough from a colon label into a arrow label. Another case where a simliar problem arises is this: case null: case String s: // whoops, s is not DA here Really, we'd like to say case null s, String s: or case (null | String) s: or something similar. We don't have to cross this until we get to type patterns, but it's on the horizon. |
Re: JEP325: Switch expressions spec
Thanks Maurizio. Some replies inline. > On 13 Apr 2018, at 12:15, Maurizio Cimadamore >wrote: > > Looks neat. Some comments: > > * I note that you introduced patterns to describe the new syntactic options; > while that's a completely fine choice, I wonder if it could lead to confusion > - I always thought of JEP 325 as a set of standalone switch improvements, > which don't need the P-word to be justified. Of course, I'm not opposed to > what you have done, just noting (aloud) the mismatch with my expectations. Yes, you spotting me setting things up for a future release :-) But in my defence: in the current spec, we say “case constant” where constant is either a constant expression or an enum constant. We are adding to this the possibility of a “null”, so we need to find another word anyhow. That said, I think you have a point, so I’ll look again to see if I can dial it down a bit. > > * in 14.11 I find these sentences: > > "then we say that the null pattern matches", "then we say that the pattern > matches" > > A bit odd to read , as the transitive verb 'matches' is missing its object. I know what you mean, but the spec today already states “...then we say that the case label *matches*.” So I actually kept that text as it is. > > * also I note some replication: > > "If all these statements complete normally, or if there are no statements > after the pattern label containing the matching pattern, then the entire > switch statement completes normally." > "If all these statements complete normally, or if there are no statements > after the pattern label containing the matching pattern, then the entire > switch statement completes normally." > "If all these statements complete normally, or if there are no statements > after the default pattern label, then the entire switch statement completes > normally." > > The first two are identical, the last only slightly different, perhaps > something can be done to consolidate I’ll take another look. > > * "A break statement either transfers control out of an enclosing statement > or returns a value to an immediately enclosing switch expression." > > Is it an either/or? My mental model is that break always transfer controls > out - it can do so with a value, or w/o a value (as in a classic break). This is a good question, although probably only one for spec-nerds. The problem is that the concept of “transfer of control” is only valid for statements - in essence you jump from one statement to the other. There is no concept in the JLS of control for *expressions*. So you can’t really say that the break statement with a value transfers control to an *expression*. This is what is so “unusual” about switch expressions, they are expressions with statements inside... This either/or distinction makes clear, for better or for worse, the new dual nature of break statements: they either transfer control to another statement, or they end up returning a value to an enclosing expression. > > * I like the fact that you define the semantics of the expression switch > clauses in terms of desugaring to statements blocks - this is consistent with > what we do in other areas (enhanced for loop, try with resources). Thanks! Although, with the proposed change to forbid fall through from statement groups into clauses, I’m not sure they can stay. > > * I suggest putting the paragraph in 15.29 starting with: > > "Given a switch expression, all of the following must be true" > > Ahead of the desugaring paragraph, which seems more > execution/semantics-related, while this one is still about well-formedness. Yes! Thanks. > * On totality - this line: > > default -> 10; // Legal > > deserves some more explanation - e.g. one might think it's unreachable, but > it's not because new constants could pop up at runtime; maybe add a > clarification. Yes! Thanks. > > * On non-returning, this sentence is obscure: > > "Thus a switch expression block that can not complete normally, can only do > so by occurrences of a break statement with an Expression. This ensures that > a switch expression must either result in a value, or complete abruptly." > > because it contradicts what is said just a line above: > > "an occurrence of a break statement with an Expression in a switch expression > means that the switch expression will complete normally with the the value of > the Expression" > > The way I read this is: > > 1) the only way for the block after a 'case' in a switch pattern to complete > abnormally is via a break expression > 2) even if the _block_ completes abnormally, the containing switch expression > will complete normally, with the value of Expression > > Is that what you meant? Yes, although I’m not sure I quite see the “contradiction”. I’ll take another look at this text. > * At the end of the switch expression section there are sub-optimal sentences > like the