From kevinb at google.com Tue May 1 16:39:13 2018 From: kevinb at google.com (Kevin Bourrillion) Date: Tue, 1 May 2018 09:39:13 -0700 Subject: `case null:` (here we go) In-Reply-To: References: Message-ID: A few small follow-ups: Upon further research, the statistic that 2.4% of our switch statements are simulating `case null` has mostly held up - it's somewhere between 2.0 and 2.3%. (Note that our development practices are relatively null-hostile, so the value would likely be higher in other codebases.) But I also found that of *these*, 62-81% are doing it to give null the same behavior as default. Compared to (of course) 19-38% giving null distinct behavior. (That wide range is a 90% confidence interval and could be narrowed if it were actually helpful.) So, what this tells us is that `case null` without the ability to combine it with `default` would indeed be a dissatisfying change. However, having reviewed 67 samples (across both kinds) manually, I can confirm that (so long as we do have the ability to combine `default` and `case null` together) they do simplify pretty nicely with the proposed change. I had expected to find a number of examples where null could instead be canonicalized to another value, which would then enable the switch to work as written. However, it's only worth doing that when it "feels right" and not like a hack, and it turned out there were only a small handful of examples like that. So (as previously conceded) the change IS a win for these cases. The question really is just about how hamstrung we are or aren't by the decisions already set in stone for null switch in previous versions. My data won't do anything to settle it; it comes down to a squishy judgment call about what best protects whatever measure of conceptual simplicity switch can hang onto. ftr, my request continues to be only that we hold off on making any change regarding null for now. On Fri, Apr 27, 2018 at 8:59 AM, Kevin Bourrillion wrote: > From newest spec: > > > *ClauseLabel*: > > *CasePattern ->* > > *CasePattern:* > > *case Pattern { , Pattern }* > *default* > > *Pattern:* > > *ConstantExpression* > *EnumConstantName* > *null* > > > Just a reminder that we still have this conflict to resolve. Even when you > learn the wart that `default` is not covering null, there is no way to > *make* it do so without repeating the RHS. We need `default, case null:`. > > Of course, my preferred resolution is to *hold off* on `case null` > support for now. I'd like to give one honest attempt at a full argument; I > hope to get an engaged response to it, and then if a decision is made > against it, I'll move on, figure I was wrong, and never speak of it again. > :-) > > ~~ > > 1. For the sake of argument I'll just concede the notion that today's null > behavior in switch was a mistake and if we could turn back time we would > change it. > > 2. On the flip side, I think that proponents of the feature can probably > concede that we would *never* have designed it in the now-proposed way > for a fresh language; it *is* a permanent wart brought about by > historical accident only. (Yes?) So, I assume that proponents recognize > that rejecting this change is at least *defensible*, by appealing to the > compatibility constraints we inherited. We should not need to worry that we > will "look like idiots" (or whatever terms our deepest fears phrase > themselves in :-)). > > 3. Many users since 2004 have said, and will continue to say, that they > wish `case null` were allowed. However, I don't think we can assume they > are necessarily comparing today's behavior to the *actual* feature we are > proposing, with its warts. It is likely and natural that they are really > comparing today's behavior to the time-machine feature of our having > supported `case null` from the start. Therefore I think we have to take > most such requests with a grain of salt. > > 4. Yes, sometimes users do write code that simulates `case null` and that > code could be nicely simplified if null were allowed in switch. I can do a > better job of quantifying the incidence of this need in our large codebase > if necessary (but have been prioritizing string literal research for > now). But fundamentally, the feature *is* a win, for *these* examples. > > 5. It has been implied that patterns are what make the current null > treatment "untenable". To me, I don't think this argument has been made > convincingly yet. It seems to add up to "there may be a few more of those > cases where you bump up against the prohibition and think 'oh yeah, grrrr, > can't switch directly on null because of reasons no one understands!'" But > fundamentally it seems like the same problem it already was. > > 6. That benefit has to be weighed against the damage we will be causing. > Here is the meat of it: > - `default` will no longer mean default. There is really no way around > that. > - Null will be treated unaccountably differently from all other values in > switch. It becomes harder to explain how switch works -- "sorry, no null" > is at least easy. Instead it's "well, switch *itself* allows null, but it > assumes you want a `case null` that throws if you don't say otherwise". > Looked at without knowing all the baggage, is this not a bit bizarre? > - Also (back to how this email started), this appears to be the only > factor forcing us to introduce a `default, case x` syntax we would never > otherwise need - or to mint some other bespoke construction we would, > again, never otherwise need. > > From where I sit, the cost is clearly too great compared to the benefit. > While "never doing anything at all about this" might not be the solution, I > am at least confident that the current proposal is not the right solution > either, and I'd like to convince us to bench it. > > But again - if we can make either decision clearly, I'll be done here, and > not even grumpy. > > > > On Fri, Apr 27, 2018 at 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 >> >> 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 >> >> > > > -- > Kevin Bourrillion | Java Librarian | Google, Inc. | kevinb at google.com > -- Kevin Bourrillion | Java Librarian | Google, Inc. | kevinb at google.com -------------- next part -------------- An HTML attachment was scrubbed... URL: From vicente.romero at oracle.com Tue May 1 17:32:04 2018 From: vicente.romero at oracle.com (Vicente Romero) Date: Tue, 1 May 2018 13:32:04 -0400 Subject: [constables] RFR of constants API In-Reply-To: <451987dd-9371-552f-908d-e57fdc1f09ff@oracle.com> References: <451987dd-9371-552f-908d-e57fdc1f09ff@oracle.com> Message-ID: <1bc4edf2-c016-5fb2-fd45-b235a5e3d580@oracle.com> Please review also the related CSR: https://bugs.openjdk.java.net/browse/JDK-8202031 Thanks, Vicente On 04/27/2018 01:31 PM, Vicente Romero wrote: > Hi all, > > Please review the current proposal of the constants API, which are > nominal descriptor types defined in pkg java.lang.invoke.constant. The > code can be found at [1]. This API is being developed in the context > of JEP 303: Intrinsics for the LDC and INVOKEDYNAMIC Instructions [2] > > Thanks in advance for your comments, > Vicente > > [1] http://cr.openjdk.java.net/~vromero/constant.api/webrev.00 > [2] http://openjdk.java.net/jeps/303 From brian.goetz at oracle.com Tue May 1 17:43:53 2018 From: brian.goetz at oracle.com (Brian Goetz) Date: Tue, 1 May 2018 18:43:53 +0100 Subject: [constables] RFR of constants API In-Reply-To: <1bc4edf2-c016-5fb2-fd45-b235a5e3d580@oracle.com> References: <451987dd-9371-552f-908d-e57fdc1f09ff@oracle.com> <1bc4edf2-c016-5fb2-fd45-b235a5e3d580@oracle.com> Message-ID: <4B94BFE7-6D9E-490F-BB68-6ABF5CD095B4@oracle.com> To be clear: we?re asking for an *API review*. No need to review the code right now, just the API and the specs. > On May 1, 2018, at 6:32 PM, Vicente Romero wrote: > > Please review also the related CSR: https://bugs.openjdk.java.net/browse/JDK-8202031 > > Thanks, > Vicente > > On 04/27/2018 01:31 PM, Vicente Romero wrote: >> Hi all, >> >> Please review the current proposal of the constants API, which are nominal descriptor types defined in pkg java.lang.invoke.constant. The code can be found at [1]. This API is being developed in the context of JEP 303: Intrinsics for the LDC and INVOKEDYNAMIC Instructions [2] >> >> Thanks in advance for your comments, >> Vicente >> >> [1] http://cr.openjdk.java.net/~vromero/constant.api/webrev.00 >> [2] http://openjdk.java.net/jeps/303 > From kevinb at google.com Tue May 1 20:46:41 2018 From: kevinb at google.com (Kevin Bourrillion) Date: Tue, 1 May 2018 13:46:41 -0700 Subject: [raw-string] indentation stripping In-Reply-To: <5157CBFA-7068-414E-8590-150713ED1B1A@oracle.com> References: <5157CBFA-7068-414E-8590-150713ED1B1A@oracle.com> Message-ID: (None of this has any bearing on single-line RSLs, which work great and need no changes at all. "Raw means raw", all the way.) I've proposed we adopt an assumption, which I was calling the "rectangle rule", which really just says: we assume most users will prefer to see *relative indentation preserved exactly* between the source code and runtime forms of their strings. That is, I think we can assume that users will *not* want to read or write this: String one = `+-----------------+ | a nice neat box | +-----------------+`; nor this: String two = `+-----------------+ | a nice neat box | +-----------------+`; nor even this: String three = `+-----------------+ | a nice neat box | +-----------------+`; but that the universe of styles they will consider might include this: String four = `+-----------------+ | a nice neat box | +-----------------+`; or this: String five = ` +-----------------+ | a nice neat box | +-----------------+ `; or this: String six = ` +-----------------+ | a nice neat box | +-----------------+`; ... or various others, but common to all, I claim that users will want to see... well, a nice neat box. If we agree with this principle, then continuing with "raw means raw" creates a big problem: everything but style four gives you a leading newline in your actual constant, which is rarely wanted, and not even trivial to remove. And style four is itself problematic, because you may overflow your right margin, and because refactorings will break the alignment you wanted once again. So *I'm hoping to get agreement* on this question: even if we do nothing else, should we chop a leading newline (after ignoring other leading whitespace), if present? For the reasons just explained I think the answer should be yes. (My main project here is to get to a fair comparison between the "raw-means-close-to-raw" and the "automatic indentation stripping" alternatives. All I'm hoping to do here is to stop this leading newline issue from muddying that comparison, by establishing that we would strip that either way. Note that symmetric arguments do not apply for trailing newlines; in fact, for the more-raw alternative we *must not* strip those.) On Sat, Apr 28, 2018 at 11:12 AM, Brian Goetz wrote: > This thread accidentally got started on the wrong list, so bringing it > back here. The following messages are hereby read into the record (and > hence can be considered to be under the proper terms of use for a > specification list.) > > http://mail.openjdk.java.net/pipermail/amber-dev/2018-April/003034.html (Jim > #1) > http://mail.openjdk.java.net/pipermail/amber-dev/2018-April/003035.html > (John) > http://mail.openjdk.java.net/pipermail/amber-dev/2018-April/003051.html (Kevin > #1) > http://mail.openjdk.java.net/pipermail/amber-dev/2018-April/003052.html (Jim > #2) > http://mail.openjdk.java.net/pipermail/amber-dev/2018-April/003053.html (Kevin > #2) > http://mail.openjdk.java.net/pipermail/amber-dev/2018-April/003054.html (Jim > #3) > > A summary follows. > > The key point being discussed is that the ?raw means raw? interpretation > for multi-line strings is likely to be at odds with how users actually plan > to use the feature ? that they will pad the code with incidental > indentation to make it line up nicely with the enclosing Java code, and > that IDEs may well adjust said incidental indentation as the code is > maintained ? and that this is a reasonable thing to encourage. Kevin?s > data from the Google codebase backs up this supposition. Our design > already admits this to some degree ? for multi-line strings, we don?t > really believe the source file when it uses platform-specific line > terminators. So we?re trying to distill how to distinguish ?incidental? > indentation from intended indentation in multi-line strings. (More > generally: the feedback we?ve gotten is that while raw strings is the right > design center for single-line strings, when it comes to snippets that span > lines, user care more about multi-line-ness than raw-ness.) > > Assumptions: > - Most multi-line strings will be code snippets of some sort (JSON, XML, > SQL, Java, etc); > - Most developers will want to use incidental indentation to have code > snippets indent ?sensibly? relative to neighboring Java code, but said > incidental indentation is not part of the snippet. > > Jim?s #1 offers a catalog of ways in which users might craft multi-line > string literals to fit cleanly into their source code, identifying which > indentation is incidental and which is essential. > > To the goals, I?d add: > > - In addition to it being _possible_ to render the desired result, it > should be straightforward for users to _predict_ the result of indentation > stripping. > > Kevin adds: it would be useful if we could draw a ?rectangle? that > excludes all incidental indentation and includes all intended indentation. > > Tabs are a confounding issue; since there is no standard interpretation > for how many spaces correspond to a tab, in the general case no trimming > algorithm will do well with mixed spaces and tabs. However, in the > well-behaved case where lines begin with tab* space*, a common prefix can > be stripped. > > There?s some reason to believe that calling .stripIndent() will be so > common that it should be the default, rather than requiring users to invoke > it every time. > > Now back to discussion. > > -- Kevin Bourrillion | Java Librarian | Google, Inc. | kevinb at google.com -------------- next part -------------- An HTML attachment was scrubbed... URL: From john.r.rose at oracle.com Tue May 1 21:33:32 2018 From: john.r.rose at oracle.com (John Rose) Date: Tue, 1 May 2018 14:33:32 -0700 Subject: `case null:` (here we go) In-Reply-To: References: Message-ID: On Apr 27, 2018, at 8:59 AM, Kevin Bourrillion wrote: > > 6. That benefit has to be weighed against the damage we will be causing. Here is the meat of it: > - `default` will no longer mean default. There is really no way around that. You have to push the historic hostility to null either to the switch or the default. So either (as you say) "default doesn't mean default" or (with the same meaning) "switch doesn't mean switch" or we break history or we ret-con either switch or default. Pick your poison. I pick "default means (null-hostile) default". What's so hard about that? > - Null will be treated unaccountably differently from all other values in switch. It becomes harder to explain how switch works -- "sorry, no null" is at least easy. It's not easy at all when you *need* to pass nulls. I don't buy the objection that we didn't allow nulls before; now we will allow "case var x:" and (again) the choice is simple and stark: either "var means var" (and allows null if the type is nullable) or else "var means null-hostile var" in a switch. Really, you are plumping for "switch is (null-hostile) switch", but that has the unfortunate effect of making "var" be null hostile in a switch?which will be so surprising (we think) that we need to figure out a way to move the null-hostility out of the switch header, and into the default. > Instead it's "well, switch itself allows null, but it assumes you want a `case null` that throws if you don't say otherwise". Looked at without knowing all the baggage, is this not a bit bizarre? A bit. Far less bizarre than "Here's a general classifier syntax. But it doesn't work on null, sorry." I'm trying to see it your way, but I still think the best trade-off is putting the historical baggage on default, not at the top of the switch. > - Also (back to how this email started), this appears to be the only factor forcing us to introduce a `default, case x` syntax we would never otherwise need - or to mint some other bespoke construction we would, again, never otherwise need. We don't need to mint any such construction. We could simply say this: "You know that old fallthrough thing you sometimes need for combining cases? Well, you need need it when you want case null to fall through into default." Null-friendliness, in that story, is just one of the factors that might move you towards colons and away from arrows. And Remi has already sketched a reasonable extension (bespoke construction) which is good for lots of things: You simply give an "or" construction along the lines of "case x,y,z:" and then you allow default to play in the or construction. There's nothing surprising about that proposal, when you realize that the main use of fall-through in today's switches is to get the effect of an or construction, with or without default. What's more natural than finding a way to do this with arrow-switches? You don't even need to mention null to justify this, and then easier null friendliness (with arrow as well as colon) is one of the side-effects. ? John From guy.steele at oracle.com Tue May 1 21:19:56 2018 From: guy.steele at oracle.com (Guy Steele) Date: Tue, 1 May 2018 17:19:56 -0400 Subject: [raw-string] indentation stripping In-Reply-To: References: <5157CBFA-7068-414E-8590-150713ED1B1A@oracle.com> Message-ID: <463CD19A-767C-4EFA-BCFC-1144E3ABB28B@oracle.com> > On May 1, 2018, at 4:46 PM, Kevin Bourrillion wrote: > > (None of this has any bearing on single-line RSLs, which work great and need no changes at all. "Raw means raw", all the way.) > > I've proposed we adopt an assumption, which I was calling the "rectangle rule", which really just says: we assume most users will prefer to see relative indentation preserved exactly between the source code and runtime forms of their strings. > > That is, I think we can assume that users will not want to read or write this: > > String one = `+-----------------+ > | a nice neat box | > +-----------------+`; > > nor this: > > String two = `+-----------------+ > | a nice neat box | > +-----------------+`; > > nor even this: > > String three = > `+-----------------+ > | a nice neat box | > +-----------------+`; > > but that the universe of styles they will consider might include this: > > String four = `+-----------------+ > | a nice neat box | > +-----------------+`; > > or this: > > String five = ` > +-----------------+ > | a nice neat box | > +-----------------+ > `; > > or this: > > String six = ` > +-----------------+ > | a nice neat box | > +-----------------+`; > > ... or various others, but common to all, I claim that users will want to see... well, a nice neat box. > > If we agree with this principle, then continuing with "raw means raw" creates a big problem: everything but style four gives you a leading newline in your actual constant, which is rarely wanted, and not even trivial to remove. And style four is itself problematic, because you may overflow your right margin, and because refactorings will break the alignment you wanted once again. > > So I'm hoping to get agreement on this question: even if we do nothing else, should we chop a leading newline (after ignoring other leading whitespace), if present? For the reasons just explained I think the answer should be yes. > > (My main project here is to get to a fair comparison between the "raw-means-close-to-raw" and the "automatic indentation stripping" alternatives. All I'm hoping to do here is to stop this leading newline issue from muddying that comparison, by establishing that we would strip that either way. Note that symmetric arguments do not apply for trailing newlines; in fact, for the more-raw alternative we must not strip those.) If we do provide a way to strip that leading newline (whether ?always" or through use of a library method), this suggests a seventh possible style: String seven = ` +-----------------+ | a nice neat box | +-----------------+ `; String sevenLibrary = ` +-----------------+ | a nice neat box | +-----------------+ `.trimIndentation(); // If a library method is used with the convention that if the last line consists entirely of whitespace and does not end in a newline, then it should be stripped _and furthermore the exact same amount of whitespace should be stripped from all other lines in the literal_. Maybe this feature gets triggered in the automatic case only if a leading newline is also there to be stripped. This strategy eliminates the need to use some special character such as | to delineate the indentation level. And it nests properly: String myNestedExample = ``` String seven = ` +-----------------+ | a nice neat box | +-----------------+ `; ```; In this last example, the nice neat box, once stripping has occurred, has no leading indentation, whereas the text that begins ?String seven? has two spaces of leading indentation. ?Guy P.S. We can actually have it both ways: do the stripping if and only if the number of tick marks is even. :-b String myNestedExample = ```` String seven = `` +-----------------+ | a nice neat box | +-----------------+ ``; ````; -------------- next part -------------- An HTML attachment was scrubbed... URL: From guy.steele at oracle.com Tue May 1 21:26:56 2018 From: guy.steele at oracle.com (Guy Steele) Date: Tue, 1 May 2018 17:26:56 -0400 Subject: `case null:` (here we go) In-Reply-To: References: Message-ID: <98C982EE-B1D1-4E13-96E2-E14ADB247F16@oracle.com> ? ?case null: default:? IS NOT FALLTHROUGH, IT?S MULTIPLE LABELS!? Guy howled into the uncaring darkness. :-) (I know, I know; I might as well be insisting that everybody use ?whom? correctly.) Except for that, +1. :-) :-) ?Guy > On May 1, 2018, at 5:33 PM, John Rose wrote: > > On Apr 27, 2018, at 8:59 AM, Kevin Bourrillion wrote: >> >> 6. That benefit has to be weighed against the damage we will be causing. Here is the meat of it: >> - `default` will no longer mean default. There is really no way around that. > > You have to push the historic hostility to null either to the switch or > the default. So either (as you say) "default doesn't mean default" > or (with the same meaning) "switch doesn't mean switch" or we > break history or we ret-con either switch or default. Pick your poison. > I pick "default means (null-hostile) default". What's so hard about that? > >> - Null will be treated unaccountably differently from all other values in switch. It becomes harder to explain how switch works -- "sorry, no null" is at least easy. > > It's not easy at all when you *need* to pass nulls. I don't buy the objection > that we didn't allow nulls before; now we will allow "case var x:" and > (again) the choice is simple and stark: either "var means var" (and > allows null if the type is nullable) or else "var means null-hostile var" > in a switch. Really, you are plumping for "switch is (null-hostile) > switch", but that has the unfortunate effect of making "var" be null > hostile in a switch?which will be so surprising (we think) that we > need to figure out a way to move the null-hostility out of the switch > header, and into the default. > >> Instead it's "well, switch itself allows null, but it assumes you want a `case null` that throws if you don't say otherwise". Looked at without knowing all the baggage, is this not a bit bizarre? > > A bit. Far less bizarre than "Here's a general classifier syntax. > But it doesn't work on null, sorry." I'm trying to see it your way, > but I still think the best trade-off is putting the historical baggage > on default, not at the top of the switch. > >> - Also (back to how this email started), this appears to be the only factor forcing us to introduce a `default, case x` syntax we would never otherwise need - or to mint some other bespoke construction we would, again, never otherwise need. > > We don't need to mint any such construction. We could simply say this: > "You know that old fallthrough thing you sometimes need for combining > cases? Well, you need need it when you want case null to fall through > into default." Null-friendliness, in that story, is just one of the factors > that might move you towards colons and away from arrows. > > And Remi has already sketched a reasonable extension (bespoke > construction) which is good for lots of things: You simply give an > "or" construction along the lines of "case x,y,z:" and then you allow > default to play in the or construction. There's nothing surprising > about that proposal, when you realize that the main use of > fall-through in today's switches is to get the effect of an or > construction, with or without default. What's more natural > than finding a way to do this with arrow-switches? You don't > even need to mention null to justify this, and then easier null > friendliness (with arrow as well as colon) is one of the side-effects. > > ? John From kevinb at google.com Tue May 1 22:38:39 2018 From: kevinb at google.com (Kevin Bourrillion) Date: Tue, 1 May 2018 15:38:39 -0700 Subject: `case null:` (here we go) In-Reply-To: References: Message-ID: On Tue, May 1, 2018 at 2:33 PM, John Rose wrote: On Apr 27, 2018, at 8:59 AM, Kevin Bourrillion wrote: > > > > 6. That benefit has to be weighed against the damage we will be causing. > Here is the meat of it: > > - `default` will no longer mean default. There is really no way around > that. > > You have to push the historic hostility to null either to the switch or > the default. So either (as you say) "default doesn't mean default" > or (with the same meaning) "switch doesn't mean switch" or we > break history or we ret-con either switch or default. Pick your poison. > I pick "default means (null-hostile) default". What's so hard about that? > We can't just localize the null-hostility to `default`, since null-case-less switches that don't have `default` will still throw. It has always been `switch` itself that is null-hostile. We can only change that through conceptual contortions; I'm doubtful we can find anything as tidy as what you suggest. > - Null will be treated unaccountably differently from all other values in > switch. It becomes harder to explain how switch works -- "sorry, no null" > is at least easy. > > It's not easy at all when you *need* to pass nulls. Sure. I was making a different point about the conceptual simplicity of the feature. "Easy to explain" and "easy to code your use case" are simply different topics. I don't buy the objection > that we didn't allow nulls before; now we will allow "case var x:" and > (again) the choice is simple and stark: either "var means var" (and > allows null if the type is nullable) or else "var means null-hostile var" > in a switch. Really, you are plumping for "switch is (null-hostile) > switch", but that has the unfortunate effect of making "var" be null > hostile in a switch? Would that really look like a null-hostile `var`? To me, it looks like the var allows null but the switch is not letting it through. If I doubt that, I can just look at the stack trace. I assume it would point straight at the switch, as it does today. > Instead it's "well, switch itself allows null, but it assumes you want a > `case null` that throws if you don't say otherwise". Looked at without > knowing all the baggage, is this not a bit bizarre? > > A bit. Far less bizarre than "Here's a general classifier syntax. > But it doesn't work on null, sorry." I suppose we'll agree to disagree on this part. I think it's unfortunate, but still conceptually simple. The reason it rejects null is the exact same reason it always did. (The fact that reason is *bad* was already conceded at top.) > > - Also (back to how this email started), this appears to be the only > factor forcing us to introduce a `default, case x` syntax we would never > otherwise need - or to mint some other bespoke construction we would, > again, never otherwise need. > > We don't need to mint any such construction. We could simply say this: > "You know that old fallthrough thing you sometimes need for combining > cases? Well, you need need it when you want case null to fall through > into default." Null-friendliness, in that story, is just one of the > factors > that might move you towards colons and away from arrows. > > And Remi has already sketched a reasonable extension (bespoke > construction) which is good for lots of things: You simply give an > "or" construction along the lines of "case x,y,z:" and then you allow > default to play in the or construction. There's nothing surprising > about that proposal, when you realize that the main use of > fall-through in today's switches is to get the effect of an or > construction, with or without default. What's more natural > than finding a way to do this with arrow-switches? You don't > even need to mention null to justify this, and then easier null > friendliness (with arrow as well as colon) is one of the side-effects. > This sounds like a persuasive case that the grammar should allow for `default, case null`. But I agree with that already (it was how this thread began). It is fine. I just felt it was noteworthy that we would never have needed the ability to comma-combine default with other case labels if not for this. It's minted for this very special case. -- Kevin Bourrillion | Java Librarian | Google, Inc. | kevinb at google.com -------------- next part -------------- An HTML attachment was scrubbed... URL: From james.laskey at oracle.com Tue May 1 23:04:07 2018 From: james.laskey at oracle.com (Jim Laskey) Date: Tue, 1 May 2018 20:04:07 -0300 Subject: [raw-string] indentation stripping In-Reply-To: <463CD19A-767C-4EFA-BCFC-1144E3ABB28B@oracle.com> References: <5157CBFA-7068-414E-8590-150713ED1B1A@oracle.com> <463CD19A-767C-4EFA-BCFC-1144E3ABB28B@oracle.com> Message-ID: <3EC8BC69-8BC4-45DE-858F-38DA1DB589C7@oracle.com> > > P.S. We can actually have it both ways: do the stripping if and only if the number of tick marks is even. :-b > > String myNestedExample = ```` > String seven = `` > +-----------------+ > | a nice neat box | > +-----------------+ > ``; > ````; Groan -------------- next part -------------- An HTML attachment was scrubbed... URL: From guy.steele at oracle.com Wed May 2 03:39:49 2018 From: guy.steele at oracle.com (Guy Steele) Date: Tue, 1 May 2018 23:39:49 -0400 Subject: [raw-string] indentation stripping In-Reply-To: <3EC8BC69-8BC4-45DE-858F-38DA1DB589C7@oracle.com> References: <5157CBFA-7068-414E-8590-150713ED1B1A@oracle.com> <463CD19A-767C-4EFA-BCFC-1144E3ABB28B@oracle.com> <3EC8BC69-8BC4-45DE-858F-38DA1DB589C7@oracle.com> Message-ID: > On May 1, 2018, at 7:04 PM, Jim Laskey wrote: > >> >> P.S. We can actually have it both ways: do the stripping if and only if the number of tick marks is even. :-b >> >> String myNestedExample = ```` >> String seven = `` >> +-----------------+ >> | a nice neat box | >> +-----------------+ >> ``; >> ````; > > Groan Okay, that part was stupid, but everything before that was quite serious. ?Guy -------------- next part -------------- An HTML attachment was scrubbed... URL: From john.r.rose at oracle.com Wed May 2 05:31:59 2018 From: john.r.rose at oracle.com (John Rose) Date: Tue, 1 May 2018 22:31:59 -0700 Subject: [raw-string] indentation stripping In-Reply-To: <463CD19A-767C-4EFA-BCFC-1144E3ABB28B@oracle.com> References: <5157CBFA-7068-414E-8590-150713ED1B1A@oracle.com> <463CD19A-767C-4EFA-BCFC-1144E3ABB28B@oracle.com> Message-ID: On May 1, 2018, at 2:19 PM, Guy Steele wrote: > > the convention that if the last line consists entirely of whitespace and does not > end in a newline, then it should be stripped _and furthermore the exact same > amount of whitespace should be stripped from all other lines in the literal_ Seconded. (And see discussion of case y in my earlier note to amber-dev, where the final line is the control line. Relevant part copied below.) I keep coming back to the idea that the final line of the quote is the best place to control indentation stripping. Here's a rule we could make: If the trailing line of the literal is blank (except for indentation) then it is treated as part of the payload delimiter. In that case, that whitespace must be uniformly present as leading indentation on all other lines, which is also stripped from every line of the quote body. The leading newline (if any) is also stripped. String y = ` ..___line one ..line fifty-two ..___line ninety-nine ::`; The payload starts with "___line one" and ends with "___line ninety-nine". (Here underbar _ is a non-stripped space and colon : is the controlling stripped space, while period are the non-controlling copies of the stripped space.) By declaring that the final line gets stripped, the literal's payload is fully and exactly contained in the displayed source code lines between the two stripped lines of the literal. That is not possible unless the last line is stripped as well as the first. More: *We can specify that it is an error if the identical leading whitespace is not present on every payload line and also the stripped trailing line.* This means there are no invisible surprises: What you see at the end of the string is the same as everywhere else. Previous versions of the stripping rule distribute the responsibility across all the lines, but make it difficult or impossible to find the line with the shortest indent, since (a) it might be in the middle of the literal, or (b) it might even display the same as other lines with a different combination of spaces and tabs. By contrast, making the trailing line uniquely responsible for controlling the stripping removes situation (a) and requiring other lines to have the same leading space substantially removes situation (b). String y_err = ` ..___line one _line fifty-two ..___line ninety-nine ::`; // error: unaligned indent before "line fifty-two" I think we should do this. It would make it a little (a *very* little) harder to correctly write indented What if the trailing line has non-space characters? Fine; don't exdent that literal (that's option A). Or (option B) exdent by all the leading whitespace characters, and tack on the remaining part of the final line to the payload; that gives a hook for ending a multi-line literal without a newline but keeping the indent feature. (We have to favor one and disfavor the other, among the two options of trailing newline and non-trailing newline.) There's a third choice (option E) to reserve that condition for future use. FWIW I like option A as the simplest back-off from fancy stuff: String y_A = ` _____line one __line fifty-two _____line ninety-nine __line 100`; // => really raw no indent stripping Rationale: The trailing line controls exdenting, but *only if* it is all whitespace: All the exdent and nothing else. What about the leading line? Should it have its indent stripped? No, because that doesn't help make clean indented rectangles of source code; stripping that space would be pure puzzler with no upside. In fact, any non-empty first line is *not* going to align with the rest of the lines, if indentation is in play. Therefore, we have similar options as dealing with non-blanks in the trailing line: Option A1 is to turn off exdenting altogether if the first line is non-empty (that's S. Colebourne's proposal too I think). Option B1 is keep the first line as-is, even though it won't align with the rest of the rectangle, and exdent the rest. Option E1 is to disallow a non-empty leading line. For completeness, option E1A is to disallow a leading line *if it begins with whitespace*, but if it begins with non-whitespace turn off exdenting. (Note that under these rules if the trailing line begins with non-whitespace exdenting is also turned off.) I think B1 is bad: It breaks up the rectangle. I'd like to say that we don't ever break up rectangles; if a proper text rectangle can't be formed in the source code, then exdenting is turned off. No partial exdents. I guess A1 is consistent with the previous A, but so is E1A. String y_E1A = `__spacey ..___line one ..line fifty-two ..___line ninety-nine ::line 100`; // => error: unaligned indent before "spacey" Bottom line suggestions: 1. Control indent/exdent string by defining it precisely as the *trailing* line. 2. Omit that trailing line (if it is all-blank), because it is pure control, not payload. 3. If the trailing line has non-blanks, it's not indent control so don't strip or omit anything. (B: Or split such a trailing line into leading blanks for indent control and payload.) 4. If stripping, require that *every* payload line without exception have the same prefix. 5. If the leading line is not empty, don't strip anything. (Rectangles wouldn't align anyway.) 6. Conversely, if stripping, omit the leading line: It can't contribute anything to a rectangle. 7. Make some edge conditions errors (as in 4) and others "do not strip" cases (as in 3, 5). Net model is you are either raw-means-raw or raw-is-a-rectangle. The latter mode is the only way lines are omitted or left-indents are stripped. To get into the latter mode, you have to have a well-formed rectangle with no oddities. If there's an oddity, you get an error (if it would be hard to read) or you back off to raw-means-raw. A multi-line string that doesn't have a leading newline is raw-means-raw, no exceptions. One downside to putting all the weight on the trailing line: You don't get all of Kevin's style choices. You have to indent the trailing quote the amount you expect to have stripped. But on balance this is IMO a feature not a bug: The exdent level is defined in one unique place. ? John P.S. And for the record, here's my errant message to amber-dev: From: John Rose Subject: Re: Raw String Literals (RSL) - indent stripping of multi-line strings Date: April 23, 2018 at 12:20:02 PM PDT To: Jim Laskey Cc: amber-dev > > - Should trailing whitespace be stripped? As with the "all-indented" case above, trailing space should be stripped only if there is a way to opt out of stripping. I think the trimMarkers API is the way to cover this use case, since it is rather specialized. > - Should the first or last line be removed if blank? Yes. In essence, the syntax of a quote sequence includes a line terminator. This BTW allows non-periodic quote sequences, which as a corollary allows leading and trailing quote sequences to be encoded in the RSL: var hasLeadingAndTrailingTick = `` `I went for a walk in the tall brush and picked up some riders.` ``; Also, the removal of leading and trailing blank lines gives users some degrees of stylistic freedom that seem to be customary, along with the indent-stripping. Here's a new point along these lines, if I may be so bold: If we are sticking in non-payload stylistic inputs into RSLs, we should consider opening up a reservation for future use, in the form of RSL configurations which are declared to be illegal. We could declare that some obviously pathological subset of near-misses to an indent-stripped RSLs is illegal, and reserved for future extension. On the other hand, we are trying very hard to accept every RSL the user could randomly type in, which is incompatible with reserving a set of constructs for future use. This isn't logically necessary in the style-control use cases; we can simply declare that some style-control is just illegal, if we think there's a chance of using that coding space in the future. By obviously pathological I mean something like one or all of these: String x = `_ ..line one ..line two ..`; String y = ` ..___line one ..line fifty-two ..___line ninety-nine ..`; String z = ` ..line one ..line two ..___`; (Here underbar _ is a non-stripped space.) In case x, the is a whitespace on the non-determining blank first line. Surprisingly, this space doesn't get stripped (under the proposed rules). In case y, line 52 determines the indent to strip, and this is true even if it is buried in the middle of 100 lines. Luckily, in this case, the determining last line (just before the close-quote) ratifies this choice, so there is a unique place to look for the stripped indent, without searching the whole string. In case z, the stripped last line, while a determining line, has extra whitespace. This is easy to miss. I suggest placing a structural constraint on stripped indents, that the last line, if blank, is stripped, and if stripped, must be of length exactly zero after the leading indent is trimmed. That would rule out z and ameliorate y. I also suggest ruling out x by requiring that the first line, which is non-determining, must not have leading whitespace at all. This doesn't break any of your examples a-f. Removing cases x and z might remove a class of puzzler about the significance of leading white spaces near the ends of RSLs. (Can anyone see a positive use case for them that can't be easily adjusted to a less pathological form?) And (getting back to extensions) ruling out x also gives us a tidy little subspace of RSLs to reserve for future use. In other words, an RSL with multiple lines whose leading line begins with a space can be defined, in future iterations of this feature, to include envelope information about the RLS, after that space. Something like this: String q = `_{cool RSL header invented by our successors} ..line one ..line two ..`; This envelope information would *not* be included in the payload, but would be stripped as if the leading line were purely blank. It would somehow control the processing of the RSL payload, and/or the parsing of the rest of the RSL. So in this future feature, the first line would still not be a determining line, and would be stripped completely, and the stuff between braces would be used in some way we can't define at present. I suppose it could have to do with processing embedded escapes. String r = `_{cool RSL header invented by our successors} ..line one ..line two {cool embedded stuff enabled by RSL header} ..`; But there's no way to say at this moment what such a future syntax would look like, and that's my point: For now we can reserve a corner of the RSL encoding space for futures. We might never exercise the option, but it seems wise to buy the option, if it can be bought cheaply as a side effect of restrictions on pathological indent management. I didn't raise this earlier though it was on my mind, but as you see the complexity trade-offs change with built-in indent stripping. And, obviously, there are other ways to extend RSLs in the future which may seem better, such as by adding prefixes before the string quote. If we don't put constraints on cases x and z above, we still have options for future extension. Conversely, even if we are sure we want to make other choices regarding futures, I think it is a safe move to exclude x and z above. ? John -------------- next part -------------- An HTML attachment was scrubbed... URL: From james.laskey at oracle.com Wed May 2 10:11:16 2018 From: james.laskey at oracle.com (James Laskey) Date: Wed, 2 May 2018 07:11:16 -0300 Subject: [raw-string] indentation stripping In-Reply-To: References: <5157CBFA-7068-414E-8590-150713ED1B1A@oracle.com> <463CD19A-767C-4EFA-BCFC-1144E3ABB28B@oracle.com> <3EC8BC69-8BC4-45DE-858F-38DA1DB589C7@oracle.com> Message-ID: Agree. Sent from my iPhone > On May 2, 2018, at 12:39 AM, Guy Steele wrote: > > >>> On May 1, 2018, at 7:04 PM, Jim Laskey wrote: >>> >>> >>> P.S. We can actually have it both ways: do the stripping if and only if the number of tick marks is even. :-b >>> >>> String myNestedExample = ```` >>> String seven = `` >>> +-----------------+ >>> | a nice neat box | >>> +-----------------+ >>> ``; >>> ````; >> >> Groan > > Okay, that part was stupid, but everything before that was quite serious. > > ?Guy > -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Wed May 2 11:17:58 2018 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 2 May 2018 12:17:58 +0100 Subject: `case null:` (here we go) In-Reply-To: References: Message-ID: <30C47241-8D8C-4B5B-82B2-27DB12A9A202@oracle.com> We discussed Kevin?s suggestions when Gavin and I were in Dublin this week. I think the argument for delaying some of these features for the ?next bus full of switch enhancements? is pretty reasonable. With regard to null, the argument I found most compelling is ?you guys still haven?t finished designing how null will work with patterns.? Which is, I must admit, true. Given that the proximate motivation here is that patterns will essentially demand it, delivering it with patterns ? when the full story is in place ? seems a reasonable and prudent choice. With regard to primitives, while I think the semantics are pretty truly settled, supporting the other primitives is mostly (a) for patterns and (b) for completeness; there?s no one banging on the door for switching on floats. So while I see no strong reason to delay, I also see no strong reason to not let this one board the bus with patterns as well. (While switch on long is arguably useful, I would much rather complete the set at once than add things in bit by bit. While we have more delivery vehicles for features, it is probably best that we deliver features in coherent sets where possible.) With regard to the position of default in the switch, since we currently have nothing but constant patterns, let?s defer deciding just how hostile/accomodating we want to be to the quirks of ?default?. When we have richer patterns, I don?t want to allow ?default? to come ahead of cases that it dominates, but those cases can?t occur yet. So harassing users about default placement now seems premature. (As an extreme option, we might even choose to just kill default in patterns in favor of something more well-behaved. So no point expending capital on adjusting people?s use of it right now.) > On May 1, 2018, at 11:38 PM, Kevin Bourrillion wrote: > > On Tue, May 1, 2018 at 2:33 PM, John Rose > wrote: > > On Apr 27, 2018, at 8:59 AM, Kevin Bourrillion > wrote: > > > > 6. That benefit has to be weighed against the damage we will be causing. Here is the meat of it: > > - `default` will no longer mean default. There is really no way around that. > > You have to push the historic hostility to null either to the switch or > the default. So either (as you say) "default doesn't mean default" > or (with the same meaning) "switch doesn't mean switch" or we > break history or we ret-con either switch or default. Pick your poison. > I pick "default means (null-hostile) default". What's so hard about that? > > We can't just localize the null-hostility to `default`, since null-case-less switches that don't have `default` will still throw. > > It has always been `switch` itself that is null-hostile. We can only change that through conceptual contortions; I'm doubtful we can find anything as tidy as what you suggest. > > > > - Null will be treated unaccountably differently from all other values in switch. It becomes harder to explain how switch works -- "sorry, no null" is at least easy. > > It's not easy at all when you *need* to pass nulls. > > Sure. I was making a different point about the conceptual simplicity of the feature. "Easy to explain" and "easy to code your use case" are simply different topics. > > > I don't buy the objection > that we didn't allow nulls before; now we will allow "case var x:" and > (again) the choice is simple and stark: either "var means var" (and > allows null if the type is nullable) or else "var means null-hostile var" > in a switch. Really, you are plumping for "switch is (null-hostile) > switch", but that has the unfortunate effect of making "var" be null > hostile in a switch? > > Would that really look like a null-hostile `var`? To me, it looks like the var allows null but the switch is not letting it through. If I doubt that, I can just look at the stack trace. I assume it would point straight at the switch, as it does today. > > > > Instead it's "well, switch itself allows null, but it assumes you want a `case null` that throws if you don't say otherwise". Looked at without knowing all the baggage, is this not a bit bizarre? > > A bit. Far less bizarre than "Here's a general classifier syntax. > But it doesn't work on null, sorry." > > I suppose we'll agree to disagree on this part. I think it's unfortunate, but still conceptually simple. The reason it rejects null is the exact same reason it always did. (The fact that reason is bad was already conceded at top.) > > > > - Also (back to how this email started), this appears to be the only factor forcing us to introduce a `default, case x` syntax we would never otherwise need - or to mint some other bespoke construction we would, again, never otherwise need. > > We don't need to mint any such construction. We could simply say this: > "You know that old fallthrough thing you sometimes need for combining > cases? Well, you need need it when you want case null to fall through > into default." Null-friendliness, in that story, is just one of the factors > that might move you towards colons and away from arrows. > > And Remi has already sketched a reasonable extension (bespoke > construction) which is good for lots of things: You simply give an > "or" construction along the lines of "case x,y,z:" and then you allow > default to play in the or construction. There's nothing surprising > about that proposal, when you realize that the main use of > fall-through in today's switches is to get the effect of an or > construction, with or without default. What's more natural > than finding a way to do this with arrow-switches? You don't > even need to mention null to justify this, and then easier null > friendliness (with arrow as well as colon) is one of the side-effects. > > This sounds like a persuasive case that the grammar should allow for `default, case null`. But I agree with that already (it was how this thread began). It is fine. I just felt it was noteworthy that we would never have needed the ability to comma-combine default with other case labels if not for this. It's minted for this very special case. > > -- > Kevin Bourrillion | Java Librarian | Google, Inc. | kevinb at google.com -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Wed May 2 12:14:33 2018 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 2 May 2018 13:14:33 +0100 Subject: `case null:` (here we go) In-Reply-To: <326232349.2862.1525038104745.JavaMail.zimbra@u-pem.fr> References: <326232349.2862.1525038104745.JavaMail.zimbra@u-pem.fr> Message-ID: <5AA43567-D3A7-4960-9BBD-5C78C2DB77A8@oracle.com> I think this is a little too strong. default is associated with switch, and we probably do need to massage switch?s handling of default, but we don?t need to make it a full blown pattern. And we probably don?t want to; saying case Foo(default): ? or if (x instanceof Bar(default)) doesn?t make much sense. So I agree it should be rehabilitated, but not by quite that much. > Now that we have decided that the -> syntax doesn't allow fallthrough, i think we have no choice but to allow, default has a possible 'Pattern' in the grammar. -------------- next part -------------- An HTML attachment was scrubbed... URL: From forax at univ-mlv.fr Wed May 2 16:59:47 2018 From: forax at univ-mlv.fr (Remi Forax) Date: Wed, 2 May 2018 18:59:47 +0200 (CEST) Subject: `case null:` (here we go) In-Reply-To: <30C47241-8D8C-4B5B-82B2-27DB12A9A202@oracle.com> References: <30C47241-8D8C-4B5B-82B2-27DB12A9A202@oracle.com> Message-ID: <2066564214.960378.1525280387364.JavaMail.zimbra@u-pem.fr> > De: "Brian Goetz" > ?: "Kevin Bourrillion" > Cc: "amber-spec-experts" > Envoy?: Mercredi 2 Mai 2018 13:17:58 > Objet: Re: `case null:` (here we go) > We discussed Kevin?s suggestions when Gavin and I were in Dublin this week. I > think the argument for delaying some of these features for the ?next bus full > of switch enhancements? is pretty reasonable. I wonder if there are not 3 steps: 1/ the expression switch 2/ the switch on new kinds any type, long, handling of null 3/ the full pattern matching that can do match, extract, backtrack, match, extract, backtrack, etc I've separated 2 and 3 because the translation strategy is very different depending if you can do extraction or not, technically, it's if you can do matching on extracted data that change the translation. > With regard to null, the argument I found most compelling is ?you guys still > haven?t finished designing how null will work with patterns.? Which is, I must > admit, true. Given that the proximate motivation here is that patterns will > essentially demand it, delivering it with patterns ? when the full story is in > place ? seems a reasonable and prudent choice. yes > With regard to primitives, while I think the semantics are pretty truly settled, > supporting the other primitives is mostly (a) for patterns and (b) for > completeness; there?s no one banging on the door for switching on floats. So > while I see no strong reason to delay, I also see no strong reason to not let > this one board the bus with patterns as well. (While switch on long is arguably > useful, I would much rather complete the set at once than add things in bit by > bit. While we have more delivery vehicles for features, it is probably best > that we deliver features in coherent sets where possible.) ok > With regard to the position of default in the switch, since we currently have > nothing but constant patterns, let?s defer deciding just how > hostile/accomodating we want to be to the quirks of ?default?. When we have > richer patterns, I don?t want to allow ?default? to come ahead of cases that it > dominates, but those cases can?t occur yet. So harassing users about default > placement now seems premature. (As an extreme option, we might even choose to > just kill default in patterns in favor of something more well-behaved. So no > point expending capital on adjusting people?s use of it right now.) yes, we can still replace default by '_' with another semantics. R?mi >> On May 1, 2018, at 11:38 PM, Kevin Bourrillion < [ mailto:kevinb at google.com | >> kevinb at google.com ] > wrote: >> On Tue, May 1, 2018 at 2:33 PM, John Rose < [ mailto:john.r.rose at oracle.com | >> john.r.rose at oracle.com ] > wrote: >>> On Apr 27, 2018, at 8:59 AM, Kevin Bourrillion < [ mailto:kevinb at google.com | >>> kevinb at google.com ] > wrote: >>>> 6. That benefit has to be weighed against the damage we will be causing. Here is >>> > the meat of it: >>> > - `default` will no longer mean default. There is really no way around that. >>> You have to push the historic hostility to null either to the switch or >>> the default. So either (as you say) "default doesn't mean default" >>> or (with the same meaning) "switch doesn't mean switch" or we >>> break history or we ret-con either switch or default. Pick your poison. >>> I pick "default means (null-hostile) default". What's so hard about that? >> We can't just localize the null-hostility to `default`, since null-case-less >> switches that don't have `default` will still throw. >> It has always been `switch` itself that is null-hostile. We can only change that >> through conceptual contortions; I'm doubtful we can find anything as tidy as >> what you suggest. >>>> - Null will be treated unaccountably differently from all other values in >>>> switch. It becomes harder to explain how switch works -- "sorry, no null" is at >>> > least easy. >>> It's not easy at all when you *need* to pass nulls. >> Sure. I was making a different point about the conceptual simplicity of the >> feature. "Easy to explain" and "easy to code your use case" are simply >> different topics. >>> I don't buy the objection >>> that we didn't allow nulls before; now we will allow "case var x:" and >>> (again) the choice is simple and stark: either "var means var" (and >>> allows null if the type is nullable) or else "var means null-hostile var" >>> in a switch. Really, you are plumping for "switch is (null-hostile) >>> switch", but that has the unfortunate effect of making "var" be null >>> hostile in a switch? >> Would that really look like a null-hostile `var`? To me, it looks like the var >> allows null but the switch is not letting it through. If I doubt that, I can >> just look at the stack trace. I assume it would point straight at the switch, >> as it does today. >>>> Instead it's "well, switch itself allows null, but it assumes you want a `case >>>> null` that throws if you don't say otherwise". Looked at without knowing all >>> > the baggage, is this not a bit bizarre? >>> A bit. Far less bizarre than "Here's a general classifier syntax. >>> But it doesn't work on null, sorry." >> I suppose we'll agree to disagree on this part. I think it's unfortunate, but >> still conceptually simple. The reason it rejects null is the exact same reason >> it always did. (The fact that reason is bad was already conceded at top.) >>>> - Also (back to how this email started), this appears to be the only factor >>>> forcing us to introduce a `default, case x` syntax we would never otherwise >>>> need - or to mint some other bespoke construction we would, again, never >>> > otherwise need. >>> We don't need to mint any such construction. We could simply say this: >>> "You know that old fallthrough thing you sometimes need for combining >>> cases? Well, you need need it when you want case null to fall through >>> into default." Null-friendliness, in that story, is just one of the factors >>> that might move you towards colons and away from arrows. >>> And Remi has already sketched a reasonable extension (bespoke >>> construction) which is good for lots of things: You simply give an >>> "or" construction along the lines of "case x,y,z:" and then you allow >>> default to play in the or construction. There's nothing surprising >>> about that proposal, when you realize that the main use of >>> fall-through in today's switches is to get the effect of an or >>> construction, with or without default. What's more natural >>> than finding a way to do this with arrow-switches? You don't >>> even need to mention null to justify this, and then easier null >>> friendliness (with arrow as well as colon) is one of the side-effects. >> This sounds like a persuasive case that the grammar should allow for `default, >> case null`. But I agree with that already (it was how this thread began). It is >> fine. I just felt it was noteworthy that we would never have needed the ability >> to comma-combine default with other case labels if not for this. It's minted >> for this very special case. >> -- >> Kevin Bourrillion | Java Librarian | Google, Inc. | [ mailto:kevinb at google.com | >> kevinb at google.com ] -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Wed May 2 17:02:12 2018 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 2 May 2018 13:02:12 -0400 Subject: `case null:` (here we go) In-Reply-To: <2066564214.960378.1525280387364.JavaMail.zimbra@u-pem.fr> References: <30C47241-8D8C-4B5B-82B2-27DB12A9A202@oracle.com> <2066564214.960378.1525280387364.JavaMail.zimbra@u-pem.fr> Message-ID: <3459294C-1430-420C-BBBD-31A52BFBC8DA@oracle.com> > > I wonder if there are not 3 steps: > 1/ the expression switch > 2/ the switch on new kinds any type, long, handling of null > 3/ the full pattern matching that can do match, extract, backtrack, match, extract, backtrack, etc > > I've separated 2 and 3 because the translation strategy is very different depending if you can do extraction or not, technically, it's if you can do matching on extracted data that change the translation. Yes, this is defensible as well. From a perception management perspective, I think its good to deliver batches of related features together, because users are already going to have a hard time remembering what was added in 12 vs 13 vs 14. So remembering ?switch on long in 12 and switch on float in 13? is hard, but ?all the new switch goodies in 13? is easier. That?s not a hard and fast rule but its something to put in the decision mixer. -------------- next part -------------- An HTML attachment was scrubbed... URL: From forax at univ-mlv.fr Wed May 2 17:03:54 2018 From: forax at univ-mlv.fr (forax at univ-mlv.fr) Date: Wed, 2 May 2018 19:03:54 +0200 (CEST) Subject: `case null:` (here we go) In-Reply-To: <5AA43567-D3A7-4960-9BBD-5C78C2DB77A8@oracle.com> References: <326232349.2862.1525038104745.JavaMail.zimbra@u-pem.fr> <5AA43567-D3A7-4960-9BBD-5C78C2DB77A8@oracle.com> Message-ID: <260131090.961032.1525280634636.JavaMail.zimbra@u-pem.fr> > De: "Brian Goetz" > ?: "Remi Forax" > Cc: "Kevin Bourrillion" , "amber-spec-experts" > > Envoy?: Mercredi 2 Mai 2018 14:14:33 > Objet: Re: `case null:` (here we go) > I think this is a little too strong. default is associated with switch, and we > probably do need to massage switch?s handling of default, but we don?t need to > make it a full blown pattern. And we probably don?t want to; saying > case Foo(default): ? > or > if (x instanceof Bar(default)) > doesn?t make much sense. default can be a primary pattern without being a secondary pattern, i.e not available when matching something extracted, in term of grammar those can be separated. > So I agree it should be rehabilitated, but not by quite that much. >> Now that we have decided that the -> syntax doesn't allow fallthrough, i think >> we have no choice but to allow, default has a possible 'Pattern' in the >> grammar. R?mi -------------- next part -------------- An HTML attachment was scrubbed... URL: From daniel.smith at oracle.com Thu May 3 23:07:50 2018 From: daniel.smith at oracle.com (Dan Smith) Date: Thu, 3 May 2018 17:07:50 -0600 Subject: `case null:` (here we go) In-Reply-To: <98C982EE-B1D1-4E13-96E2-E14ADB247F16@oracle.com> References: <98C982EE-B1D1-4E13-96E2-E14ADB247F16@oracle.com> Message-ID: > On May 1, 2018, at 3:26 PM, Guy Steele wrote: > > ? ?case null: default:? IS NOT FALLTHROUGH, IT?S MULTIPLE LABELS!? Guy howled into the uncaring darkness. :-) #TeamMultipleLabels From john.r.rose at oracle.com Thu May 3 23:41:18 2018 From: john.r.rose at oracle.com (John Rose) Date: Thu, 3 May 2018 16:41:18 -0700 Subject: `case null:` (here we go) In-Reply-To: References: <98C982EE-B1D1-4E13-96E2-E14ADB247F16@oracle.com> Message-ID: <5E811241-41CB-4D0E-B323-D116B4DF5CB7@oracle.com> On May 3, 2018, at 4:07 PM, Dan Smith wrote: > >> On May 1, 2018, at 3:26 PM, Guy Steele > wrote: >> >> ? ?case null: default:? IS NOT FALLTHROUGH, IT?S MULTIPLE LABELS!? Guy howled into the uncaring darkness. :-) > > #TeamMultipleLabels There's this invisible semicolon, see? -------------- next part -------------- An HTML attachment was scrubbed... URL: From vicente.romero at oracle.com Fri May 4 19:09:48 2018 From: vicente.romero at oracle.com (Vicente Romero) Date: Fri, 4 May 2018 15:09:48 -0400 Subject: [constables] RFR of constants API In-Reply-To: <4B94BFE7-6D9E-490F-BB68-6ABF5CD095B4@oracle.com> References: <451987dd-9371-552f-908d-e57fdc1f09ff@oracle.com> <1bc4edf2-c016-5fb2-fd45-b235a5e3d580@oracle.com> <4B94BFE7-6D9E-490F-BB68-6ABF5CD095B4@oracle.com> Message-ID: <47a62c30-cc05-89f2-86b6-ed6de6444bec@oracle.com> please review another iteration of the constants API at [3]. This one removes the Lookup argument from describeConstable() plus adds interfaces FieldDescriptor, TypeDescriptor and MethodDescriptor Thanks, Vicente [3] http://cr.openjdk.java.net/~vromero/constant.api/webrev.01/constants.api.patch On 05/01/2018 01:43 PM, Brian Goetz wrote: > To be clear: we?re asking for an *API review*. No need to review the code right now, just the API and the specs. > >> On May 1, 2018, at 6:32 PM, Vicente Romero wrote: >> >> Please review also the related CSR: https://bugs.openjdk.java.net/browse/JDK-8202031 >> >> Thanks, >> Vicente >> >> On 04/27/2018 01:31 PM, Vicente Romero wrote: >>> Hi all, >>> >>> Please review the current proposal of the constants API, which are nominal descriptor types defined in pkg java.lang.invoke.constant. The code can be found at [1]. This API is being developed in the context of JEP 303: Intrinsics for the LDC and INVOKEDYNAMIC Instructions [2] >>> >>> Thanks in advance for your comments, >>> Vicente >>> >>> [1] http://cr.openjdk.java.net/~vromero/constant.api/webrev.00 >>> [2] http://openjdk.java.net/jeps/303 From brian.goetz at oracle.com Tue May 8 16:59:01 2018 From: brian.goetz at oracle.com (Brian Goetz) Date: Tue, 8 May 2018 12:59:01 -0400 Subject: `case null:` (here we go) In-Reply-To: <30C47241-8D8C-4B5B-82B2-27DB12A9A202@oracle.com> References: <30C47241-8D8C-4B5B-82B2-27DB12A9A202@oracle.com> Message-ID: <533b24b3-2ed2-6470-57b1-bbb081d047df@oracle.com> Hearing no responses on each of these, I'm going to say we should: ?- defer case null ?- defer all new primitive targets ?- do nothing now about default placement, since all switches will still be constant switches in the current iteration. These can all be deferred to the next bus full of switch improvements (of which there is at least one, if not two, in our near-ish future.) On 5/2/2018 7:17 AM, Brian Goetz wrote: > We discussed Kevin?s suggestions when Gavin and I were in Dublin this > week. ?I think the argument for delaying some of these features for > the ?next bus full of switch enhancements? is pretty reasonable. > > With regard to null, the argument I found most compelling is ?you guys > still haven?t finished designing how null will work with patterns.? > ?Which is, I must admit, true. ?Given that the proximate motivation > here is that patterns will essentially demand it, delivering it with > patterns ? when the full story is in place ? seems a reasonable and > prudent choice. > > With regard to primitives, while I think the semantics are pretty > truly settled, supporting the other primitives is mostly (a) for > patterns and (b) for completeness; there?s no one banging on the door > for switching on floats. ?So while I see no strong reason to delay, I > also see no strong reason to not let this one board the bus with > patterns as well. ?(While switch on long is arguably useful, I would > much rather complete the set at once than add things in bit by bit. > ?While we have more delivery vehicles for features, it is probably > best that we deliver features in coherent sets where possible.) > > With regard to the position of default in the switch, since we > currently have nothing but constant patterns, let?s defer deciding > just how hostile/accomodating we want to be to the quirks of > ?default?. ?When we have richer patterns, I don?t want to allow > ?default? to come ahead of cases that it dominates, but those cases > can?t occur yet. ?So harassing users about default placement now seems > premature. ?(As an extreme option, we might even choose to just kill > default in patterns in favor of something more well-behaved. ?So no > point expending capital on adjusting people?s use of it right now.) > > > >> On May 1, 2018, at 11:38 PM, Kevin Bourrillion > > wrote: >> >> On Tue, May 1, 2018 at 2:33 PM, John Rose > > wrote: >> >> On Apr 27, 2018, at 8:59 AM, Kevin Bourrillion > > wrote: >> > >> > 6. That benefit has to be weighed against the damage we will be >> causing. Here is the meat of it: >> > - `default` will no longer mean default. There is really no way >> around that. >> >> You have to push the historic hostility to null either to the >> switch or >> the default.? So either (as you say) "default doesn't mean default" >> or (with the same meaning) "switch doesn't mean switch" or we >> break history or we ret-con either switch or default.? Pick your >> poison. >> I pick "default means (null-hostile) default". What's so hard >> about that? >> >> >> We can't just localize the null-hostility to `default`, since >> null-case-less switches that don't have `default` will still throw. >> >> It has always been `switch` itself that is null-hostile. We can only >> change that through conceptual contortions; I'm doubtful we can find >> anything as tidy as what you suggest. >> >> >> > - Null will be treated unaccountably differently from all other >> values in switch. It becomes harder to explain how switch works >> -- "sorry, no null" is at least easy. >> >> It's not easy at all when you *need* to pass nulls. >> >> >> Sure. I was making a different point about the conceptual simplicity >> of the feature. "Easy to explain" and "easy to code your use case" >> are simply different topics. >> >> >> I don't buy the objection >> that we didn't allow nulls before; now we will allow "case var >> x:" and >> (again) the choice is simple and stark:? either "var means var" (and >> allows null if the type is nullable) or else "var means >> null-hostile var" >> in a switch.? Really, you are plumping for "switch is (null-hostile) >> switch", but that has the unfortunate effect of making "var" be null >> hostile in a switch? >> >> >> Would that really look like a null-hostile `var`? To me, it looks >> like the var allows null but the switch is not letting it through. If >> I doubt that, I can just look at the stack trace. I assume it would >> point straight at the switch, as it does today. >> >> >> > Instead it's "well, switch itself allows null, but it assumes >> you want a `case null` that throws if you don't say otherwise". >> Looked at without knowing all the baggage, is this not a bit bizarre? >> >> >> A bit.? Far less bizarre than "Here's a general classifier syntax. >> But it doesn't work on null, sorry." >> >> >> I suppose we'll agree to disagree on this part. I think it's >> unfortunate, but still conceptually simple. The reason it rejects >> null is the exact same?reason it always did. (The fact that reason is >> /bad/?was already conceded at top.) >> >> > - Also (back to how this email started), this appears to be the >> only factor forcing us to introduce a `default, case x` syntax we >> would never otherwise need - or to mint some other bespoke >> construction we would, again, never otherwise need. >> >> We don't need to mint any such construction.? We could simply say >> this: >> "You know that old fallthrough thing you sometimes need for combining >> cases?? Well, you need need it when you want case null to fall >> through >> into default."? Null-friendliness, in that story, is just one of >> the factors >> that might move you towards colons and away from arrows. >> >> And Remi has already sketched a reasonable extension (bespoke >> construction) which is good for lots of things: You simply give an >> "or" construction along the lines of "case x,y,z:" and then you allow >> default to play in the or construction.? There's nothing surprising >> about that proposal, when you realize that the main use of >> fall-through in today's switches is to get the effect of an or >> construction, with or without default.? What's more natural >> than finding a way to do this with arrow-switches?? You don't >> even need to mention null to justify this, and then easier null >> friendliness (with arrow as well as colon) is one of the >> side-effects. >> >> >> This sounds like a persuasive case that the grammar should allow for >> `default, case null`. But I agree with that already (it was how this >> thread began). It is fine. I just felt it was noteworthy that we >> would never have needed the ability to comma-combine default with >> other case labels if not for this. It's minted for this very special >> case. >> >> -- >> Kevin Bourrillion?|?Java Librarian |?Google, Inc.?|kevinb at google.com >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From vicente.romero at oracle.com Tue May 8 17:35:55 2018 From: vicente.romero at oracle.com (Vicente Romero) Date: Tue, 8 May 2018 13:35:55 -0400 Subject: [constables] RFR of constants API In-Reply-To: <47a62c30-cc05-89f2-86b6-ed6de6444bec@oracle.com> References: <451987dd-9371-552f-908d-e57fdc1f09ff@oracle.com> <1bc4edf2-c016-5fb2-fd45-b235a5e3d580@oracle.com> <4B94BFE7-6D9E-490F-BB68-6ABF5CD095B4@oracle.com> <47a62c30-cc05-89f2-86b6-ed6de6444bec@oracle.com> Message-ID: <0b88aada-9fc1-b464-4d15-6a03319fe211@oracle.com> I have made a tweak to the last iteration [4], removing the @Foldable annotation that shouldn't be part of the API as targeted to 11 Thanks, Vicente [4] http://cr.openjdk.java.net/~vromero/constant.api/webrev.02/constants.api.patch On 05/04/2018 03:09 PM, Vicente Romero wrote: > please review another iteration of the constants API at [3]. This one > removes the Lookup argument from describeConstable() plus adds > interfaces FieldDescriptor, TypeDescriptor and MethodDescriptor > > Thanks, > Vicente > > [3] > http://cr.openjdk.java.net/~vromero/constant.api/webrev.01/constants.api.patch > > On 05/01/2018 01:43 PM, Brian Goetz wrote: >> To be clear: we?re asking for an *API review*. No need to review the >> code right now, just the API and the specs. >> >>> On May 1, 2018, at 6:32 PM, Vicente Romero >>> wrote: >>> >>> Please review also the related CSR: >>> https://bugs.openjdk.java.net/browse/JDK-8202031 >>> >>> Thanks, >>> Vicente >>> >>> On 04/27/2018 01:31 PM, Vicente Romero wrote: >>>> Hi all, >>>> >>>> Please review the current proposal of the constants API, which are >>>> nominal descriptor types defined in pkg java.lang.invoke.constant. >>>> The code can be found at [1]. This API is being developed in the >>>> context of JEP 303: Intrinsics for the LDC and INVOKEDYNAMIC >>>> Instructions [2] >>>> >>>> Thanks in advance for your comments, >>>> Vicente >>>> >>>> [1] http://cr.openjdk.java.net/~vromero/constant.api/webrev.00 >>>> [2] http://openjdk.java.net/jeps/303 > From maurizio.cimadamore at oracle.com Tue May 8 17:50:38 2018 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Tue, 8 May 2018 18:50:38 +0100 Subject: [constables] RFR of constants API In-Reply-To: <47a62c30-cc05-89f2-86b6-ed6de6444bec@oracle.com> References: <451987dd-9371-552f-908d-e57fdc1f09ff@oracle.com> <1bc4edf2-c016-5fb2-fd45-b235a5e3d580@oracle.com> <4B94BFE7-6D9E-490F-BB68-6ABF5CD095B4@oracle.com> <47a62c30-cc05-89f2-86b6-ed6de6444bec@oracle.com> Message-ID: <8d63064c-6bbd-af20-be66-31184f006e95@oracle.com> The [Type, Method, Field]Descriptor API looks neat - I have two comments on this: * I believe the name descriptor is going to be confusing with the rest of the API, as there are a lot of classes whose name ends with 'Desc' * we discussed internally to sprinkle parameters on java/lang/reflect/Member (e.g. have a type parameter T <: TypeDescriptor, and have a method type() which returns a T). That way we could have Member to be a full live representation of a reflective member, including access to owner (a Class), name (String) and, finally, a type (some TypeDescriptor T). Maurizio On 04/05/18 20:09, Vicente Romero wrote: > please review another iteration of the constants API at [3]. This one > removes the Lookup argument from describeConstable() plus adds > interfaces FieldDescriptor, TypeDescriptor and MethodDescriptor > > Thanks, > Vicente > > [3] > http://cr.openjdk.java.net/~vromero/constant.api/webrev.01/constants.api.patch > > On 05/01/2018 01:43 PM, Brian Goetz wrote: >> To be clear: we?re asking for an *API review*. No need to review the >> code right now, just the API and the specs. >> >>> On May 1, 2018, at 6:32 PM, Vicente Romero >>> wrote: >>> >>> Please review also the related CSR: >>> https://bugs.openjdk.java.net/browse/JDK-8202031 >>> >>> Thanks, >>> Vicente >>> >>> On 04/27/2018 01:31 PM, Vicente Romero wrote: >>>> Hi all, >>>> >>>> Please review the current proposal of the constants API, which are >>>> nominal descriptor types defined in pkg java.lang.invoke.constant. >>>> The code can be found at [1]. This API is being developed in the >>>> context of JEP 303: Intrinsics for the LDC and INVOKEDYNAMIC >>>> Instructions [2] >>>> >>>> Thanks in advance for your comments, >>>> Vicente >>>> >>>> [1] http://cr.openjdk.java.net/~vromero/constant.api/webrev.00 >>>> [2] http://openjdk.java.net/jeps/303 > From brian.goetz at oracle.com Tue May 8 18:06:10 2018 From: brian.goetz at oracle.com (Brian Goetz) Date: Tue, 8 May 2018 14:06:10 -0400 Subject: [constables] RFR of constants API In-Reply-To: <8d63064c-6bbd-af20-be66-31184f006e95@oracle.com> References: <451987dd-9371-552f-908d-e57fdc1f09ff@oracle.com> <1bc4edf2-c016-5fb2-fd45-b235a5e3d580@oracle.com> <4B94BFE7-6D9E-490F-BB68-6ABF5CD095B4@oracle.com> <47a62c30-cc05-89f2-86b6-ed6de6444bec@oracle.com> <8d63064c-6bbd-af20-be66-31184f006e95@oracle.com> Message-ID: <78bbdb32-5342-2240-b277-acb089741f87@oracle.com> On 5/8/2018 1:50 PM, Maurizio Cimadamore wrote: > The [Type, Method, Field]Descriptor API looks neat - I have two > comments on this: > > * I believe the name descriptor is going to be confusing with the rest > of the API, as there are a lot of classes whose name ends with 'Desc' Then perhaps these types belong somewhere else besides jlic? > * we discussed internally to sprinkle parameters on > java/lang/reflect/Member (e.g. have a type parameter T <: > TypeDescriptor, and have a method type() which returns a T). That > way we could have Member to be a full live representation of a > reflective member, including access to owner (a Class), name > (String) and, finally, a type (some TypeDescriptor T). Yes, this patch doesn't yet do this but we can certainly go there once we have agreement on the approach. From brian.goetz at oracle.com Tue May 8 19:31:37 2018 From: brian.goetz at oracle.com (Brian Goetz) Date: Tue, 8 May 2018 15:31:37 -0400 Subject: Continue in switch Message-ID: This is not an urgent issue for the expression switch work, but I'd like to get some ideas about how we will want to handle guards in pattern switch, as we may want to lay some groundwork in the form of warnings now. Initially we considered explicit guards: ??? case Foo(var x, var y) ??????? where x <= y: ... (Note that there is a connection between nested patterns and guards; a nested pattern P(Q) is equivalent to P(x) with a guard of x matches Q.) While this is semantically attractive (the guard condition is declarative), I worry that it is not likely to be very satisfying in practice.? In toy examples, it looks great, but as examples expand to a more realistic scale, the pattern, guard, and imperative consequence can easily mush together.? For example: case Point(var x, var y) where x > 0 && y > 0 && x < y -> x + y; You can try reformatting: case Point(var x, var y) where x > 0 && y > 0 && x < y -> x + y; but its not that much better.? So, I'm pretty down on this approach right now, and I think several others are as well. An alternative is to provide an imperative means to refine the switch selection.? The obvious choice is to give "continue" semantics within a switch: ??? case Foo(var x, var y): ??????? if (x > y) ??????????? continue;? // keep processing at next case ??????? foo(x, y); ??????? break; Continuing in a switch means "keep testing the target against case labels, starting with the next case label."? This is only a short hop from the current notion of continue in for/while loops. Of course, compatibility raises its ugly head.? You could have a switch today with continue-in-switch-in-for: ??? for (...) { ??????? switch (x) { ??????????? case 0: continue;? // valid today, means continue the loop ??????? } ??? } This code works today, which means a continue in a switch in a loop would be ambiguous, and would require a label. As a means of mitigation, we could also allow the syntax "continue switch" or "continue while" to mean "continue from the innermost switch/while".? This is arguably more readable, and reduces the number of cases where a label would be required. If we're going to go the "continue" route, we might want to consider warning now in cases where there would be an ambiguity, suggesting that the user use a labeled continue, to move codebases in the right direction. If continue is the right notion, our choice is essentially between: ?- drive towards continue in switch working like it does in everything else, and deal with ambiguities (switch in loop) as they come up; ?- drive towards something that looks sufficiently different from "naked" continue (continue with label, "continue switch") in switches, and accept there will be a permanent seam (in switch you do it this way, in loops, this other way.) From john.r.rose at oracle.com Tue May 8 20:31:12 2018 From: john.r.rose at oracle.com (John Rose) Date: Tue, 8 May 2018 13:31:12 -0700 Subject: Continue in switch In-Reply-To: References: Message-ID: <004C06F2-4A44-46CC-9327-CC47BC5FAC14@oracle.com> On May 8, 2018, at 12:31 PM, Brian Goetz wrote: > > If continue is the right notion, our choice is essentially between: > - drive towards continue in switch working like it does in everything else, and deal with ambiguities (switch in loop) as they come up; > - drive towards something that looks sufficiently different from "naked" continue (continue with label, "continue switch") in switches, and accept there will be a permanent seam (in switch you do it this way, in loops, this other way.) (Cards on table: I'm on Team `continue switch;` and $0.02 follows.) The permanent seam doesn't bother me very much, for the following explainable reason: Switch is not a proper loop, although it is a continuable statement. If you want to continue a continuable statement that isn't a loop, you have to be specific. (And you should be specific anyway if your code is deeply nested.) Classic Java loops while/for/do-while are (usually) not statically bounded. Depending on their logic they can run an arbitrary number of times. Now, by saying "continue" in a switch, we are ascribing it a loopish nature. And this is true, because a switch is (in our new theory) a _decision chain_, that is a finite, sequence of statically defined predicates which are tested in order until one matches. The number of predicates is arbitrary (like a loop) but they are listed statically (unlike a loop). In both loops and decision chains there is a well-defined and very useful control flow operation, which is "continue to the next step". The next step of the loop is to run the iteration and execute the loop body again. The next step of the decision chain is to abandon the current predicate and test the next one. The "continue" concept fits the bill for both. But compatibility says a bare "continue" must go to a proper loop, not a decision chain. Thus, bare continue always reaches the enclosing proper loop, but "continue switch" or "continue L" (L labeling the switch) reaches the enclosing switch, because although switches are not proper loops, they are loopish, they are continuable even if they cannot run forever like a loop. Explained this way, the "seam" Brian is referring to is an artifact, not of history, but of the distinction between proper loops and other continuable ("loopish") constructs. Personally I'd be fine with this seam as a permanent thing. The seam can be reduced also, and I think that is what Brian is aiming at. Bare "continue" in an expression switch will always be unambiguous, since it *cannot* reach an enclosing loop (no branches out from an expression.) Sailing yet more closely to the wind: Bare "continue" in a switch *not* nested in a loop is also unambiguous, since there's no proper loop to reach. Brian, are you thinking that bare continue, inside switch, *inside loop*, is an *ambiguity error*? That would be worth warning about about: Today's correct code would become an error tomorrow: for (;;) { switch (x) { case 0: continue; // Error/warning: ambiguous unlabeled continue } } The message could say "unlabeled continue is ambiguous when nested in both switch and proper loop, repair by saying either 'continue switch' or 'continue for', or use a label." In that case, the warnings could be sent even after feature adoption. Eventually when the warnings turn to errors, no code changes semantics, but some code breaks. Or make it be a warning forever. OK, now for some "decision chain theory". Besides switches, decision chains have two other forms which are worth contemplating, as elucidating the essential structure in another surface form, and also as a possible refactoring target. switch (x) { case P1 -> S1; // suppressing legacy fallthrough for simplicity case P2 -> S2; ? } if (x matches P1) S1; else if (x matches P2) S2; else ? for (Function> casef : List.of( x -> x matches P1 ? Optional.of(S1) : Optional.none(), x -> x matches P2 ? Optional.of(S2) : Optional.none() )) { var y = casef.apply(x); if (!y.isPresent()) continue; result = y.get(); break; } The third form seems exotic but it is a coding pattern some of us have surely used for decision chains, test lists, and on similar occasions. (I have!) The continue keyword is native in the third form, and corresponds exactly to the proposed continue [switch] form for the first form. OK, now I'm going to push farther, by your leave, with a thought experiment exploring and extending the correspondence between the first two forms of decision chain, switch and if/else. The second form is of course a far more common refactoring of decision chains; in fact one of the motivations of pattern-switch is to refactor many existing if/else decision chains into easier-to-read switches. Here's an example: if (x matches Plus(0.0, var a)) { res = a; } else if (x matches Plus(var a, 0.0)) { res = a; } else { res = x; } This simplifies to a switch-based decision chain: switch (x) { case Plus(0.0, var a) -> res = a; case Plus(var a, 0.0) -> res = a; default -> res = x; } Here's the odd part: The close duality between if and switch forms suggests that we should also consider "continue if", as a form which means "find the innermost enclosing 'if' with a continuation point and branch to it". What on earth is a continuation point of an 'if'? That's easy, it's spelled "else". In other words, if/else (not just if w/o else) is loopish too. (And "if" without an "else" gets passed by from "continue" since there is no continuation point.) Here's the same example, but enhanced with guards (isNan): switch (x) { case Plus(0.0, var a): if (a.isNan()) continue switch; res = a; break; case Plus(var a, 0.0): if (a.isNan()) continue switch; res = a; break; default: res = x; } What's the equivalent if/else decision chain, with the same guards? if (x matches Plus(0.0, var a) && !a.isNan()) { res = a; } else if (x matches Plus(var a, 0.0) && !a.isNan()) { res = a; } else { res = x; } But this one pushes the guards to one side, making the basic structure easier to read (in some cases, not all!): if (x matches Plus(0.0, var a)) { if (a.isNan()) continue if; res = a; } else if (x matches Plus(var a, 0.0)) { if (a.isNan()) continue if; res = a; } else { res = x; } How often have you added a complicated "&& !foo" rider expression to an otherwise clear "if/else" chain, just to push control forward towards the next "else" which miight handle your marginal "foo" condition? I have, many times. I think "continue if" would have been helpful. (Note that "break if" is slightly useful too, if you just want to execute a localized action for some marginal condition and be done. Today you need to nest your main action equally with the marginal action, putting an if/else inside the if/else. That's not too bad, but we might sometime might prefer the option of making the marginal case be an asymmetrical add-on to the main flow of logic.) ? John -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Tue May 8 21:21:13 2018 From: brian.goetz at oracle.com (Brian Goetz) Date: Tue, 8 May 2018 17:21:13 -0400 Subject: Continue in switch In-Reply-To: <004C06F2-4A44-46CC-9327-CC47BC5FAC14@oracle.com> References: <004C06F2-4A44-46CC-9327-CC47BC5FAC14@oracle.com> Message-ID: Yes, that's what I'm aiming at.? If you have something simple where the switch is not enclosed in a loop, then bare "continue" does the obvious thing; if there is an ambiguity, you have to say "continue label" or "continue switch".? Hence the warning now for when that might happen later. On 5/8/2018 4:31 PM, John Rose wrote: > > Brian, are you thinking that bare continue, inside switch, *inside loop*, > is an *ambiguity error*? ?That would be worth warning about about: > Today's correct code would become an error tomorrow: > > for (;;) { > ? ?switch (x) { > ? ? ? case 0: > ? ? ? ? continue; ?// Error/warning: ambiguous unlabeled continue > ? ?} > } > > The message could say "unlabeled continue is ambiguous when > nested in both switch and proper loop, repair by saying either > 'continue switch' or 'continue for', or use a label." > > In that case, the warnings could be sent even after feature adoption. > Eventually when the warnings turn to errors, no code changes > semantics, but some code breaks. ?Or make it be a warning forever. From forax at univ-mlv.fr Tue May 8 21:37:16 2018 From: forax at univ-mlv.fr (Remi Forax) Date: Tue, 8 May 2018 23:37:16 +0200 (CEST) Subject: Continue in switch In-Reply-To: <004C06F2-4A44-46CC-9327-CC47BC5FAC14@oracle.com> References: <004C06F2-4A44-46CC-9327-CC47BC5FAC14@oracle.com> Message-ID: <1345367187.694149.1525815436523.JavaMail.zimbra@u-pem.fr> We can twist the semantics of continue or decide to go with another (local) keyword which i think is a better idea here. The syntax will be keyword; which is not a valid syntax for a local variable, so any identifier can be used. Like var, i also think we should choose a name which is not a valid name for a local variable if you follow the coding convention, so by example a name composed of two words with no camel case. I propose nextcase; but i'm sure people will find a better alternative name. cheers, R?mi > De: "John Rose" > ?: "Brian Goetz" > Cc: "amber-spec-experts" > Envoy?: Mardi 8 Mai 2018 22:31:12 > Objet: Re: Continue in switch > On May 8, 2018, at 12:31 PM, Brian Goetz < [ mailto:brian.goetz at oracle.com | > brian.goetz at oracle.com ] > wrote: >> If continue is the right notion, our choice is essentially between: >> - drive towards continue in switch working like it does in everything else, and >> deal with ambiguities (switch in loop) as they come up; >> - drive towards something that looks sufficiently different from "naked" >> continue (continue with label, "continue switch") in switches, and accept there >> will be a permanent seam (in switch you do it this way, in loops, this other >> way.) > (Cards on table: I'm on Team `continue switch;` and $0.02 follows.) > The permanent seam doesn't bother me very much, for the following > explainable reason: Switch is not a proper loop, although it is a > continuable statement. If you want to continue a continuable > statement that isn't a loop, you have to be specific. (And you > should be specific anyway if your code is deeply nested.) > Classic Java loops while/for/do-while are (usually) not statically > bounded. Depending on their logic they can run an arbitrary > number of times. > Now, by saying "continue" in a switch, we are ascribing it a loopish > nature. And this is true, because a switch is (in our new theory) > a _decision chain_, that is a finite, sequence of statically defined > predicates which are tested in order until one matches. The number > of predicates is arbitrary (like a loop) but they are listed statically > (unlike a loop). > In both loops and decision chains there is a well-defined and very > useful control flow operation, which is "continue to the next step". > The next step of the loop is to run the iteration and execute the > loop body again. The next step of the decision chain is to abandon > the current predicate and test the next one. > The "continue" concept fits the bill for both. But compatibility says > a bare "continue" must go to a proper loop, not a decision chain. > Thus, bare continue always reaches the enclosing proper loop, > but "continue switch" or "continue L" (L labeling the switch) > reaches the enclosing switch, because although switches are > not proper loops, they are loopish, they are continuable even > if they cannot run forever like a loop. > Explained this way, the "seam" Brian is referring to is an artifact, > not of history, but of the distinction between proper loops and > other continuable ("loopish") constructs. Personally I'd be fine > with this seam as a permanent thing. > The seam can be reduced also, and I think that is what Brian > is aiming at. Bare "continue" in an expression switch will always be > unambiguous, since it *cannot* reach an enclosing loop (no branches > out from an expression.) Sailing yet more closely to the wind: Bare > "continue" in a switch *not* nested in a loop is also unambiguous, > since there's no proper loop to reach. > Brian, are you thinking that bare continue, inside switch, *inside loop*, > is an *ambiguity error*? That would be worth warning about about: > Today's correct code would become an error tomorrow: > for (;;) { > switch (x) { > case 0: > continue; // Error/warning: ambiguous unlabeled continue > } > } > The message could say "unlabeled continue is ambiguous when > nested in both switch and proper loop, repair by saying either > 'continue switch' or 'continue for', or use a label." > In that case, the warnings could be sent even after feature adoption. > Eventually when the warnings turn to errors, no code changes > semantics, but some code breaks. Or make it be a warning forever. > OK, now for some "decision chain theory". > Besides switches, decision chains have two other forms which are > worth contemplating, as elucidating the essential structure in another > surface form, and also as a possible refactoring target. > switch (x) { > case P1 -> S1; // suppressing legacy fallthrough for simplicity > case P2 -> S2; > ? > } > if (x matches P1) S1; > else if (x matches P2) S2; > else ? > for (Function> casef : List.of( > x -> x matches P1 ? Optional.of(S1) : Optional.none(), > x -> x matches P2 ? Optional.of(S2) : Optional.none() > )) { > var y = casef.apply(x); > if (!y.isPresent()) continue; > result = y.get(); > break; > } > The third form seems exotic but it is a coding pattern some > of us have surely used for decision chains, test lists, and > on similar occasions. (I have!) > The continue keyword is native in the third form, and corresponds > exactly to the proposed continue [switch] form for the first form. > OK, now I'm going to push farther, by your leave, with a thought > experiment exploring and extending the correspondence between > the first two forms of decision chain, switch and if/else. > The second form is of course a far more common refactoring of > decision chains; in fact one of the motivations of pattern-switch > is to refactor many existing if/else decision chains into easier-to-read > switches. Here's an example: > if (x matches Plus(0.0, var a)) { > res = a; > } else if (x matches Plus(var a, 0.0)) { > res = a; > } else { > res = x; > } > This simplifies to a switch-based decision chain: > switch (x) { > case Plus(0.0, var a) -> res = a; > case Plus(var a, 0.0) -> res = a; > default -> res = x; > } > Here's the odd part: The close duality between if and switch forms > suggests that we should also consider "continue if", as a form which > means "find the innermost enclosing 'if' with a continuation point > and branch to it". What on earth is a continuation point of an 'if'? > That's easy, it's spelled "else". In other words, if/else (not just > if w/o else) is loopish too. (And "if" without an "else" gets passed > by from "continue" since there is no continuation point.) > Here's the same example, but enhanced with guards (isNan): > switch (x) { > case Plus(0.0, var a): > if (a.isNan()) continue switch; > res = a; > break; > case Plus(var a, 0.0): > if (a.isNan()) continue switch; > res = a; > break; > default: > res = x; > } > What's the equivalent if/else decision chain, with the same guards? > if (x matches Plus(0.0, var a) && !a.isNan()) { > res = a; > } else if (x matches Plus(var a, 0.0) && !a.isNan()) { > res = a; > } else { > res = x; > } > But this one pushes the guards to one side, making the > basic structure easier to read (in some cases, not all!): > if (x matches Plus(0.0, var a)) { > if (a.isNan()) continue if; > res = a; > } else if (x matches Plus(var a, 0.0)) { > if (a.isNan()) continue if; > res = a; > } else { > res = x; > } > How often have you added a complicated "&& !foo" rider expression > to an otherwise clear "if/else" chain, just to push control forward towards > the next "else" which miight handle your marginal "foo" condition? > I have, many times. I think "continue if" would have been helpful. > (Note that "break if" is slightly useful too, if you just want to execute > a localized action for some marginal condition and be done. Today > you need to nest your main action equally with the marginal action, > putting an if/else inside the if/else. That's not too bad, but we might > sometime might prefer the option of making the marginal case be > an asymmetrical add-on to the main flow of logic.) > ? John -------------- next part -------------- An HTML attachment was scrubbed... URL: From daniel.smith at oracle.com Tue May 8 22:37:09 2018 From: daniel.smith at oracle.com (Dan Smith) Date: Tue, 8 May 2018 16:37:09 -0600 Subject: Treatment of nested 'break' Message-ID: <2C0702D8-31BF-4BAF-A695-0E2B2A41C868@oracle.com> I am concerned about the treatment of 'break' statements in switch expressions. The following seems like something that would be very natural to do: boolean x = switch (expr()) { case FOO -> { for (String s : strings) { if (s.isEmpty()) break false; } break true; } case BAR -> true; default -> false; }; This is specified as a compiler error, even though the intent is clear, and we allow code of this shape in other contexts (compare, e.g., a method body). I think what prompted this degree of brittleness is worries about ambiguity between label breaks and value breaks. Let me suggest this disambiguation strategy instead (in the spirit of 6.5.2): - If an unqualified name appears immediately after a 'break' and occurs in the scope of a label with that name, it is a LabelName - Otherwise, it is an ExpressionName (In practice, I expect it to be rare for a real ambiguity to exist between a label name and a variable name.) With that disambiguation rule in place, we can then treat value breaks much like label breaks: "If no switch expression in the immediately enclosing method, constructor, initializer, or lambda body contains the break statement, a compile-time error occurs." (No special rule about appearing inside a 'while', 'for', etc.) From daniel.smith at oracle.com Tue May 8 23:08:11 2018 From: daniel.smith at oracle.com (Dan Smith) Date: Tue, 8 May 2018 17:08:11 -0600 Subject: JEP325: Switch expressions spec In-Reply-To: <0CF1227E-79B4-48A1-A227-86466EDB6219@oracle.com> References: <8E28CEE7-0F85-485A-9AE7-15801522B06C@oracle.com> <0CF1227E-79B4-48A1-A227-86466EDB6219@oracle.com> Message-ID: <5A242ACE-EF32-4310-BE13-52A95EC3EC18@oracle.com> 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 unclear exactly what this pseudo-code means (which JLS rules apply to it?), and there tends to be a lot of tedious work to make the pseudo-code valid (what if the statement can't complete normally?). Here it would be much clearer to just describe the run-time behavior of 'switch' in terms of clauses. 14.11 "If multiple statements are needed then a block (14.2) should be used": this is a useful illustration, but in the context of Chapter 14, probably too chatty. It's a given that a Block can be used wherever you want multiple statements. Compare the spec for the 'while' loop (14.12). 14.11: discussion about unboxing would be clearer if it were limited to a bullet defining the rule for matching a constant expression. (I might separate "constant expression of a primitive type" as a distinct case in the definition.) 14.11: "evaluates to the null" 14.11 "A case label can contain multiple patterns, and is said to match if": again, I want to push this down into a definition of "match" somewhere. Example 14.11-1: Some further illustration is good here, but this sequencing feels very much like it was tacked on. Something like "what's the difference between two forms of switch blocks?" might be a better way to approach the discussion. 14.15, 14.16, 14.17 "immediately enclosing method, constructor, or initializer": this list should consistently include lambda bodies and switch expression blocks as well. (In the 'return' case, switch expression blocks should also be included in the rule about illegal containers.) 14.15, 14.16, 14.17 "not permitted to transfer control through a switch expression": with the change to include switch expression blocks in the other rule, there's no need for a special rule that applies to switch expressions. In fact, calling them out suggests that they are somehow treated differently than lambda bodies, when they are not. These paragraphs can be deleted. 15.15 "and the switch expression": should be green 15.29: this is probably the wrong section number; we'll have to ask Alex how much disruption he wants to tolerate. 15.29 "In contrast to a switch statement": I think the right thing to say about the contrast is this: it's impossible for the expression to complete normally without a value, so the expression must not leave out some cases. 15.29 "The rules for the selector expression": I approve of reuse, but I think this is small enough that it would be better to copy/paste the rule here. 15.29 "Can return": I don't think this requires so much discussion. Just a couple of sentences: "It is a compile-time error if the Block of a SwitchExpressionClause can complete normally. It is a compile-time error if statements of the last SwitchBlockStatementGroup can complete normally." 15.29 "the switch expression completes normally": More conventionally, "the value of the switch expression is ..." From maurizio.cimadamore at oracle.com Tue May 8 23:37:25 2018 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Wed, 9 May 2018 00:37:25 +0100 Subject: Treatment of nested 'break' In-Reply-To: <2C0702D8-31BF-4BAF-A695-0E2B2A41C868@oracle.com> References: <2C0702D8-31BF-4BAF-A695-0E2B2A41C868@oracle.com> Message-ID: <17d322ee-6b97-eb95-3cc2-fb464822c081@oracle.com> On 08/05/18 23:37, Dan Smith wrote: > I think what prompted this degree of brittleness is worries about ambiguity between label breaks and value breaks. Let me suggest this disambiguation strategy instead (in the spirit of 6.5.2): > - If an unqualified name appears immediately after a 'break' and occurs in the scope of a label with that name, it is a LabelName > - Otherwise, it is an ExpressionName I might be wrong, but I think the brittleness is only tangentially related to disambiguation of label vs. value. I believe what we also wanted to avoid was for a 'break expression' to appear nested inside another break-y context - e.g. another statement switch - example: boolean v = switch (e1) { ??? case "One": ?????????? switch (e2) { ????????????????? case 42: break false; // <----- ?????????? } ?????????? break true; ??? ... } The fact that we can 'break false' from a switch (statement) nested inside a switch (expression) is visually very confusing - and I've seen code snippets (one of javac regression tests) where it was virtually impossible to determine whether a switch was an expression or a statement because of this fact. So, maybe the brittleness can be tweaked, but I'd be wary of completely remove it. Maurizio From brian.goetz at oracle.com Wed May 9 01:16:13 2018 From: brian.goetz at oracle.com (Brian Goetz) Date: Tue, 8 May 2018 21:16:13 -0400 Subject: Treatment of nested 'break' In-Reply-To: <2C0702D8-31BF-4BAF-A695-0E2B2A41C868@oracle.com> References: <2C0702D8-31BF-4BAF-A695-0E2B2A41C868@oracle.com> Message-ID: > I am concerned about the treatment of 'break' statements in switch expressions. The following seems like something that would be very natural to do: > > boolean x = switch (expr()) { > case FOO -> { > for (String s : strings) { > if (s.isEmpty()) break false; > } > break true; > } > case BAR -> true; > default -> false; > }; This should be valid. If you recall the table I posted regarding abrupt completion, the for-loop should be transparent to ?break val?, in the same way it is transparent to ?return? or ?throw? or that block expressions are transparent to all abruptly completing statements. The constraint on ?case Foo -> { ? }? is that the block must complete abruptly via break-value. From daniel.smith at oracle.com Wed May 9 18:14:06 2018 From: daniel.smith at oracle.com (Dan Smith) Date: Wed, 9 May 2018 12:14:06 -0600 Subject: Treatment of nested 'break' In-Reply-To: References: <2C0702D8-31BF-4BAF-A695-0E2B2A41C868@oracle.com> Message-ID: <738BE148-1431-41C4-A559-5C525F0957E8@oracle.com> > On May 8, 2018, at 7:16 PM, Brian Goetz wrote: > >> I am concerned about the treatment of 'break' statements in switch expressions. The following seems like something that would be very natural to do: >> >> boolean x = switch (expr()) { >> case FOO -> { >> for (String s : strings) { >> if (s.isEmpty()) break false; >> } >> break true; >> } >> case BAR -> true; >> default -> false; >> }; > > This should be valid. If you recall the table I posted regarding abrupt completion, the for-loop should be transparent to ?break val?, in the same way it is transparent to ?return? or ?throw? or that block expressions are transparent to all abruptly completing statements. The constraint on ?case Foo -> { ? }? is that the block must complete abruptly via break-value. Definitely prohibited in the current spec. But... this table? > More formally; we can construct a table whose rows are the control constructs and whose columns are the nonlocal branches, and whose entries are "handlers" for a nonlocal branch. Each block has a parent (the immediately enclosing block.) > > break-e break break-l continue return > > switch-e L X X X X > switch-s X L P L P > for X L P L P > while X L P L P > block P P P P P > labeled X X L* X P > lambda X X X X L > method X X X X L > > The handlers mean: > > X -- not allowed > P -- let the parent handle it > L -- handle it and complete normally > L* -- handle it and complete normally if the labels match, otherwise P > I'm worried about those X's in the first column. A simplified model which the spec suggests: there are certain constructs that introduce control flow barriers: method, constructor, initializer, lambda body, switch expression body. It's an error if a break/continue/return reaches one of those and cannot be handled. Nested within one of those, all constructs may choose to handle a break/continue/return, or (by default) propagate it outward. A method/constructor/initializer/lambda body/switch expression body cannot choose to propagate a break/continue/return outward (i.e., "P" is not valid), and other constructs cannot choose to prohibit a break/continue/return (i.e., "X" is not valid). From daniel.smith at oracle.com Wed May 9 18:23:59 2018 From: daniel.smith at oracle.com (Dan Smith) Date: Wed, 9 May 2018 12:23:59 -0600 Subject: Treatment of nested 'break' In-Reply-To: <17d322ee-6b97-eb95-3cc2-fb464822c081@oracle.com> References: <2C0702D8-31BF-4BAF-A695-0E2B2A41C868@oracle.com> <17d322ee-6b97-eb95-3cc2-fb464822c081@oracle.com> Message-ID: > On May 8, 2018, at 5:37 PM, Maurizio Cimadamore wrote: > > I believe what we also wanted to avoid was for a 'break expression' to appear nested inside another break-y context - e.g. another statement switch - example: > > boolean v = switch (e1) { > case "One": > switch (e2) { > case 42: break false; // <----- > } > break true; > ... > } > > The fact that we can 'break false' from a switch (statement) nested inside a switch (expression) is visually very confusing - and I've seen code snippets (one of javac regression tests) where it was virtually impossible to determine whether a switch was an expression or a statement because of this fact. There's some work to be done to develop a new intuition, but I think once we've gotten there, things like this will not be so confusing. The intuition is based on recognizing "subexpression markers"?things like "= switch" or "foo(switch". When I encounter a value break, I look for the first enclosing subexpression marker, and that's where the value goes. My gut feeling is that, once these constructs have been socialized, people will get it. From brian.goetz at oracle.com Wed May 9 18:37:22 2018 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 9 May 2018 14:37:22 -0400 Subject: Treatment of nested 'break' In-Reply-To: <738BE148-1431-41C4-A559-5C525F0957E8@oracle.com> References: <2C0702D8-31BF-4BAF-A695-0E2B2A41C868@oracle.com> <738BE148-1431-41C4-A559-5C525F0957E8@oracle.com> Message-ID: > Definitely prohibited in the current spec. But... this table? Yep.? (Sorry for the formatting.) >> More formally; we can construct a table whose rows are the control constructs and whose columns are the nonlocal branches, and whose entries are "handlers" for a nonlocal branch. Each block has a parent (the immediately enclosing block.) >> >> break-e break break-l continue return >> >> switch-e L X X X X >> switch-s X L P L P >> for X L P L P >> while X L P L P >> block P P P P P >> labeled X X L* X P >> lambda X X X X L >> method X X X X L >> >> The handlers mean: >> >> X -- not allowed >> P -- let the parent handle it >> L -- handle it and complete normally >> L* -- handle it and complete normally if the labels match, otherwise P >> > I'm worried about those X's in the first column. Right, now I see what you mean, and now I recall the motivation. The idea was that there are "breaky" and "nonbreaky" contexts, and for each breaky context, it supports either break-e or break-{l,nothing}. > A simplified model which the spec suggests: there are certain constructs that introduce control flow barriers: method, constructor, initializer, lambda body, switch expression body. It's an error if a break/continue/return reaches one of those and cannot be handled. Nested within one of those, all constructs may choose to handle a break/continue/return, or (by default) propagate it outward. Right, that's where I was going with this approach.? Certain constructs consume certain abrupt completions, and others are barriers to certain abrupt completions.? I left out try-catch but it would fit into this approach too, with a little more work. From daniel.smith at oracle.com Wed May 9 20:27:26 2018 From: daniel.smith at oracle.com (Dan Smith) Date: Wed, 9 May 2018 14:27:26 -0600 Subject: Treatment of nested 'break' In-Reply-To: References: <2C0702D8-31BF-4BAF-A695-0E2B2A41C868@oracle.com> <738BE148-1431-41C4-A559-5C525F0957E8@oracle.com> Message-ID: <672B6182-0970-4747-B041-DE4C20157784@oracle.com> > On May 9, 2018, at 12:37 PM, Brian Goetz wrote: > > Right, now I see what you mean, and now I recall the motivation. The idea was that there are "breaky" and "nonbreaky" contexts, and for each breaky context, it supports either break-e or break-{l,nothing}. Okay, yep. I'm saying that I think this is a bad idea, because it makes value breaks much less useful than returns, though both serve a similar purpose and would be used in similar ways. The key readability question is: can I readily find this value break's target? I think the answer will usually be "yes", even when nested in other constructs. If not, I worry that that's a fatal problem with 'break', and we should be looking at a different keyword. >> A simplified model which the spec suggests: there are certain constructs that introduce control flow barriers: method, constructor, initializer, lambda body, switch expression body. It's an error if a break/continue/return reaches one of those and cannot be handled. Nested within one of those, all constructs may choose to handle a break/continue/return, or (by default) propagate it outward. > > Right, that's where I was going with this approach. Certain constructs consume certain abrupt completions, and others are barriers to certain abrupt completions. I left out try-catch but it would fit into this approach too, with a little more work. You've got a general framework, and I'm saying we can reduce some degrees of freedom by saying that if a construct is a "barrier", it's got to be a barrier for all abrupt completions. That limitation contains all the X's to certain rows, and distributes them uniformly across columns. Here's my proposed table, if it helps (also has some bug fixes): break-e break break-l continue return switch-s P L P P P for P L P L P while P L P L P block P P P P P labeled P P L* P P [simple rule: if you can handle it, great; if not, pass it on] lambda X X X X L method X X X X L switch-e L X X X X [simple rule: if you can handle it, great; if not, error] From brian.goetz at oracle.com Wed May 9 20:32:43 2018 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 9 May 2018 16:32:43 -0400 Subject: Treatment of nested 'break' In-Reply-To: <672B6182-0970-4747-B041-DE4C20157784@oracle.com> References: <2C0702D8-31BF-4BAF-A695-0E2B2A41C868@oracle.com> <738BE148-1431-41C4-A559-5C525F0957E8@oracle.com> <672B6182-0970-4747-B041-DE4C20157784@oracle.com> Message-ID: <2FC4A094-DCAF-48D0-9DA2-B584632D9DB1@oracle.com> > The key readability question is: can I readily find this value break's target? I think the answer will usually be "yes", even when nested in other constructs. If not, I worry that that's a fatal problem with 'break', and we should be looking at a different keyword. The thing this model tries to avoid is having ?break? and ?break e? in the same scope apply to different constructs. Code like: if (foo) break; else break 3; seems pretty confusing. The model here is that break is like return; the type of its operand must agree with the enclosing method. From john.r.rose at oracle.com Thu May 10 02:20:26 2018 From: john.r.rose at oracle.com (John Rose) Date: Wed, 9 May 2018 19:20:26 -0700 Subject: JEP325: Switch expressions spec In-Reply-To: <55cf153c-c602-24d6-8675-ee321b2d9a8d@oracle.com> References: <8E28CEE7-0F85-485A-9AE7-15801522B06C@oracle.com> <144bd9d6-fca8-eec5-db85-156d2ad98519@oracle.com> <55cf153c-c602-24d6-8675-ee321b2d9a8d@oracle.com> Message-ID: <21288FC5-C2F2-4B79-9C54-3B3835FBB682@oracle.com> 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 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; > From guy.steele at oracle.com Thu May 10 02:43:48 2018 From: guy.steele at oracle.com (Guy Steele) Date: Wed, 9 May 2018 22:43:48 -0400 Subject: JEP325: Switch expressions spec In-Reply-To: <21288FC5-C2F2-4B79-9C54-3B3835FBB682@oracle.com> References: <8E28CEE7-0F85-485A-9AE7-15801522B06C@oracle.com> <144bd9d6-fca8-eec5-db85-156d2ad98519@oracle.com> <55cf153c-c602-24d6-8675-ee321b2d9a8d@oracle.com> <21288FC5-C2F2-4B79-9C54-3B3835FBB682@oracle.com> Message-ID: <0A545FDB-4EBE-4769-8449-1AA1F3914411@oracle.com> 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 Rose wrote: > > 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 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; >> > > From gavin.bierman at oracle.com Thu May 10 10:12:16 2018 From: gavin.bierman at oracle.com (Gavin Bierman) Date: Thu, 10 May 2018 11:12:16 +0100 Subject: JEP325: Switch expressions spec In-Reply-To: <5AE39C51.7040300@oracle.com> References: <8E28CEE7-0F85-485A-9AE7-15801522B06C@oracle.com> <0CF1227E-79B4-48A1-A227-86466EDB6219@oracle.com> <5AE39C51.7040300@oracle.com> Message-ID: [Apologies for slow reply. Now going through the latest batch of feedback.] Ack. Thanks. Gavin > On 27 Apr 2018, at 22:55, Alex Buckley wrote: > > 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 From gavin.bierman at oracle.com Thu May 10 10:37:41 2018 From: gavin.bierman at oracle.com (Gavin Bierman) Date: Thu, 10 May 2018 11:37:41 +0100 Subject: JEP325: Switch expressions spec In-Reply-To: References: <8E28CEE7-0F85-485A-9AE7-15801522B06C@oracle.com> <0CF1227E-79B4-48A1-A227-86466EDB6219@oracle.com> Message-ID: <136A7DDD-70A8-4DB0-823F-BEF8CADDF92C@oracle.com> Hah! Yes, good catch. Let me think about this one. Thanks, Gavin > On 30 Apr 2018, at 17:13, ?amonn McManus wrote: > > 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 From gavin.bierman at oracle.com Thu May 10 12:28:10 2018 From: gavin.bierman at oracle.com (Gavin Bierman) Date: Thu, 10 May 2018 13:28:10 +0100 Subject: JEP325: Switch expressions spec In-Reply-To: <5A242ACE-EF32-4310-BE13-52A95EC3EC18@oracle.com> References: <8E28CEE7-0F85-485A-9AE7-15801522B06C@oracle.com> <0CF1227E-79B4-48A1-A227-86466EDB6219@oracle.com> <5A242ACE-EF32-4310-BE13-52A95EC3EC18@oracle.com> Message-ID: <9232CF99-5D92-4CB1-B0BD-E769BAF04053@oracle.com> > On 9 May 2018, at 00:08, Dan Smith wrote: > > 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? 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. > > 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.] > > 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. This makes sense if we go for the symmetry approach. > 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.) I?ll ask about this. At least to me it seems a little odd to throw in a tweak to lambdas in a JEP concerning switch. But maybe it?s acceptable; I?ll find out. > > --- > > 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. ok > > 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. > > --- > > 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 > Thanks. (Amazing how big this small feature is!) > --- > > 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. 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. > > 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. Agreed. > > 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.) > > 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. Yes, some of this text is still out of date. Will re-work. > 14.11: "It should be clear from that grammar ..." should be green Thanks. > > 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?] > > 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?.) It?s going back in anyhow! > > 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. Hmm?That?s old text that predates this JEP. > > 14.11: I'm pretty down on explaining features via translation to other features. It's often unclear exactly what this pseudo-code means (which JLS rules apply to it?), and there tends to be a lot of tedious work to make the pseudo-code valid (what if the statement can't complete normally?). Here it would be much clearer to just describe the run-time behavior of 'switch' in terms of clauses. Ah, thanks for reminding me about this. Actually, this translation was necessary to avoid opening a can of worms to spec out the ?can return? for switch. However, much of that pain was dealing with mixed -> and : case labels. In our new world of not mixing them we can take another look at this. Thanks! > > 14.11 "If multiple statements are needed then a block (14.2) should be used": this is a useful illustration, but in the context of Chapter 14, probably too chatty. It's a given that a Block can be used wherever you want multiple statements. Compare the spec for the 'while' loop (14.12). Ok. That was an explicit request but I?ll take another look. > > 14.11: discussion about unboxing would be clearer if it were limited to a bullet defining the rule for matching a constant expression. (I might separate "constant expression of a primitive type" as a distinct case in the definition.) ack. > > 14.11: "evaluates to the null? Thanks. > > 14.11 "A case label can contain multiple patterns, and is said to match if": again, I want to push this down into a definition of "match" somewhere. > > Example 14.11-1: Some further illustration is good here, but this sequencing feels very much like it was tacked on. Something like "what's the difference between two forms of switch blocks?" might be a better way to approach the discussion. I?ll take another look. > 14.15, 14.16, 14.17 "immediately enclosing method, constructor, or initializer": this list should consistently include lambda bodies and switch expression blocks as well. (In the 'return' case, switch expression blocks should also be included in the rule about illegal containers.) > > 14.15, 14.16, 14.17 "not permitted to transfer control through a switch expression": with the change to include switch expression blocks in the other rule, there's no need for a special rule that applies to switch expressions. In fact, calling them out suggests that they are somehow treated differently than lambda bodies, when they are not. These paragraphs can be deleted. I?ll take another look at this text. > 15.15 "and the switch expression": should be green Thanks. > > 15.29: this is probably the wrong section number; we'll have to ask Alex how much disruption he wants to tolerate. Will do. > > 15.29 "In contrast to a switch statement": I think the right thing to say about the contrast is this: it's impossible for the expression to complete normally without a value, so the expression must not leave out some cases. Thanks, I?ll take another look at this text. > > 15.29 "The rules for the selector expression": I approve of reuse, but I think this is small enough that it would be better to copy/paste the rule here. Ok. > > 15.29 "Can return": I don't think this requires so much discussion. Just a couple of sentences: "It is a compile-time error if the Block of a SwitchExpressionClause can complete normally. It is a compile-time error if statements of the last SwitchBlockStatementGroup can complete normally.? Yes, you might be right. Although it is a big difference between switch statement and switch expressions. The thing I don?t like is the rather awkward double-negative definition, so I?d be happy to simply this. > > 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. From brian.goetz at oracle.com Thu May 10 14:11:48 2018 From: brian.goetz at oracle.com (Brian Goetz) Date: Thu, 10 May 2018 10:11:48 -0400 Subject: JEP325: Switch expressions spec In-Reply-To: <0A545FDB-4EBE-4769-8449-1AA1F3914411@oracle.com> References: <8E28CEE7-0F85-485A-9AE7-15801522B06C@oracle.com> <144bd9d6-fca8-eec5-db85-156d2ad98519@oracle.com> <55cf153c-c602-24d6-8675-ee321b2d9a8d@oracle.com> <21288FC5-C2F2-4B79-9C54-3B3835FBB682@oracle.com> <0A545FDB-4EBE-4769-8449-1AA1F3914411@oracle.com> Message-ID: 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 Rose wrote: >> >> 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 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; >>> >> From guy.steele at oracle.com Thu May 10 14:34:35 2018 From: guy.steele at oracle.com (Guy Steele) Date: Thu, 10 May 2018 10:34:35 -0400 Subject: JEP325: Switch expressions spec In-Reply-To: <9232CF99-5D92-4CB1-B0BD-E769BAF04053@oracle.com> References: <8E28CEE7-0F85-485A-9AE7-15801522B06C@oracle.com> <0CF1227E-79B4-48A1-A227-86466EDB6219@oracle.com> <5A242ACE-EF32-4310-BE13-52A95EC3EC18@oracle.com> <9232CF99-5D92-4CB1-B0BD-E769BAF04053@oracle.com> Message-ID: > On May 10, 2018, at 8:28 AM, Gavin Bierman wrote: > > >> 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 From guy.steele at oracle.com Thu May 10 15:03:14 2018 From: guy.steele at oracle.com (Guy Steele) Date: Thu, 10 May 2018 11:03:14 -0400 Subject: JEP325: Switch expressions spec In-Reply-To: References: <8E28CEE7-0F85-485A-9AE7-15801522B06C@oracle.com> <144bd9d6-fca8-eec5-db85-156d2ad98519@oracle.com> <55cf153c-c602-24d6-8675-ee321b2d9a8d@oracle.com> <21288FC5-C2F2-4B79-9C54-3B3835FBB682@oracle.com> <0A545FDB-4EBE-4769-8449-1AA1F3914411@oracle.com> Message-ID: > 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** :-). ?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. From brian.goetz at oracle.com Thu May 10 15:32:04 2018 From: brian.goetz at oracle.com (Brian Goetz) Date: Thu, 10 May 2018 11:32:04 -0400 Subject: JEP325: Switch expressions spec In-Reply-To: References: <8E28CEE7-0F85-485A-9AE7-15801522B06C@oracle.com> <144bd9d6-fca8-eec5-db85-156d2ad98519@oracle.com> <55cf153c-c602-24d6-8675-ee321b2d9a8d@oracle.com> <21288FC5-C2F2-4B79-9C54-3B3835FBB682@oracle.com> <0A545FDB-4EBE-4769-8449-1AA1F3914411@oracle.com> Message-ID: <5BB3B03A-E20C-4188-AB94-4E583DFBFCAC@oracle.com> > On May 10, 2018, at 11:03 AM, Guy Steele wrote: > > >> 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. From daniel.smith at oracle.com Thu May 10 17:36:34 2018 From: daniel.smith at oracle.com (Dan Smith) Date: Thu, 10 May 2018 11:36:34 -0600 Subject: JEP325: Switch expressions spec In-Reply-To: <9232CF99-5D92-4CB1-B0BD-E769BAF04053@oracle.com> References: <8E28CEE7-0F85-485A-9AE7-15801522B06C@oracle.com> <0CF1227E-79B4-48A1-A227-86466EDB6219@oracle.com> <5A242ACE-EF32-4310-BE13-52A95EC3EC18@oracle.com> <9232CF99-5D92-4CB1-B0BD-E769BAF04053@oracle.com> Message-ID: <9FFBF5BA-27EE-4884-9057-B95532C7E92F@oracle.com> > On May 10, 2018, at 6:28 AM, Gavin Bierman wrote: > >> 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 some inputs is a feature of switch statements. > > Hmm?That?s old text that predates this JEP. Yes, but we have scrutinized it a lot when developing this feature, and agreed that it was misguided. >> 14.11 "If multiple statements are needed then a block (14.2) should be used": this is a useful illustration, but in the context of Chapter 14, probably too chatty. It's a given that a Block can be used wherever you want multiple statements. Compare the spec for the 'while' loop (14.12). > > Ok. That was an explicit request but I?ll take another look. This is always subjective. There is a tendency, which I'm trying to guard against, of over-explaining new features while assuming everyone intuitively understands old features. We want the finished document to feel cohesive to someone with fresh eyes. But sometimes the old features could use a little more discussion, too! >> 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. From alex.buckley at oracle.com Thu May 10 18:15:04 2018 From: alex.buckley at oracle.com (Alex Buckley) Date: Thu, 10 May 2018 11:15:04 -0700 Subject: JEP325: Switch expressions spec In-Reply-To: <9FFBF5BA-27EE-4884-9057-B95532C7E92F@oracle.com> References: <8E28CEE7-0F85-485A-9AE7-15801522B06C@oracle.com> <0CF1227E-79B4-48A1-A227-86466EDB6219@oracle.com> <5A242ACE-EF32-4310-BE13-52A95EC3EC18@oracle.com> <9232CF99-5D92-4CB1-B0BD-E769BAF04053@oracle.com> <9FFBF5BA-27EE-4884-9057-B95532C7E92F@oracle.com> Message-ID: <5AF48C28.5060201@oracle.com> On 5/10/2018 10:36 AM, Dan Smith wrote: >> On May 10, 2018, at 6:28 AM, Gavin Bierman >> wrote: >>> 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 From daniel.smith at oracle.com Thu May 10 18:45:12 2018 From: daniel.smith at oracle.com (Dan Smith) Date: Thu, 10 May 2018 12:45:12 -0600 Subject: Treatment of nested 'break' In-Reply-To: <2FC4A094-DCAF-48D0-9DA2-B584632D9DB1@oracle.com> References: <2C0702D8-31BF-4BAF-A695-0E2B2A41C868@oracle.com> <738BE148-1431-41C4-A559-5C525F0957E8@oracle.com> <672B6182-0970-4747-B041-DE4C20157784@oracle.com> <2FC4A094-DCAF-48D0-9DA2-B584632D9DB1@oracle.com> Message-ID: > On May 9, 2018, at 2:32 PM, Brian Goetz wrote: > > The model here is that break is like return; the type of its operand must agree with the enclosing method. Okay, I think I've successfully wrapped my mind around the two views we're discussing. One is that value break is like label break: it's a transfer of control to a specific target, in this case the innermost surrounding switch expression. The only thing that would prevent you from legally breaking with that target would be a control flow barrier?a construct that simply doesn't support passing control to the surrounding context. The other is that value break is like empty break or value return: a transfer of control to the immediately surrounding "break" thing. At that point, if you happen to have provided the wrong flavor of payload, it's an error. I think these are both valid explanations, with different outcomes, but anyway it's fair to say that it would be confusing to have the latter perspective and then try to explain how a value break can get past a surrounding 'for' loop. My problem: if you're deep in the guts of nested loops and you want to break to an enclosing target, you can use a label. Or if you want to return from the method, you can use the 'return' keyword.* What do you do if you want to break with a value? (*We don't strictly need a 'return' keyword in the language at all. 'break' could unambiguously serve the same purpose, with the same limitations as in a switch block. But there would be lots of pitchforks if we tried imposing those limitations on method bodies.) From brian.goetz at oracle.com Thu May 10 19:06:47 2018 From: brian.goetz at oracle.com (Brian Goetz) Date: Thu, 10 May 2018 15:06:47 -0400 Subject: Treatment of nested 'break' In-Reply-To: References: <2C0702D8-31BF-4BAF-A695-0E2B2A41C868@oracle.com> <738BE148-1431-41C4-A559-5C525F0957E8@oracle.com> <672B6182-0970-4747-B041-DE4C20157784@oracle.com> <2FC4A094-DCAF-48D0-9DA2-B584632D9DB1@oracle.com> Message-ID: <984333b2-de40-bd42-3b25-4204904fef8e@oracle.com> > I think these are both valid explanations, with different outcomes, but anyway it's fair to say that it would be confusing to have the latter perspective and then try to explain how a value break can get past a surrounding 'for' loop. One option is: you can't.? While I agree there is code that one might like to write that is made cumbersome by this, it's a valid option, and not one that is utterly terrible. Another option is to extend the break syntax along the lines of the proposed continue syntax.? Suppose for every continuable construct x (for, while, switch) we supported "continue x".? So for every breakable construct y we could support "break y".? If a for loop were enclosed in an expression switch, you could then say "break switch e".? Then if (foo) break; else break 3; becomes if (foo) break for; else break switch 3; and it is much more obvious what is going on. From guy.steele at oracle.com Thu May 10 19:12:15 2018 From: guy.steele at oracle.com (Guy Steele) Date: Thu, 10 May 2018 15:12:15 -0400 Subject: Treatment of nested 'break' In-Reply-To: <984333b2-de40-bd42-3b25-4204904fef8e@oracle.com> References: <2C0702D8-31BF-4BAF-A695-0E2B2A41C868@oracle.com> <738BE148-1431-41C4-A559-5C525F0957E8@oracle.com> <672B6182-0970-4747-B041-DE4C20157784@oracle.com> <2FC4A094-DCAF-48D0-9DA2-B584632D9DB1@oracle.com> <984333b2-de40-bd42-3b25-4204904fef8e@oracle.com> Message-ID: <3B85A86A-064F-4B3C-9AAA-1FD123E52F6C@oracle.com> > On May 10, 2018, at 3:06 PM, Brian Goetz wrote: > > >> I think these are both valid explanations, with different outcomes, but anyway it's fair to say that it would be confusing to have the latter perspective and then try to explain how a value break can get past a surrounding 'for' loop. > > One option is: you can't. While I agree there is code that one might like to write that is made cumbersome by this, it's a valid option, and not one that is utterly terrible. > > Another option is to extend the break syntax along the lines of the proposed continue syntax. Suppose for every continuable construct x (for, while, switch) we supported "continue x". So for every breakable construct y we could support "break y". If a for loop were enclosed in an expression switch, you could then say "break switch e". Then > > if (foo) > break; > else > break 3; > > becomes > > if (foo) > break for; > else > break switch 3; > > and it is much more obvious what is going on. If we are willing to pile up keywords in that manner, an alternate possibility is to spell a value-returning break in a different way: return switch ; Then your example can become (I have added the implicit context): switch (?) { case 17 -> { ? for (?) { ... if (foo) break; else return switch 3; ? } ? } ? } The additional advantage of this approach is that it completely eliminates the syntactic ambiguity between break variableName; and break labelName; Given that we think most occurrences of ?return switch? (or ?switch return?, take your pick) will be abbreviated by -> anyway, this might be an acceptable approach. You can then still choose to go ahead and also allow things like break for; break switch; break while; continue for; continue switch; but that can be a separate decision; these become simply a way to avoid using statement labels. ?Guy From kevinb at google.com Thu May 10 19:57:21 2018 From: kevinb at google.com (Kevin Bourrillion) Date: Thu, 10 May 2018 12:57:21 -0700 Subject: Treatment of nested 'break' In-Reply-To: <3B85A86A-064F-4B3C-9AAA-1FD123E52F6C@oracle.com> References: <2C0702D8-31BF-4BAF-A695-0E2B2A41C868@oracle.com> <738BE148-1431-41C4-A559-5C525F0957E8@oracle.com> <672B6182-0970-4747-B041-DE4C20157784@oracle.com> <2FC4A094-DCAF-48D0-9DA2-B584632D9DB1@oracle.com> <984333b2-de40-bd42-3b25-4204904fef8e@oracle.com> <3B85A86A-064F-4B3C-9AAA-1FD123E52F6C@oracle.com> Message-ID: I'm just going to say that naming a keyword as the argument of another keyword seems novel and unprecedented for Java, and as such I think should require pretty strong justification. On Thu, May 10, 2018 at 12:12 PM, Guy Steele wrote: > > > On May 10, 2018, at 3:06 PM, Brian Goetz wrote: > > > > > >> I think these are both valid explanations, with different outcomes, but > anyway it's fair to say that it would be confusing to have the latter > perspective and then try to explain how a value break can get past a > surrounding 'for' loop. > > > > One option is: you can't. While I agree there is code that one might > like to write that is made cumbersome by this, it's a valid option, and not > one that is utterly terrible. > > > > Another option is to extend the break syntax along the lines of the > proposed continue syntax. Suppose for every continuable construct x (for, > while, switch) we supported "continue x". So for every breakable construct > y we could support "break y". If a for loop were enclosed in an expression > switch, you could then say "break switch e". Then > > > > if (foo) > > break; > > else > > break 3; > > > > becomes > > > > if (foo) > > break for; > > else > > break switch 3; > > > > and it is much more obvious what is going on. > > If we are willing to pile up keywords in that manner, an alternate > possibility is to spell a value-returning break in a different way: > > return switch ; > > Then your example can become (I have added the implicit context): > > switch (?) { case 17 -> { > ? > for (?) { > ... > if (foo) > break; > else > return switch 3; > ? } > ? } > ? } > > The additional advantage of this approach is that it completely eliminates > the syntactic ambiguity between > > break variableName; > > and > > break labelName; > > Given that we think most occurrences of ?return switch? (or ?switch > return?, take your pick) will be abbreviated by -> anyway, this might be an > acceptable approach. > > You can then still choose to go ahead and also allow things like > > break for; > break switch; > break while; > continue for; > continue switch; > > but that can be a separate decision; these become simply a way to avoid > using statement labels. > > ?Guy > > -- Kevin Bourrillion | Java Librarian | Google, Inc. | kevinb at google.com -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Thu May 10 20:04:15 2018 From: brian.goetz at oracle.com (Brian Goetz) Date: Thu, 10 May 2018 16:04:15 -0400 Subject: Treatment of nested 'break' In-Reply-To: References: <2C0702D8-31BF-4BAF-A695-0E2B2A41C868@oracle.com> <738BE148-1431-41C4-A559-5C525F0957E8@oracle.com> <672B6182-0970-4747-B041-DE4C20157784@oracle.com> <2FC4A094-DCAF-48D0-9DA2-B584632D9DB1@oracle.com> <984333b2-de40-bd42-3b25-4204904fef8e@oracle.com> <3B85A86A-064F-4B3C-9AAA-1FD123E52F6C@oracle.com> Message-ID: <26cb201a-b59c-f3f3-c8e1-11e1b1e30598@oracle.com> This might not help, but perhaps think of it as a compound keyword; "break switch" is not "break with an argument of switch", but a multi-word keyword itself. (Back in lambda, when we explored the consequence of using "return" in lambda, and observed it foreclosed on nonlocal return should we ever want to get there, we briefly discussed "long return" as a compound keyword for that case.? Same game.) Personally if I saw "break while", I think I'd immediately know what that means, and might even thank the author for being clear. On 5/10/2018 3:57 PM, Kevin Bourrillion wrote: > I'm just going to say that naming a keyword as the argument of another > keyword seems novel and unprecedented for Java, and as such I think > should require pretty strong justification. > > > On Thu, May 10, 2018 at 12:12 PM, Guy Steele > wrote: > > > > On May 10, 2018, at 3:06 PM, Brian Goetz > wrote: > > > > > >> I think these are both valid explanations, with different > outcomes, but anyway it's fair to say that it would be confusing > to have the latter perspective and then try to explain how a value > break can get past a surrounding 'for' loop. > > > > One option is: you can't.? While I agree there is code that one > might like to write that is made cumbersome by this, it's a valid > option, and not one that is utterly terrible. > > > > Another option is to extend the break syntax along the lines of > the proposed continue syntax.? Suppose for every continuable > construct x (for, while, switch) we supported "continue x".? So > for every breakable construct y we could support "break y".? If a > for loop were enclosed in an expression switch, you could then say > "break switch e".? Then > > > >? ? if (foo) > >? ? ? ? break; > >? ? else > >? ? ? ? break 3; > > > > becomes > > > >? ? if (foo) > >? ? ? ? break for; > >? ? else > >? ? ? ? break switch 3; > > > > and it is much more obvious what is going on. > > If we are willing to pile up keywords in that manner, an alternate > possibility is to spell a value-returning break in a different way: > > ? ? ? ? return switch ; > > Then your example can become (I have added the implicit context): > > ? ? ? ? switch (?) { case 17 -> { > ? ? ? ? ? ? ? ? ? > ? ? ? ? ? ? ? ? for (?) { > ? ? ? ? ? ? ? ? ? ?... > ? ? ? ? ? ? ? ? ? ?if (foo) > ? ? ? ? ? ? ? ? ? ? ? ?break; > ? ? ? ? ? ? ? ? ? ?else > ? ? ? ? ? ? ? ? ? ? ? ?return switch 3; > ? ? ? ? ? ? ? ? ? } > ? ? ? ? ? ? ? } > ? ? ? ? ? } > > The additional advantage of this approach is that it completely > eliminates the syntactic ambiguity between > > ? ? ? ? break variableName; > > and > > ? ? ? ? break labelName; > > Given that we think most occurrences of ?return switch? (or > ?switch return?, take your pick) will be abbreviated by -> anyway, > this might be an acceptable approach. > > You can then still choose to go ahead and also allow things like > > ? ? ? ? break for; > ? ? ? ? break switch; > ? ? ? ? break while; > ? ? ? ? continue for; > ? ? ? ? continue switch; > > but that can be a separate decision; these become simply a way to > avoid using statement labels. > > ?Guy > > > > > -- > Kevin Bourrillion?|?Java Librarian |?Google, Inc.?|kevinb at google.com > -------------- next part -------------- An HTML attachment was scrubbed... URL: From guy.steele at oracle.com Thu May 10 19:48:08 2018 From: guy.steele at oracle.com (Guy Steele) Date: Thu, 10 May 2018 15:48:08 -0400 Subject: Treatment of nested 'break' In-Reply-To: References: <2C0702D8-31BF-4BAF-A695-0E2B2A41C868@oracle.com> <738BE148-1431-41C4-A559-5C525F0957E8@oracle.com> <672B6182-0970-4747-B041-DE4C20157784@oracle.com> <2FC4A094-DCAF-48D0-9DA2-B584632D9DB1@oracle.com> <984333b2-de40-bd42-3b25-4204904fef8e@oracle.com> <3B85A86A-064F-4B3C-9AAA-1FD123E52F6C@oracle.com> Message-ID: <52D75C9E-A2D7-4DA9-9D04-BAED52BCD9CC@oracle.com> > On May 10, 2018, at 3:57 PM, Kevin Bourrillion wrote: > > I'm just going to say that naming a keyword as the argument of another keyword seems novel and unprecedented for Java, and as such I think should require pretty strong justification. I concur. Note that ?case x, default ->? has the same property: it causes the `default` keyword to be an ?argument? of the `case` keyword. I kind of lean against doing such things. However, if we are going to explore that part of the design space, I just wanted to point out that ?return switch a;? has at least one advantage relative to ?break switch a;?. From brian.goetz at oracle.com Thu May 10 20:12:37 2018 From: brian.goetz at oracle.com (Brian Goetz) Date: Thu, 10 May 2018 16:12:37 -0400 Subject: Exhaustiveness in switch Message-ID: In the long (and indirect) thread on "Expression Switch Exception Naming", we eventually meandered around to the question of when should the compiler deem an expression switch to be exhaustive, and therefore emit a catch-all throwing default. Let's step back from this for a bit and remind ourselves why we care about this. Superficially, having to write a throwing default for a condition we believe to be impossible is annoying: ??? switch (trafficLight) { ??????? case RED -> stop(); ??????? case GREEN -> driveFast(); ??????? case YELLOW -> driveFaster(); ??????? default -> throw new ExasperationException("No, we haven't added any new traffic light colors since the invention of the automobile, so I have no idea what " + trafficLight + " is"); ??? } The annoyance here, though, is twofold: ?- I have to write code for something which I think can't happen; ?- That code is annoying to write. In the above, we "knew" another traffic light color was impossible, and we listed them all -- and the compiler knew it. This is particularly irritating.? However, we often also see cases like this: ??? void processVowel(letter) { ? ?? ?? switch (letter) { ??? ? ?? ?? case A: ... ??????????? case E: ... ? ?? ?????? case I: ... ??? ? ?? ?? case O: ... ??????????? case U: ... ? ?? ?????? default: throw new IllegalStateException("Not a vowel: " + letter); ??????? } Here, the annoyance is slightly different, in that I could not reasonably expect the compiler to know I'd covered all the vowels.? In fact, I think the explicit exception in this case is useful, in that it documents an invariant known to the programmer but not captured in the type system.? But it is still annoying that I have to construct a format string, construct an exception, and throw it; if there were easier ways to do that, I might be less annoyed.? Without diving into the bikeshed, maybe this looks something like: ??????? default: throw IllegalStateException.format("Not a vowel: %s", vowel); The details aren't relevant, but the point is: maybe a small-ish library tweak would reduce the annoyance of writing such clauses. (This one isn't so bad, but Dan excavated a bunch that were way worse.)? But, let's set this aside for a moment, and return back to the point of why we want the compiler to provide a throwing default. I think most of the discussion has centered on the problem of a novel value showing up at runtime.? This is surely an issue, and must be dealt with, but the central issue is: a default is never able to distinguish between a runtime-novel value and a value we just forgot to include at compile time.? It doesn't matter whether this default throws (as the implicit default in an expression switch) or does nothing (as the implicit default in statement switches today does). We agreed that we should not require the user to provide a default when they provide case clauses that cover the target type as of compile time (true+false for boolean, all the members of a sealed type, etc.)? This is because the default you'd be forced to put in otherwise (for expression switches) is actually harmful; if the type were later modified to have more values, an explicit default would swallow them, rather than yielding an error at recompilation time.? So it is not only annoying, but actually could cover up errors. We then went off on the wrong tangent, though, where we wondered whether it was OK to implicitly assume enums were sealed, since some enums are clearly intended to acquire new values.? But the mistake was focusing on the wrong aspect of sealed-ness (the statement of intent to not add more values), rather than the compiler's ability to reason credibly about known possible values. So, backing up, I think we should always treat a "complete" enum expression switch specially -- don't require a default, and implicitly add a throwing one, if all the cases are specified. This way, if the assumption that you've covered all the cases is later broken via separate compilation, on recompilation, you'll discover this early, rather than at runtime.? (You'll still get runtime protection either way.)? Regardless of whether we think the enum will be extended in the future or not.? There's no need for enums to declare themselves "sealed" or "non-sealed" (and such a declaration would likely be incorrect anyway, as it asks users to predict the future, which is error-prone.) Given this, I'm willing to use ICCE as a base type for the implicit exception (though there should be more specific subtypes.) Now, statement switches.? It seems sad that we can't get the same kind of compile-time assistance over statement switches than we do over expression switches.? We're somewhat locked in by compatibility here; statement switches today get an implicit "default: nothing" clause if they have no default, and we cannot (and don't want to) break this.? So the next best thing is if the user could say "I want to get the same sort of compile-time verification of putative exhaustiveness for this statement switch as I would for expression switches."? This would require some additional syntax (please, let's not bikeshed this until everything else on this topic is nailed down; this is a target of opportunity, not a problem to be solved Right Now.) Someone is likely to suggest that we should do the exhaustiveness thing for all three of the four new forms (statement arrow, and expression colon/arrow).? Feel free to make this suggestion, but you're going to get the "snitch" lecture :) Another thing that we can do to make it easier to write throwing defaults: lean on intrinsics.? Recall that separately, we've got a story to expose some compiler intrinsics for ldc() and invokedynamic().? There's room to add other things to this, such as the equivalent of __LINE__ and __FILE__ macros in C, or (relevant to this) information about the the current point in the compilation (such as the cases enumerated in the innermost switch.)? So for example: ??? default: throw SwitchException.format("Found %s, but expected one of %s", ????????????????????????????????????????? target, Intrinsics.switchCases()); or even ??? default: throw SwitchException.of(target, Intrinsics.switchCases()); where `Intrinsics.switchCases()` would evaluate to a string that includes all the cases handled by the current switch (in our vowels case, this would be "A, E, I, O, U").? Again, not something for Right Now, but something that machinery that's in the pipeline can contribute to making it simpler and more uniform to express catch-all defaults, and thereby reduced the perceived annoyance. Summary: ?- For switches over any type where the compiler can enumerate the possibilities (includes enums, some primitives, and sealed types), always allow the user to leave off a default if they've specified all the known cases. ?- Use subtypes of ICCE in implicit throwing defaults. ?- Consider library enhancements to common exceptions (and maybe additional intrinsics) to simplify code that throws formatted exceptions. From kevinb at google.com Thu May 10 20:44:33 2018 From: kevinb at google.com (Kevin Bourrillion) Date: Thu, 10 May 2018 13:44:33 -0700 Subject: Exhaustiveness in switch In-Reply-To: References: Message-ID: This is just a quick initial response and that it will veer off-topic: * Users of Guava's Preconditions love the support for "%s"-formatting. But on the other hand, in code where you *are definitely* about to throw something, why wouldn't I just use string concatenation? That is generally easier to read because you don't have to mentally correlate specifiers to faraway arguments. (Okay: one reason might be if your message is long enough that you'd like to use a multi-line raw string literal for it, where concatenation is BadBadBad, but I can't say how common this is or isn't at the moment.) * If you do add those methods, though, you don't want to just call String.format() inside -- or if you do, you at least want to catch InvalidFormatException and produce a fallback message in that case; don't let that except supplant the one the user is really trying to create (especially if that is unchecked). * I think that for most occurrences of `default: throw...`, by far, the user really doesn't benefit from being able to choose the exception type or the message at all. A standardized choice of exception, and an autogenerated message (that automatically includes the switch target, which users usually don't bother to do themselves!), may be strictly better. Can we consider providing them a shortcut (strawman: just `default: throw;`!)? * For exhaustive switches (so far: enums), the ideal we have been trying to shoot for is that the user makes an informed, intelligent choice about whether they want the compile error or the runtime error when a new one is added. So far, with what we've implemented at Google, it seems that we're falling fall short of that ideal. We have been strongly considering the idea that you *shouldn't* be allowed to simply omit a default at all, because what that *means* is far too opaque. It would be better if the user had to do something explicit in either case. Could it be that the idea in the previous bullet actually provides this? We would go back to always requiring an explicit `default` for an e-switch, but you still get to make an explicit choice which behavior you're asking for. * It would feel strange to even bother applying this exhaustiveness goo to *byte* switches. If we ever had ranges.... of course then, any type of switch could join the party. (I don't know whether ranges are a thing we're considering or not and I'm not pushing that we do.) On Thu, May 10, 2018 at 1:12 PM, Brian Goetz wrote: > In the long (and indirect) thread on "Expression Switch Exception Naming", > we eventually meandered around to the question of when should the compiler > deem an expression switch to be exhaustive, and therefore emit a catch-all > throwing default. Let's step back from this for a bit and remind ourselves > why we care about this. > > Superficially, having to write a throwing default for a condition we > believe to be impossible is annoying: > > switch (trafficLight) { > case RED -> stop(); > case GREEN -> driveFast(); > case YELLOW -> driveFaster(); > default -> throw new ExasperationException("No, we haven't added > any new traffic light colors since the invention of the automobile, so I > have no idea what " + trafficLight + " is"); > } > > The annoyance here, though, is twofold: > - I have to write code for something which I think can't happen; > - That code is annoying to write. > > In the above, we "knew" another traffic light color was impossible, and we > listed them all -- and the compiler knew it. This is particularly > irritating. However, we often also see cases like this: > > void processVowel(letter) { > switch (letter) { > case A: ... > case E: ... > case I: ... > case O: ... > case U: ... > default: throw new IllegalStateException("Not a vowel: " + > letter); > } > > Here, the annoyance is slightly different, in that I could not reasonably > expect the compiler to know I'd covered all the vowels. In fact, I think > the explicit exception in this case is useful, in that it documents an > invariant known to the programmer but not captured in the type system. But > it is still annoying that I have to construct a format string, construct an > exception, and throw it; if there were easier ways to do that, I might be > less annoyed. Without diving into the bikeshed, maybe this looks something > like: > > default: throw IllegalStateException.format("Not a vowel: %s", > vowel); > > The details aren't relevant, but the point is: maybe a small-ish library > tweak would reduce the annoyance of writing such clauses. (This one isn't > so bad, but Dan excavated a bunch that were way worse.) But, let's set > this aside for a moment, and return back to the point of why we want the > compiler to provide a throwing default. > > I think most of the discussion has centered on the problem of a novel > value showing up at runtime. This is surely an issue, and must be dealt > with, but the central issue is: a default is never able to distinguish > between a runtime-novel value and a value we just forgot to include at > compile time. It doesn't matter whether this default throws (as the > implicit default in an expression switch) or does nothing (as the implicit > default in statement switches today does). > > We agreed that we should not require the user to provide a default when > they provide case clauses that cover the target type as of compile time > (true+false for boolean, all the members of a sealed type, etc.) This is > because the default you'd be forced to put in otherwise (for expression > switches) is actually harmful; if the type were later modified to have more > values, an explicit default would swallow them, rather than yielding an > error at recompilation time. So it is not only annoying, but actually > could cover up errors. > > We then went off on the wrong tangent, though, where we wondered whether > it was OK to implicitly assume enums were sealed, since some enums are > clearly intended to acquire new values. But the mistake was focusing on > the wrong aspect of sealed-ness (the statement of intent to not add more > values), rather than the compiler's ability to reason credibly about known > possible values. > > So, backing up, I think we should always treat a "complete" enum > expression switch specially -- don't require a default, and implicitly add > a throwing one, if all the cases are specified. This way, if the assumption > that you've covered all the cases is later broken via separate compilation, > on recompilation, you'll discover this early, rather than at runtime. > (You'll still get runtime protection either way.) Regardless of whether we > think the enum will be extended in the future or not. There's no need for > enums to declare themselves "sealed" or "non-sealed" (and such a > declaration would likely be incorrect anyway, as it asks users to predict > the future, which is error-prone.) > > Given this, I'm willing to use ICCE as a base type for the implicit > exception (though there should be more specific subtypes.) > > > Now, statement switches. It seems sad that we can't get the same kind of > compile-time assistance over statement switches than we do over expression > switches. We're somewhat locked in by compatibility here; statement > switches today get an implicit "default: nothing" clause if they have no > default, and we cannot (and don't want to) break this. So the next best > thing is if the user could say "I want to get the same sort of compile-time > verification of putative exhaustiveness for this statement switch as I > would for expression switches." This would require some additional syntax > (please, let's not bikeshed this until everything else on this topic is > nailed down; this is a target of opportunity, not a problem to be solved > Right Now.) > > Someone is likely to suggest that we should do the exhaustiveness thing > for all three of the four new forms (statement arrow, and expression > colon/arrow). Feel free to make this suggestion, but you're going to get > the "snitch" lecture :) > > > Another thing that we can do to make it easier to write throwing defaults: > lean on intrinsics. Recall that separately, we've got a story to expose > some compiler intrinsics for ldc() and invokedynamic(). There's room to > add other things to this, such as the equivalent of __LINE__ and __FILE__ > macros in C, or (relevant to this) information about the the current point > in the compilation (such as the cases enumerated in the innermost switch.) > So for example: > > default: throw SwitchException.format("Found %s, but expected one of > %s", > target, > Intrinsics.switchCases()); > > or even > > default: throw SwitchException.of(target, Intrinsics.switchCases()); > > where `Intrinsics.switchCases()` would evaluate to a string that includes > all the cases handled by the current switch (in our vowels case, this would > be "A, E, I, O, U"). Again, not something for Right Now, but something > that machinery that's in the pipeline can contribute to making it simpler > and more uniform to express catch-all defaults, and thereby reduced the > perceived annoyance. > > > Summary: > - For switches over any type where the compiler can enumerate the > possibilities (includes enums, some primitives, and sealed types), always > allow the user to leave off a default if they've specified all the known > cases. > - Use subtypes of ICCE in implicit throwing defaults. > - Consider library enhancements to common exceptions (and maybe > additional intrinsics) to simplify code that throws formatted exceptions. > -- Kevin Bourrillion | Java Librarian | Google, Inc. | kevinb at google.com -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Thu May 10 20:54:59 2018 From: brian.goetz at oracle.com (Brian Goetz) Date: Thu, 10 May 2018 16:54:59 -0400 Subject: Exhaustiveness in switch In-Reply-To: References: Message-ID: <07a4d56e-3934-2940-732d-a0615bf2f110@oracle.com> > * Users of Guava's Preconditions love the support for > "%s"-formatting.? But on the other hand, in code where you /are > definitely/?about to throw something, why wouldn't I just use string > concatenation? That is generally easier to read because you don't have > to mentally correlate specifiers to faraway arguments. (Okay: one > reason might be if your message is long enough that you'd like to use > a multi-line raw string literal for it, where concatenation is > BadBadBad, but I can't say how common this is or isn't at the moment.) I think this is YMMV.? Some users (this one included) always feel dirty using string concatenation.? I would prefer to use formatting almost all the time.? That exceptions don't incorporate formatting is mostly an artifact of the fact that the last big overhaul in exception APIs was in 1.4 (when we added chaining) and format was added in 1.5.? (Because of the way it was done in 1.4, where the constructor parameter of the general form is (String, Throwable), we can't overload with a (String, Object...) constructor that would treat the string as a format string, which is surely what we would have done had we had format() in 1.0.) > * I think that for most occurrences of `default: throw...`, by far, > the user really doesn't benefit from being able to choose the > exception type or the message at all. A standardized choice of > exception, and an autogenerated message (that automatically includes > the switch target, which users usually don't bother to do > themselves!), may be strictly better. Can we consider providing them a > shortcut (strawman: just `default: throw;`!)? We did actually discuss this very notion.? While its attractive, it also feels like an attractor for an infinite stream of "can you let me customize x/y/z" requests.? So we wanted to explore whether there are library moves we can make that get us to this benefit first. For example, if you could say ??? default: throw switchException(); where switchExpression() was a static-import of Intrinsics.switchExpression() (which could still capture Object.toString() of the target, as well as a description of the switch context), that's a smaller hammer with more flexibility. > * For exhaustive switches (so far: enums), the ideal we have been > trying to shoot for is that the user makes an informed, intelligent > choice about whether they want the compile error or the runtime error > when a new one is added. So far, with what we've implemented at > Google, it seems that we're falling fall short of that ideal. We have > been strongly considering the idea that you /shouldn't/?be allowed to > simply omit a default at all, because what that /means/ is far too > opaque. It would be better if the user had to do something explicit in > either case. Could it be that the idea in the previous bullet actually > provides this? We would go back to always requiring an explicit > `default` for an e-switch, but you still get to make an explicit > choice which behavior you're asking for. That sounds like a turnaround.? Previously, you'd argued that specifying all the enum cases and omitting a default was ideal because then you have a valuable tripwire against new values being added without them getting swept under the rug. > * It would feel strange to even bother applying this exhaustiveness > goo to /byte/ switches. If we ever had ranges.... of course then, any > type of switch could join the party. (I don't know whether ranges are > a thing we're considering or not and I'm not pushing that we do.) Yeah, its on the edge.? Its a no-brainer for `boolean`, its nuts for `int` (without ranges), but its vaguely defensible for `byte`. Though I can't really get too excited about it. -------------- next part -------------- An HTML attachment was scrubbed... URL: From guy.steele at oracle.com Thu May 10 20:46:31 2018 From: guy.steele at oracle.com (Guy Steele) Date: Thu, 10 May 2018 16:46:31 -0400 Subject: Exhaustiveness in switch In-Reply-To: <07a4d56e-3934-2940-732d-a0615bf2f110@oracle.com> References: <07a4d56e-3934-2940-732d-a0615bf2f110@oracle.com> Message-ID: <9D1E2611-7E5D-4C67-9BB4-FF3109A46CF9@oracle.com> > On May 10, 2018, at 4:54 PM, Brian Goetz wrote: > >> * It would feel strange to even bother applying this exhaustiveness goo to byte switches. If we ever had ranges.... of course then, any type of switch could join the party. (I don't know whether ranges are a thing we're considering or not and I'm not pushing that we do.) > > Yeah, its on the edge. Its a no-brainer for `boolean`, its nuts for `int` (without ranges), but its vaguely defensible for `byte`. Though I can't really get too excited about it. The choice is not just among four sizes of integer. One could imagine recognizing certain idioms such as switch (myInt & 7) { case 2, 3, 5, 7 -> ?prime?; case 0, 1, 4 -> ?square?; case 6 -> ?perfect?; } and understanding that they are exhaustive. Dunno if the compiler guys want to go there. ?Guy -------------- next part -------------- An HTML attachment was scrubbed... URL: From kevinb at google.com Thu May 10 21:05:06 2018 From: kevinb at google.com (Kevin Bourrillion) Date: Thu, 10 May 2018 14:05:06 -0700 Subject: Exhaustiveness in switch In-Reply-To: <07a4d56e-3934-2940-732d-a0615bf2f110@oracle.com> References: <07a4d56e-3934-2940-732d-a0615bf2f110@oracle.com> Message-ID: On Thu, May 10, 2018 at 1:54 PM, Brian Goetz wrote: > * I think that for most occurrences of `default: throw...`, by far, the > user really doesn't benefit from being able to choose the exception type or > the message at all. A standardized choice of exception, and an > autogenerated message (that automatically includes the switch target, which > users usually don't bother to do themselves!), may be strictly better. Can > we consider providing them a shortcut (strawman: just `default: throw;`!)? > > > We did actually discuss this very notion. While its attractive, it also > feels like an attractor for an infinite stream of "can you let me customize > x/y/z" requests. So we wanted to explore whether there are library moves > we can make that get us to this benefit first. For example, if you could > say > > default: throw switchException(); > > where switchExpression() was a static-import of > Intrinsics.switchExpression() (which could still capture Object.toString() > of the target, as well as a description of the switch context), that's a > smaller hammer with more flexibility. > Yes, that sounds like it ticks the boxes as well. Could we apply this strategy to all "I believe this line to be unreachable" situations? * For exhaustive switches (so far: enums), the ideal we have been trying to > shoot for is that the user makes an informed, intelligent choice about > whether they want the compile error or the runtime error when a new one is > added. So far, with what we've implemented at Google, it seems that we're > falling fall short of that ideal. We have been strongly considering the > idea that you *shouldn't* be allowed to simply omit a default at all, > because what that *means* is far too opaque. It would be better if the > user had to do something explicit in either case. Could it be that the idea > in the previous bullet actually provides this? We would go back to always > requiring an explicit `default` for an e-switch, but you still get to make > an explicit choice which behavior you're asking for. > > > That sounds like a turnaround. Previously, you'd argued that specifying > all the enum cases and omitting a default was ideal because then you have a > valuable tripwire against new values being added without them getting swept > under the rug. > The only distinction I am discussing now is whether it is implicit or explicit. It was never my intention to argue that the benefits came from the implicitness - I just want there to be a way to choose between the two behaviors. -- Kevin Bourrillion | Java Librarian | Google, Inc. | kevinb at google.com -------------- next part -------------- An HTML attachment was scrubbed... URL: From daniel.smith at oracle.com Thu May 10 22:28:02 2018 From: daniel.smith at oracle.com (Dan Smith) Date: Thu, 10 May 2018 16:28:02 -0600 Subject: Exhaustiveness in switch In-Reply-To: <9D1E2611-7E5D-4C67-9BB4-FF3109A46CF9@oracle.com> References: <07a4d56e-3934-2940-732d-a0615bf2f110@oracle.com> <9D1E2611-7E5D-4C67-9BB4-FF3109A46CF9@oracle.com> Message-ID: > On May 10, 2018, at 2:46 PM, Guy Steele wrote: > >> On May 10, 2018, at 4:54 PM, Brian Goetz > wrote: >> >>> * It would feel strange to even bother applying this exhaustiveness goo to byte switches. If we ever had ranges.... of course then, any type of switch could join the party. (I don't know whether ranges are a thing we're considering or not and I'm not pushing that we do.) >> >> Yeah, its on the edge. Its a no-brainer for `boolean`, its nuts for `int` (without ranges), but its vaguely defensible for `byte`. Though I can't really get too excited about it. > > The choice is not just among four sizes of integer. One could imagine recognizing certain idioms such as > > switch (myInt & 7) { > case 2, 3, 5, 7 -> ?prime?; > case 0, 1, 4 -> ?square?; > case 6 -> ?perfect?; > } > > and understanding that they are exhaustive. Dunno if the compiler guys want to go there. We can teach the compiler a few properties of primitive numbers, but we can't effectively teach it about a random WidgetStateMachine. (Like, maybe if one field is null, then the WidgetState will be one of 3 possible enum values, out of 33 total. This is totally obvious to people who know about WidgetStateMachines, why does the compiler make me write extra code?!?) But an idea I've raised is that while the compiler's ability to prove exhaustiveness will always be limited, a user might appreciate _asserting_ exhaustiveness in some extremely lightweight way. That would opt out of any compile-time checking ("looks like you missed a case"), and instead, like a cast, would give you runtime checks for unexpected inputs ("you told me I wouldn't see this value, but I did"). Brian's response to this, conveyed in the OP, is that he sees forcing an explicit "default -> unexpected input" case as a feature, not a bug. Which, yeah, I can see a reader sometimes wanting an explanation in an error message. But sometimes I think you just want to implicitly assert something you expect to be true ("this Object is a String", "this value can be dereferenced", "this number is a valid array index"). The bottom line is that it's not clear whether that extra modifier on switch (or whatever) which would opt in to runtime checking is worth the extra complexity. But maybe there's something there, in conjunction with a modifier (or whatever) which would opt in to compile-time checking. -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Thu May 10 22:52:40 2018 From: brian.goetz at oracle.com (Brian Goetz) Date: Thu, 10 May 2018 18:52:40 -0400 Subject: Exhaustiveness in switch In-Reply-To: References: <07a4d56e-3934-2940-732d-a0615bf2f110@oracle.com> Message-ID: <78e12e9f-010f-5e76-bb3c-1560b7ad7bcd@oracle.com> OK, but consider these cases. Case 1: ??? enum E { A, B } ??? ... ??? switch (e) { ??????? case A -> ... ??????? case B -> ... ??????? default: throw ...; ??? } Now, we add "C" to E and recompile.? No compilation error, and it throws on input C. Case 2: ??? enum E { A, B } ??? ... ??? switch (e) { ??????? case A -> ... ??????? case B -> ... ??????? // implicit throwing default ??? } Again, we add C and recompile.? Now we get a compilation error, because the switch isn't exhaustive. Case 3: compiler doesn't try to reason about exhaustiveness of enums. ??? enum E { A, B } ??? ... ??? switch (e) { ??????? case A -> ... ??????? case B -> ... ??? } And we get a compilation error because there's no default. I was under the impression you were a big fan of (2), because then the compiler notifies you when your switch becomes non-exhaustive.? With an explicit default (1), or no implicit throwing default (3), you lose that. Can you clarify? On 5/10/2018 5:05 PM, Kevin Bourrillion wrote: > The only distinction I am discussing now is whether it is implicit or > explicit.? It was never my intention to argue that the benefits came > from the implicitness - I just want there to be a way to choose > between the two behaviors. > From forax at univ-mlv.fr Thu May 10 23:06:45 2018 From: forax at univ-mlv.fr (Remi Forax) Date: Fri, 11 May 2018 01:06:45 +0200 (CEST) Subject: Exhaustiveness in switch In-Reply-To: References: Message-ID: <2097530633.1353639.1525993605727.JavaMail.zimbra@u-pem.fr> > De: "Kevin Bourrillion" > ?: "Brian Goetz" > Cc: "amber-spec-experts" > Envoy?: Jeudi 10 Mai 2018 22:44:33 > Objet: Re: Exhaustiveness in switch > * I think that for most occurrences of `default: throw...`, by far, the user > really doesn't benefit from being able to choose the exception type or the > message at all. A standardized choice of exception, and an autogenerated > message (that automatically includes the switch target, which users usually > don't bother to do themselves!), may be strictly better. +1, as one of my student put it, it's important to always go banana predictably. R?mi > On Thu, May 10, 2018 at 1:12 PM, Brian Goetz < [ mailto:brian.goetz at oracle.com | > brian.goetz at oracle.com ] > wrote: >> In the long (and indirect) thread on "Expression Switch Exception Naming", we >> eventually meandered around to the question of when should the compiler deem an >> expression switch to be exhaustive, and therefore emit a catch-all throwing >> default. Let's step back from this for a bit and remind ourselves why we care >> about this. >> Superficially, having to write a throwing default for a condition we believe to >> be impossible is annoying: >> switch (trafficLight) { >> case RED -> stop(); >> case GREEN -> driveFast(); >> case YELLOW -> driveFaster(); >> default -> throw new ExasperationException("No, we haven't added any new traffic >> light colors since the invention of the automobile, so I have no idea what " + >> trafficLight + " is"); >> } >> The annoyance here, though, is twofold: >> - I have to write code for something which I think can't happen; >> - That code is annoying to write. >> In the above, we "knew" another traffic light color was impossible, and we >> listed them all -- and the compiler knew it. This is particularly irritating. >> However, we often also see cases like this: >> void processVowel(letter) { >> switch (letter) { >> case A: ... >> case E: ... >> case I: ... >> case O: ... >> case U: ... >> default: throw new IllegalStateException("Not a vowel: " + letter); >> } >> Here, the annoyance is slightly different, in that I could not reasonably expect >> the compiler to know I'd covered all the vowels. In fact, I think the explicit >> exception in this case is useful, in that it documents an invariant known to >> the programmer but not captured in the type system. But it is still annoying >> that I have to construct a format string, construct an exception, and throw it; >> if there were easier ways to do that, I might be less annoyed. Without diving >> into the bikeshed, maybe this looks something like: >> default: throw IllegalStateException.format("Not a vowel: %s", vowel); >> The details aren't relevant, but the point is: maybe a small-ish library tweak >> would reduce the annoyance of writing such clauses. (This one isn't so bad, but >> Dan excavated a bunch that were way worse.) But, let's set this aside for a >> moment, and return back to the point of why we want the compiler to provide a >> throwing default. >> I think most of the discussion has centered on the problem of a novel value >> showing up at runtime. This is surely an issue, and must be dealt with, but the >> central issue is: a default is never able to distinguish between a >> runtime-novel value and a value we just forgot to include at compile time. It >> doesn't matter whether this default throws (as the implicit default in an >> expression switch) or does nothing (as the implicit default in statement >> switches today does). >> We agreed that we should not require the user to provide a default when they >> provide case clauses that cover the target type as of compile time (true+false >> for boolean, all the members of a sealed type, etc.) This is because the >> default you'd be forced to put in otherwise (for expression switches) is >> actually harmful; if the type were later modified to have more values, an >> explicit default would swallow them, rather than yielding an error at >> recompilation time. So it is not only annoying, but actually could cover up >> errors. >> We then went off on the wrong tangent, though, where we wondered whether it was >> OK to implicitly assume enums were sealed, since some enums are clearly >> intended to acquire new values. But the mistake was focusing on the wrong >> aspect of sealed-ness (the statement of intent to not add more values), rather >> than the compiler's ability to reason credibly about known possible values. >> So, backing up, I think we should always treat a "complete" enum expression >> switch specially -- don't require a default, and implicitly add a throwing one, >> if all the cases are specified. This way, if the assumption that you've covered >> all the cases is later broken via separate compilation, on recompilation, >> you'll discover this early, rather than at runtime. (You'll still get runtime >> protection either way.) Regardless of whether we think the enum will be >> extended in the future or not. There's no need for enums to declare themselves >> "sealed" or "non-sealed" (and such a declaration would likely be incorrect >> anyway, as it asks users to predict the future, which is error-prone.) >> Given this, I'm willing to use ICCE as a base type for the implicit exception >> (though there should be more specific subtypes.) >> Now, statement switches. It seems sad that we can't get the same kind of >> compile-time assistance over statement switches than we do over expression >> switches. We're somewhat locked in by compatibility here; statement switches >> today get an implicit "default: nothing" clause if they have no default, and we >> cannot (and don't want to) break this. So the next best thing is if the user >> could say "I want to get the same sort of compile-time verification of putative >> exhaustiveness for this statement switch as I would for expression switches." >> This would require some additional syntax (please, let's not bikeshed this >> until everything else on this topic is nailed down; this is a target of >> opportunity, not a problem to be solved Right Now.) >> Someone is likely to suggest that we should do the exhaustiveness thing for all >> three of the four new forms (statement arrow, and expression colon/arrow). Feel >> free to make this suggestion, but you're going to get the "snitch" lecture :) >> Another thing that we can do to make it easier to write throwing defaults: lean >> on intrinsics. Recall that separately, we've got a story to expose some >> compiler intrinsics for ldc() and invokedynamic(). There's room to add other >> things to this, such as the equivalent of __LINE__ and __FILE__ macros in C, or >> (relevant to this) information about the the current point in the compilation >> (such as the cases enumerated in the innermost switch.) So for example: >> default: throw SwitchException.format("Found %s, but expected one of %s", >> target, Intrinsics.switchCases()); >> or even >> default: throw SwitchException.of(target, Intrinsics.switchCases()); >> where `Intrinsics.switchCases()` would evaluate to a string that includes all >> the cases handled by the current switch (in our vowels case, this would be "A, >> E, I, O, U"). Again, not something for Right Now, but something that machinery >> that's in the pipeline can contribute to making it simpler and more uniform to >> express catch-all defaults, and thereby reduced the perceived annoyance. >> Summary: >> - For switches over any type where the compiler can enumerate the possibilities >> (includes enums, some primitives, and sealed types), always allow the user to >> leave off a default if they've specified all the known cases. >> - Use subtypes of ICCE in implicit throwing defaults. >> - Consider library enhancements to common exceptions (and maybe additional >> intrinsics) to simplify code that throws formatted exceptions. > -- > Kevin Bourrillion | Java Librarian | Google, Inc. | [ mailto:kevinb at google.com | > kevinb at google.com ] -------------- next part -------------- An HTML attachment was scrubbed... URL: From forax at univ-mlv.fr Thu May 10 23:11:04 2018 From: forax at univ-mlv.fr (Remi Forax) Date: Fri, 11 May 2018 01:11:04 +0200 (CEST) Subject: Exhaustiveness in switch In-Reply-To: References: Message-ID: <2090451731.1353721.1525993864447.JavaMail.zimbra@u-pem.fr> ----- Mail original ----- > De: "Brian Goetz" > ?: "amber-spec-experts" > Envoy?: Jeudi 10 Mai 2018 22:12:37 > Objet: Exhaustiveness in switch > In the long (and indirect) thread on "Expression Switch Exception > Naming", we eventually meandered around to the question of when should > the compiler deem an expression switch to be exhaustive, and therefore > emit a catch-all throwing default. Let's step back from this for a bit > and remind ourselves why we care about this. > > Superficially, having to write a throwing default for a condition we > believe to be impossible is annoying: > > ??? switch (trafficLight) { > ??????? case RED -> stop(); > ??????? case GREEN -> driveFast(); > ??????? case YELLOW -> driveFaster(); > ??????? default -> throw new ExasperationException("No, we haven't > added any new traffic light colors since the invention of the > automobile, so I have no idea what " + trafficLight + " is"); > ??? } > > The annoyance here, though, is twofold: > ?- I have to write code for something which I think can't happen; > ?- That code is annoying to write. > > In the above, we "knew" another traffic light color was impossible, and > we listed them all -- and the compiler knew it. This is particularly > irritating.? However, we often also see cases like this: > > ??? void processVowel(letter) { > ? ?? ?? switch (letter) { > ??? ? ?? ?? case A: ... > ??????????? case E: ... > ? ?? ?????? case I: ... > ??? ? ?? ?? case O: ... > ??????????? case U: ... > ? ?? ?????? default: throw new IllegalStateException("Not a vowel: " + > letter); > ??????? } > > Here, the annoyance is slightly different, in that I could not > reasonably expect the compiler to know I'd covered all the vowels.? In > fact, I think the explicit exception in this case is useful, in that it > documents an invariant known to the programmer but not captured in the > type system.? But it is still annoying that I have to construct a format > string, construct an exception, and throw it; if there were easier ways > to do that, I might be less annoyed.? Without diving into the bikeshed, > maybe this looks something like: > > ??????? default: throw IllegalStateException.format("Not a vowel: %s", > vowel); > > The details aren't relevant, but the point is: maybe a small-ish library > tweak would reduce the annoyance of writing such clauses. (This one > isn't so bad, but Dan excavated a bunch that were way worse.)? But, > let's set this aside for a moment, and return back to the point of why > we want the compiler to provide a throwing default. > > I think most of the discussion has centered on the problem of a novel > value showing up at runtime.? This is surely an issue, and must be dealt > with, but the central issue is: a default is never able to distinguish > between a runtime-novel value and a value we just forgot to include at > compile time.? It doesn't matter whether this default throws (as the > implicit default in an expression switch) or does nothing (as the > implicit default in statement switches today does). > > We agreed that we should not require the user to provide a default when > they provide case clauses that cover the target type as of compile time > (true+false for boolean, all the members of a sealed type, etc.)? This > is because the default you'd be forced to put in otherwise (for > expression switches) is actually harmful; if the type were later > modified to have more values, an explicit default would swallow them, > rather than yielding an error at recompilation time.? So it is not only > annoying, but actually could cover up errors. > > We then went off on the wrong tangent, though, where we wondered whether > it was OK to implicitly assume enums were sealed, since some enums are > clearly intended to acquire new values.? But the mistake was focusing on > the wrong aspect of sealed-ness (the statement of intent to not add more > values), rather than the compiler's ability to reason credibly about > known possible values. > > So, backing up, I think we should always treat a "complete" enum > expression switch specially -- don't require a default, and implicitly > add a throwing one, if all the cases are specified. This way, if the > assumption that you've covered all the cases is later broken via > separate compilation, on recompilation, you'll discover this early, > rather than at runtime.? (You'll still get runtime protection either > way.)? Regardless of whether we think the enum will be extended in the > future or not.? There's no need for enums to declare themselves "sealed" > or "non-sealed" (and such a declaration would likely be incorrect > anyway, as it asks users to predict the future, which is error-prone.) > > Given this, I'm willing to use ICCE as a base type for the implicit > exception (though there should be more specific subtypes.) yes ! > > > Now, statement switches.? It seems sad that we can't get the same kind > of compile-time assistance over statement switches than we do over > expression switches.? We're somewhat locked in by compatibility here; > statement switches today get an implicit "default: nothing" clause if > they have no default, and we cannot (and don't want to) break this.? So > the next best thing is if the user could say "I want to get the same > sort of compile-time verification of putative exhaustiveness for this > statement switch as I would for expression switches."? This would > require some additional syntax (please, let's not bikeshed this until > everything else on this topic is nailed down; this is a target of > opportunity, not a problem to be solved Right Now.) > > Someone is likely to suggest that we should do the exhaustiveness thing > for all three of the four new forms (statement arrow, and expression > colon/arrow).? Feel free to make this suggestion, but you're going to > get the "snitch" lecture :) > > > Another thing that we can do to make it easier to write throwing > defaults: lean on intrinsics.? Recall that separately, we've got a story > to expose some compiler intrinsics for ldc() and invokedynamic(). > There's room to add other things to this, such as the equivalent of > __LINE__ and __FILE__ macros in C, or (relevant to this) information > about the the current point in the compilation (such as the cases > enumerated in the innermost switch.)? So for example: > > ??? default: throw SwitchException.format("Found %s, but expected one > of %s", > ????????????????????????????????????????? target, > Intrinsics.switchCases()); > > or even > > ??? default: throw SwitchException.of(target, Intrinsics.switchCases()); > > where `Intrinsics.switchCases()` would evaluate to a string that > includes all the cases handled by the current switch (in our vowels > case, this would be "A, E, I, O, U").? Again, not something for Right > Now, but something that machinery that's in the pipeline can contribute > to making it simpler and more uniform to express catch-all defaults, and > thereby reduced the perceived annoyance. I think it's a little too magic, even for me. > > > Summary: > ?- For switches over any type where the compiler can enumerate the > possibilities (includes enums, some primitives, and sealed types), > always allow the user to leave off a default if they've specified all > the known cases. > ?- Use subtypes of ICCE in implicit throwing defaults. > ?- Consider library enhancements to common exceptions (and maybe > additional intrinsics) to simplify code that throws formatted exceptions. I do not think it's important to list existing case when reporting the error, thus i do not think Intrinsics.switchCases() worth its own weight. R?mi From forax at univ-mlv.fr Thu May 10 23:20:33 2018 From: forax at univ-mlv.fr (Remi Forax) Date: Fri, 11 May 2018 01:20:33 +0200 (CEST) Subject: Treatment of nested 'break' In-Reply-To: <26cb201a-b59c-f3f3-c8e1-11e1b1e30598@oracle.com> References: <2C0702D8-31BF-4BAF-A695-0E2B2A41C868@oracle.com> <672B6182-0970-4747-B041-DE4C20157784@oracle.com> <2FC4A094-DCAF-48D0-9DA2-B584632D9DB1@oracle.com> <984333b2-de40-bd42-3b25-4204904fef8e@oracle.com> <3B85A86A-064F-4B3C-9AAA-1FD123E52F6C@oracle.com> <26cb201a-b59c-f3f3-c8e1-11e1b1e30598@oracle.com> Message-ID: <493602570.1354074.1525994433910.JavaMail.zimbra@u-pem.fr> > De: "Brian Goetz" > ?: "Kevin Bourrillion" , "Guy Steele" > Cc: "amber-spec-experts" > Envoy?: Jeudi 10 Mai 2018 22:04:15 > Objet: Re: Treatment of nested 'break' > This might not help, but perhaps think of it as a compound keyword; "break > switch" is not "break with an argument of switch", but a multi-word keyword > itself. > (Back in lambda, when we explored the consequence of using "return" in lambda, > and observed it foreclosed on nonlocal return should we ever want to get there, > we briefly discussed "long return" as a compound keyword for that case. Same > game.) > Personally if I saw "break while", I think I'd immediately know what that means, > and might even thank the author for being clear. You can also use any other word instead of break or break switch. By example, breakswitch 3; R?mi > On 5/10/2018 3:57 PM, Kevin Bourrillion wrote: >> I'm just going to say that naming a keyword as the argument of another keyword >> seems novel and unprecedented for Java, and as such I think should require >> pretty strong justification. >> On Thu, May 10, 2018 at 12:12 PM, Guy Steele < [ mailto:guy.steele at oracle.com | >> guy.steele at oracle.com ] > wrote: >>>> On May 10, 2018, at 3:06 PM, Brian Goetz < [ mailto:brian.goetz at oracle.com | >>> > brian.goetz at oracle.com ] > wrote: >>>>> I think these are both valid explanations, with different outcomes, but anyway >>>>> it's fair to say that it would be confusing to have the latter perspective and >>> >> then try to explain how a value break can get past a surrounding 'for' loop. >>>> One option is: you can't. While I agree there is code that one might like to >>>> write that is made cumbersome by this, it's a valid option, and not one that is >>> > utterly terrible. >>>> Another option is to extend the break syntax along the lines of the proposed >>>> continue syntax. Suppose for every continuable construct x (for, while, switch) >>>> we supported "continue x". So for every breakable construct y we could support >>>> "break y". If a for loop were enclosed in an expression switch, you could then >>> > say "break switch e". Then >>> > if (foo) >>> > break; >>> > else >>> > break 3; >>> > becomes >>> > if (foo) >>> > break for; >>> > else >>> > break switch 3; >>> > and it is much more obvious what is going on. >>> If we are willing to pile up keywords in that manner, an alternate possibility >>> is to spell a value-returning break in a different way: >>> return switch ; >>> Then your example can become (I have added the implicit context): >>> switch (?) { case 17 -> { >>> ? >>> for (?) { >>> ... >>> if (foo) >>> break; >>> else >>> return switch 3; >>> ? } >>> ? } >>> ? } >>> The additional advantage of this approach is that it completely eliminates the >>> syntactic ambiguity between >>> break variableName; >>> and >>> break labelName; >>> Given that we think most occurrences of ?return switch? (or ?switch return?, >>> take your pick) will be abbreviated by -> anyway, this might be an acceptable >>> approach. >>> You can then still choose to go ahead and also allow things like >>> break for; >>> break switch; >>> break while; >>> continue for; >>> continue switch; >>> but that can be a separate decision; these become simply a way to avoid using >>> statement labels. >>> ?Guy >> -- >> Kevin Bourrillion | Java Librarian | Google, Inc. | [ mailto:kevinb at google.com | >> kevinb at google.com ] -------------- next part -------------- An HTML attachment was scrubbed... URL: From kevinb at google.com Fri May 11 00:06:59 2018 From: kevinb at google.com (Kevin Bourrillion) Date: Thu, 10 May 2018 17:06:59 -0700 Subject: Treatment of nested 'break' In-Reply-To: <26cb201a-b59c-f3f3-c8e1-11e1b1e30598@oracle.com> References: <2C0702D8-31BF-4BAF-A695-0E2B2A41C868@oracle.com> <738BE148-1431-41C4-A559-5C525F0957E8@oracle.com> <672B6182-0970-4747-B041-DE4C20157784@oracle.com> <2FC4A094-DCAF-48D0-9DA2-B584632D9DB1@oracle.com> <984333b2-de40-bd42-3b25-4204904fef8e@oracle.com> <3B85A86A-064F-4B3C-9AAA-1FD123E52F6C@oracle.com> <26cb201a-b59c-f3f3-c8e1-11e1b1e30598@oracle.com> Message-ID: On Thu, May 10, 2018 at 1:04 PM, Brian Goetz wrote: This might not help, but perhaps think of it as a compound keyword; "break > switch" is not "break with an argument of switch", but a multi-word keyword > itself. > Well, then multi-word keywords are the thing that is novel and should require very strong justification. :-) But no. I've gotta disagree with this: If we tell users that they can do "break while", "break for", "continue while", "continue for", and "break switch", no one's mental model will be that those are five different new keywords. There is a very obvious orthogonal separation between (first) what to do and (second) at what scope to do it. That's what I meant by "argument of". Personally if I saw "break while", I think I'd immediately know what that > means, and might even thank the author for being clear. > It's not bad. Here's a quick tidbit from our codebase: - Labeled break/continue is *unfathomably* rare -- a rough estimate is 0.07% of all break/continue statements. (Just to be clear, no, we don't have any kind of style guide rule about avoiding the use of labels, or static analysis complaining about it, etc.) - And even among this small 0.3%, in virtually every one of them the surrounding loops are of the same kind, so `break ` would not be applicable. On 5/10/2018 3:57 PM, Kevin Bourrillion wrote: > > I'm just going to say that naming a keyword as the argument of another > keyword seems novel and unprecedented for Java, and as such I think should > require pretty strong justification. > > > On Thu, May 10, 2018 at 12:12 PM, Guy Steele > wrote: > >> >> > On May 10, 2018, at 3:06 PM, Brian Goetz >> wrote: >> > >> > >> >> I think these are both valid explanations, with different outcomes, >> but anyway it's fair to say that it would be confusing to have the latter >> perspective and then try to explain how a value break can get past a >> surrounding 'for' loop. >> > >> > One option is: you can't. While I agree there is code that one might >> like to write that is made cumbersome by this, it's a valid option, and not >> one that is utterly terrible. >> > >> > Another option is to extend the break syntax along the lines of the >> proposed continue syntax. Suppose for every continuable construct x (for, >> while, switch) we supported "continue x". So for every breakable construct >> y we could support "break y". If a for loop were enclosed in an expression >> switch, you could then say "break switch e". Then >> > >> > if (foo) >> > break; >> > else >> > break 3; >> > >> > becomes >> > >> > if (foo) >> > break for; >> > else >> > break switch 3; >> > >> > and it is much more obvious what is going on. >> >> If we are willing to pile up keywords in that manner, an alternate >> possibility is to spell a value-returning break in a different way: >> >> return switch ; >> >> Then your example can become (I have added the implicit context): >> >> switch (?) { case 17 -> { >> ? >> for (?) { >> ... >> if (foo) >> break; >> else >> return switch 3; >> ? } >> ? } >> ? } >> >> The additional advantage of this approach is that it completely >> eliminates the syntactic ambiguity between >> >> break variableName; >> >> and >> >> break labelName; >> >> Given that we think most occurrences of ?return switch? (or ?switch >> return?, take your pick) will be abbreviated by -> anyway, this might be an >> acceptable approach. >> >> You can then still choose to go ahead and also allow things like >> >> break for; >> break switch; >> break while; >> continue for; >> continue switch; >> >> but that can be a separate decision; these become simply a way to avoid >> using statement labels. >> >> ?Guy >> >> > > > -- > Kevin Bourrillion | Java Librarian | Google, Inc. | kevinb at google.com > > > -- Kevin Bourrillion | Java Librarian | Google, Inc. | kevinb at google.com -------------- next part -------------- An HTML attachment was scrubbed... URL: From kevinb at google.com Fri May 11 00:07:57 2018 From: kevinb at google.com (Kevin Bourrillion) Date: Thu, 10 May 2018 17:07:57 -0700 Subject: Treatment of nested 'break' In-Reply-To: References: <2C0702D8-31BF-4BAF-A695-0E2B2A41C868@oracle.com> <738BE148-1431-41C4-A559-5C525F0957E8@oracle.com> <672B6182-0970-4747-B041-DE4C20157784@oracle.com> <2FC4A094-DCAF-48D0-9DA2-B584632D9DB1@oracle.com> <984333b2-de40-bd42-3b25-4204904fef8e@oracle.com> <3B85A86A-064F-4B3C-9AAA-1FD123E52F6C@oracle.com> <26cb201a-b59c-f3f3-c8e1-11e1b1e30598@oracle.com> Message-ID: (Both numbers are supposed to say 0.07%.) On Thu, May 10, 2018 at 5:06 PM, Kevin Bourrillion wrote: > On Thu, May 10, 2018 at 1:04 PM, Brian Goetz > wrote: > > This might not help, but perhaps think of it as a compound keyword; "break >> switch" is not "break with an argument of switch", but a multi-word keyword >> itself. >> > > Well, then multi-word keywords are the thing that is novel and should > require very strong justification. :-) > > But no. I've gotta disagree with this: If we tell users that they can do > "break while", "break for", "continue while", "continue for", and "break > switch", no one's mental model will be that those are five different new > keywords. There is a very obvious orthogonal separation between (first) > what to do and (second) at what scope to do it. That's what I meant by > "argument of". > > > Personally if I saw "break while", I think I'd immediately know what that >> means, and might even thank the author for being clear. >> > > It's not bad. > > Here's a quick tidbit from our codebase: > > - Labeled break/continue is *unfathomably* rare -- a rough estimate is > 0.07% of all break/continue statements. (Just to be clear, no, we don't > have any kind of style guide rule about avoiding the use of labels, or > static analysis complaining about it, etc.) > > - And even among this small 0.3%, in virtually every one of them the > surrounding loops are of the same kind, so `break ` would not be > applicable. > > > > > On 5/10/2018 3:57 PM, Kevin Bourrillion wrote: >> >> I'm just going to say that naming a keyword as the argument of another >> keyword seems novel and unprecedented for Java, and as such I think should >> require pretty strong justification. >> >> >> On Thu, May 10, 2018 at 12:12 PM, Guy Steele >> wrote: >> >>> >>> > On May 10, 2018, at 3:06 PM, Brian Goetz >>> wrote: >>> > >>> > >>> >> I think these are both valid explanations, with different outcomes, >>> but anyway it's fair to say that it would be confusing to have the latter >>> perspective and then try to explain how a value break can get past a >>> surrounding 'for' loop. >>> > >>> > One option is: you can't. While I agree there is code that one might >>> like to write that is made cumbersome by this, it's a valid option, and not >>> one that is utterly terrible. >>> > >>> > Another option is to extend the break syntax along the lines of the >>> proposed continue syntax. Suppose for every continuable construct x (for, >>> while, switch) we supported "continue x". So for every breakable construct >>> y we could support "break y". If a for loop were enclosed in an expression >>> switch, you could then say "break switch e". Then >>> > >>> > if (foo) >>> > break; >>> > else >>> > break 3; >>> > >>> > becomes >>> > >>> > if (foo) >>> > break for; >>> > else >>> > break switch 3; >>> > >>> > and it is much more obvious what is going on. >>> >>> If we are willing to pile up keywords in that manner, an alternate >>> possibility is to spell a value-returning break in a different way: >>> >>> return switch ; >>> >>> Then your example can become (I have added the implicit context): >>> >>> switch (?) { case 17 -> { >>> ? >>> for (?) { >>> ... >>> if (foo) >>> break; >>> else >>> return switch 3; >>> ? } >>> ? } >>> ? } >>> >>> The additional advantage of this approach is that it completely >>> eliminates the syntactic ambiguity between >>> >>> break variableName; >>> >>> and >>> >>> break labelName; >>> >>> Given that we think most occurrences of ?return switch? (or ?switch >>> return?, take your pick) will be abbreviated by -> anyway, this might be an >>> acceptable approach. >>> >>> You can then still choose to go ahead and also allow things like >>> >>> break for; >>> break switch; >>> break while; >>> continue for; >>> continue switch; >>> >>> but that can be a separate decision; these become simply a way to avoid >>> using statement labels. >>> >>> ?Guy >>> >>> >> >> >> -- >> Kevin Bourrillion | Java Librarian | Google, Inc. | kevinb at google.com >> >> >> > > > -- > Kevin Bourrillion | Java Librarian | Google, Inc. | kevinb at google.com > -- Kevin Bourrillion | Java Librarian | Google, Inc. | kevinb at google.com -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Fri May 11 00:25:47 2018 From: brian.goetz at oracle.com (Brian Goetz) Date: Thu, 10 May 2018 20:25:47 -0400 Subject: Treatment of nested 'break' In-Reply-To: <493602570.1354074.1525994433910.JavaMail.zimbra@u-pem.fr> References: <2C0702D8-31BF-4BAF-A695-0E2B2A41C868@oracle.com> <672B6182-0970-4747-B041-DE4C20157784@oracle.com> <2FC4A094-DCAF-48D0-9DA2-B584632D9DB1@oracle.com> <984333b2-de40-bd42-3b25-4204904fef8e@oracle.com> <3B85A86A-064F-4B3C-9AAA-1FD123E52F6C@oracle.com> <26cb201a-b59c-f3f3-c8e1-11e1b1e30598@oracle.com> <493602570.1354074.1525994433910.JavaMail.zimbra@u-pem.fr> Message-ID: While ?no new keywords? is not a hard and fast rule, remember that the cost of adding conditional keywords is between 10x and 1000x of that of reusing an existing keyword (depending on where it occurs in the grammar.) So its fine to suggest alternatives, but bear in mind that alternatives are by no means cost-free. (When we suggest new keywords, we?ve already done the cost analysis to ensure its at the low end of the spectrum.) > On May 10, 2018, at 7:20 PM, Remi Forax wrote: > > > > De: "Brian Goetz" > ?: "Kevin Bourrillion" , "Guy Steele" > Cc: "amber-spec-experts" > Envoy?: Jeudi 10 Mai 2018 22:04:15 > Objet: Re: Treatment of nested 'break' > This might not help, but perhaps think of it as a compound keyword; "break switch" is not "break with an argument of switch", but a multi-word keyword itself. > > (Back in lambda, when we explored the consequence of using "return" in lambda, and observed it foreclosed on nonlocal return should we ever want to get there, we briefly discussed "long return" as a compound keyword for that case. Same game.) > > Personally if I saw "break while", I think I'd immediately know what that means, and might even thank the author for being clear. > > You can also use any other word instead of break or break switch. > By example, > breakswitch 3; > > R?mi > > > On 5/10/2018 3:57 PM, Kevin Bourrillion wrote: > I'm just going to say that naming a keyword as the argument of another keyword seems novel and unprecedented for Java, and as such I think should require pretty strong justification. > > > On Thu, May 10, 2018 at 12:12 PM, Guy Steele > wrote: > > > On May 10, 2018, at 3:06 PM, Brian Goetz > wrote: > > > > > >> I think these are both valid explanations, with different outcomes, but anyway it's fair to say that it would be confusing to have the latter perspective and then try to explain how a value break can get past a surrounding 'for' loop. > > > > One option is: you can't. While I agree there is code that one might like to write that is made cumbersome by this, it's a valid option, and not one that is utterly terrible. > > > > Another option is to extend the break syntax along the lines of the proposed continue syntax. Suppose for every continuable construct x (for, while, switch) we supported "continue x". So for every breakable construct y we could support "break y". If a for loop were enclosed in an expression switch, you could then say "break switch e". Then > > > > if (foo) > > break; > > else > > break 3; > > > > becomes > > > > if (foo) > > break for; > > else > > break switch 3; > > > > and it is much more obvious what is going on. > > If we are willing to pile up keywords in that manner, an alternate possibility is to spell a value-returning break in a different way: > > return switch ; > > Then your example can become (I have added the implicit context): > > switch (?) { case 17 -> { > ? > for (?) { > ... > if (foo) > break; > else > return switch 3; > ? } > ? } > ? } > > The additional advantage of this approach is that it completely eliminates the syntactic ambiguity between > > break variableName; > > and > > break labelName; > > Given that we think most occurrences of ?return switch? (or ?switch return?, take your pick) will be abbreviated by -> anyway, this might be an acceptable approach. > > You can then still choose to go ahead and also allow things like > > break for; > break switch; > break while; > continue for; > continue switch; > > but that can be a separate decision; these become simply a way to avoid using statement labels. > > ?Guy > > > > > -- > Kevin Bourrillion | Java Librarian | Google, Inc. | kevinb at google.com -------------- next part -------------- An HTML attachment was scrubbed... URL: From gavin.bierman at oracle.com Fri May 11 09:44:53 2018 From: gavin.bierman at oracle.com (Gavin Bierman) Date: Fri, 11 May 2018 10:44:53 +0100 Subject: JEP325: Switch expressions spec In-Reply-To: <0A545FDB-4EBE-4769-8449-1AA1F3914411@oracle.com> References: <8E28CEE7-0F85-485A-9AE7-15801522B06C@oracle.com> <144bd9d6-fca8-eec5-db85-156d2ad98519@oracle.com> <55cf153c-c602-24d6-8675-ee321b2d9a8d@oracle.com> <21288FC5-C2F2-4B79-9C54-3B3835FBB682@oracle.com> <0A545FDB-4EBE-4769-8449-1AA1F3914411@oracle.com> Message-ID: <8950C7E7-EDB9-4AD3-AE94-F9FB3F120C91@oracle.com> You make the point very well Guy. This is what makes non-clean-room language design so hard! I think the question is where we put our weight. Clearly we could say we worry more about people migrating existing code, in which case we would elect to support migrating from : to -> and the simplest rule is to support case p1 -> case p2 -> ?. The other view, and the one we had when designing this, was that once we ship the -> form, everyone will immediate use this all the time. Moreover, this is the one that will be in taught in all the Java 101 classes. In these courses, at the end of the switch lecture, the teacher will say: if you really need fall through. then change all your -> to :, insert some breaks etc. In this scenario the requirement is different: it?s to support case p1, p2: So the design decision is to either put our weight behind people migrating old switches to new with a simple rule, or behind people writing new switches and discovering in a handful of cases they need fall through and having to move to : form with a simple rule. Gavin > On 10 May 2018, at 03:43, 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 Rose wrote: >> >> 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 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; >>> >> >> > From kevinb at google.com Fri May 11 12:35:38 2018 From: kevinb at google.com (Kevin Bourrillion) Date: Fri, 11 May 2018 05:35:38 -0700 Subject: JEP325: Switch expressions spec In-Reply-To: <8950C7E7-EDB9-4AD3-AE94-F9FB3F120C91@oracle.com> References: <8E28CEE7-0F85-485A-9AE7-15801522B06C@oracle.com> <144bd9d6-fca8-eec5-db85-156d2ad98519@oracle.com> <55cf153c-c602-24d6-8675-ee321b2d9a8d@oracle.com> <21288FC5-C2F2-4B79-9C54-3B3835FBB682@oracle.com> <0A545FDB-4EBE-4769-8449-1AA1F3914411@oracle.com> <8950C7E7-EDB9-4AD3-AE94-F9FB3F120C91@oracle.com> Message-ID: I think it is right to be more concerned with the long-term outlook than with any temporary transitional pains (except of course for the inescapable compatibility requirement). On Fri, May 11, 2018 at 2:44 AM, Gavin Bierman wrote: > You make the point very well Guy. This is what makes non-clean-room > language design so hard! I think the question is where we put our weight. > Clearly we could say we worry more about people migrating existing code, in > which case we would elect to support migrating from : to -> and the > simplest rule is to support case p1 -> case p2 -> ?. > > The other view, and the one we had when designing this, was that once we > ship the -> form, everyone will immediate use this all the time. Moreover, > this is the one that will be in taught in all the Java 101 classes. In > these courses, at the end of the switch lecture, the teacher will say: if > you really need fall through. then change all your -> to :, insert some > breaks etc. In this scenario the requirement is different: it?s to support > case p1, p2: > > So the design decision is to either put our weight behind people migrating > old switches to new with a simple rule, or behind people writing new > switches and discovering in a handful of cases they need fall through and > having to move to : form with a simple rule. > > Gavin > > > > On 10 May 2018, at 03:43, 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 Rose wrote: > >> > >> 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 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; > >>> > >> > >> > > > > -- Kevin Bourrillion | Java Librarian | Google, Inc. | kevinb at google.com -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Fri May 11 14:33:19 2018 From: brian.goetz at oracle.com (Brian Goetz) Date: Fri, 11 May 2018 10:33:19 -0400 Subject: [constables] RFR of constants API In-Reply-To: <8d63064c-6bbd-af20-be66-31184f006e95@oracle.com> References: <451987dd-9371-552f-908d-e57fdc1f09ff@oracle.com> <1bc4edf2-c016-5fb2-fd45-b235a5e3d580@oracle.com> <4B94BFE7-6D9E-490F-BB68-6ABF5CD095B4@oracle.com> <47a62c30-cc05-89f2-86b6-ed6de6444bec@oracle.com> <8d63064c-6bbd-af20-be66-31184f006e95@oracle.com> Message-ID: <53f45fd4-1e60-9561-1f8a-faf7d91381bd@oracle.com> > * I believe the name descriptor is going to be confusing with the rest > of the API, as there are a lot of classes whose name ends with 'Desc' I think this speaks to these classes ({Type,Field,Method}Descriptor) being in the wrong place.? I think they should be in JLI, since they are basic building blocks for describing VM types.? Also should be TypeDescriptor, FieldTypeDescriptor, MethodTypeDescriptor. From vicente.romero at oracle.com Fri May 11 15:13:05 2018 From: vicente.romero at oracle.com (Vicente Romero) Date: Fri, 11 May 2018 11:13:05 -0400 Subject: [constables] RFR of constants API In-Reply-To: <53f45fd4-1e60-9561-1f8a-faf7d91381bd@oracle.com> References: <451987dd-9371-552f-908d-e57fdc1f09ff@oracle.com> <1bc4edf2-c016-5fb2-fd45-b235a5e3d580@oracle.com> <4B94BFE7-6D9E-490F-BB68-6ABF5CD095B4@oracle.com> <47a62c30-cc05-89f2-86b6-ed6de6444bec@oracle.com> <8d63064c-6bbd-af20-be66-31184f006e95@oracle.com> <53f45fd4-1e60-9561-1f8a-faf7d91381bd@oracle.com> Message-ID: <904e26c2-4b3c-b41a-aeb8-24216f9e8b04@oracle.com> Hi, I have updated the public webrev with the changes proposed below. http://cr.openjdk.java.net/~vromero/constant.api/webrev.03/constants.api.patch Thanks, Vicente On 05/11/2018 10:33 AM, Brian Goetz wrote: > >> * I believe the name descriptor is going to be confusing with the >> rest of the API, as there are a lot of classes whose name ends with >> 'Desc' > > I think this speaks to these classes ({Type,Field,Method}Descriptor) > being in the wrong place.? I think they should be in JLI, since they > are basic building blocks for describing VM types.? Also should be > TypeDescriptor, FieldTypeDescriptor, MethodTypeDescriptor. > From forax at univ-mlv.fr Mon May 14 12:47:55 2018 From: forax at univ-mlv.fr (forax at univ-mlv.fr) Date: Mon, 14 May 2018 14:47:55 +0200 (CEST) Subject: Treatment of nested 'break' In-Reply-To: References: <2C0702D8-31BF-4BAF-A695-0E2B2A41C868@oracle.com> <984333b2-de40-bd42-3b25-4204904fef8e@oracle.com> <3B85A86A-064F-4B3C-9AAA-1FD123E52F6C@oracle.com> <26cb201a-b59c-f3f3-c8e1-11e1b1e30598@oracle.com> <493602570.1354074.1525994433910.JavaMail.zimbra@u-pem.fr> Message-ID: <391149950.269783.1526302075612.JavaMail.zimbra@u-pem.fr> > De: "Brian Goetz" > ?: "Remi Forax" > Cc: "Kevin Bourrillion" , "Guy Steele" > , "amber-spec-experts" > > Envoy?: Vendredi 11 Mai 2018 02:25:47 > Objet: Re: Treatment of nested 'break' > While ?no new keywords? is not a hard and fast rule, remember that the cost of > adding conditional keywords is between 10x and 1000x of that of reusing an > existing keyword (depending on where it occurs in the grammar.) So its fine to > suggest alternatives, but bear in mind that alternatives are by no means > cost-free. (When we suggest new keywords, we?ve already done the cost analysis > to ensure its at the low end of the spectrum.) yes, at the same time, people use keywords as a gateway for the semantics, so re-using a keyword with a different semantics may cost a lot in term of debugging time. Anyway, sleeping on this problem the last night remember me that there is another view of this issue. One thing i've remarked with the introduction of 'var' is that writing expression oriented codes helps a lot, by example, instead of List list; if (foo) { list = ... } else { list = ... } it's easier to write var list = (foo)? ...: ...; there is another construction in Java apart switch that may need an expression version, the try syntax (and its brother the try-with-resources) using the same example as above, instead of List list; try { list = ... } catch(IOException e) { list = ... } it's easier to write var list = try { break ... } catch(IOException e) { break ... }; My fear is that if we use break as identifier, it works for 'switch' but not that well for 'try'. I do not suggest that we should implement try expression, just that 'break' makes less sense if one time we want to retrofit try to introduce a try expression. regards, R?mi >> On May 10, 2018, at 7:20 PM, Remi Forax < [ mailto:forax at univ-mlv.fr | >> forax at univ-mlv.fr ] > wrote: >>> De: "Brian Goetz" < [ mailto:brian.goetz at oracle.com | brian.goetz at oracle.com ] > >>> ?: "Kevin Bourrillion" < [ mailto:kevinb at google.com | kevinb at google.com ] >, >>> "Guy Steele" < [ mailto:guy.steele at oracle.com | guy.steele at oracle.com ] > >>> Cc: "amber-spec-experts" < [ mailto:amber-spec-experts at openjdk.java.net | >>> amber-spec-experts at openjdk.java.net ] > >>> Envoy?: Jeudi 10 Mai 2018 22:04:15 >>> Objet: Re: Treatment of nested 'break' >>> This might not help, but perhaps think of it as a compound keyword; "break >>> switch" is not "break with an argument of switch", but a multi-word keyword >>> itself. >>> (Back in lambda, when we explored the consequence of using "return" in lambda, >>> and observed it foreclosed on nonlocal return should we ever want to get there, >>> we briefly discussed "long return" as a compound keyword for that case. Same >>> game.) >>> Personally if I saw "break while", I think I'd immediately know what that means, >>> and might even thank the author for being clear. >> You can also use any other word instead of break or break switch. >> By example, >> breakswitch 3; >> R?mi >>> On 5/10/2018 3:57 PM, Kevin Bourrillion wrote: >>>> I'm just going to say that naming a keyword as the argument of another keyword >>>> seems novel and unprecedented for Java, and as such I think should require >>>> pretty strong justification. >>>> On Thu, May 10, 2018 at 12:12 PM, Guy Steele < [ mailto:guy.steele at oracle.com | >>>> guy.steele at oracle.com ] > wrote: >>>>>> On May 10, 2018, at 3:06 PM, Brian Goetz < [ mailto:brian.goetz at oracle.com | >>>>> > brian.goetz at oracle.com ] > wrote: >>>>>>> I think these are both valid explanations, with different outcomes, but anyway >>>>>>> it's fair to say that it would be confusing to have the latter perspective and >>>>> >> then try to explain how a value break can get past a surrounding 'for' loop. >>>>>> One option is: you can't. While I agree there is code that one might like to >>>>>> write that is made cumbersome by this, it's a valid option, and not one that is >>>>> > utterly terrible. >>>>>> Another option is to extend the break syntax along the lines of the proposed >>>>>> continue syntax. Suppose for every continuable construct x (for, while, switch) >>>>>> we supported "continue x". So for every breakable construct y we could support >>>>>> "break y". If a for loop were enclosed in an expression switch, you could then >>>>> > say "break switch e". Then >>>>> > if (foo) >>>>> > break; >>>>> > else >>>>> > break 3; >>>>> > becomes >>>>> > if (foo) >>>>> > break for; >>>>> > else >>>>> > break switch 3; >>>>> > and it is much more obvious what is going on. >>>>> If we are willing to pile up keywords in that manner, an alternate possibility >>>>> is to spell a value-returning break in a different way: >>>>> return switch ; >>>>> Then your example can become (I have added the implicit context): >>>>> switch (?) { case 17 -> { >>>>> ? >>>>> for (?) { >>>>> ... >>>>> if (foo) >>>>> break; >>>>> else >>>>> return switch 3; >>>>> ? } >>>>> ? } >>>>> ? } >>>>> The additional advantage of this approach is that it completely eliminates the >>>>> syntactic ambiguity between >>>>> break variableName; >>>>> and >>>>> break labelName; >>>>> Given that we think most occurrences of ?return switch? (or ?switch return?, >>>>> take your pick) will be abbreviated by -> anyway, this might be an acceptable >>>>> approach. >>>>> You can then still choose to go ahead and also allow things like >>>>> break for; >>>>> break switch; >>>>> break while; >>>>> continue for; >>>>> continue switch; >>>>> but that can be a separate decision; these become simply a way to avoid using >>>>> statement labels. >>>>> ?Guy >>>> -- >>>> Kevin Bourrillion | Java Librarian | Google, Inc. | [ mailto:kevinb at google.com | >>>> kevinb at google.com ] -------------- next part -------------- An HTML attachment was scrubbed... URL: From maurizio.cimadamore at oracle.com Mon May 14 13:55:06 2018 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Mon, 14 May 2018 14:55:06 +0100 Subject: [constables] RFR of constants API In-Reply-To: <53f45fd4-1e60-9561-1f8a-faf7d91381bd@oracle.com> References: <451987dd-9371-552f-908d-e57fdc1f09ff@oracle.com> <1bc4edf2-c016-5fb2-fd45-b235a5e3d580@oracle.com> <4B94BFE7-6D9E-490F-BB68-6ABF5CD095B4@oracle.com> <47a62c30-cc05-89f2-86b6-ed6de6444bec@oracle.com> <8d63064c-6bbd-af20-be66-31184f006e95@oracle.com> <53f45fd4-1e60-9561-1f8a-faf7d91381bd@oracle.com> Message-ID: On 11/05/18 15:33, Brian Goetz wrote: > >> * I believe the name descriptor is going to be confusing with the >> rest of the API, as there are a lot of classes whose name ends with >> 'Desc' > > I think this speaks to these classes ({Type,Field,Method}Descriptor) > being in the wrong place.? I think they should be in JLI, since they > are basic building blocks for describing VM types.? Also should be > TypeDescriptor, FieldTypeDescriptor, MethodTypeDescriptor. > I'm fine with this choice. It's actually a tie between j.l.invoke and j.l (since Class is there), but I think I'm ok with the j.l.invoke interpretation of them being VM thingies. Maurizio From vicente.romero at oracle.com Tue May 15 21:31:43 2018 From: vicente.romero at oracle.com (Vicente Romero) Date: Tue, 15 May 2018 17:31:43 -0400 Subject: [constables] RFR of constants API In-Reply-To: <451987dd-9371-552f-908d-e57fdc1f09ff@oracle.com> References: <451987dd-9371-552f-908d-e57fdc1f09ff@oracle.com> Message-ID: <17655735-7f4e-3f24-8802-3416eed0f76d@oracle.com> Hi all, I've run javadoc [1] for the three following packages: java.lang, java.lang.invoke, and the new java.lang.invoke.constant. The highlights: - java.lang.invoke.constant: The ConstantDesc hierarchy, which models "descriptors" for constant values. (Interfaces in the ConstantDesc hierarchy correspond to the various kinds of constant pool entry in JVMS 4.4. Just as the JVM resolves a constant pool entry in order to yield a value, you can ask a ConstantDesc object to resolve itself in order to yield the value "described" by the object.) Also, the factory interface Constable, which an ordinary class can implement in order to map its constant values to descriptors. - java.lang.invoke: MethodHandle, MethodType, and VarHandle implement Constable. Also, new types that model type descriptors, field descriptors, and method descriptors from JVMS 4.3. Also, the Intrinsics class with methods to instruct the compiler to generate `ldc` and `invokedynamic` bytecodes. - java.lang: Class, String, Integer, etc implement Constable. Also, Class implements j.l.i.FieldTypeDescriptor. Also, String, Integer, etc implement ConstantDesc. Also as a reference [2] is the last webrev. Thanks, Vicente [1] http://cr.openjdk.java.net/~vromero/constant.api/javadoc.03/java.base-summary.html [2] http://cr.openjdk.java.net/~vromero/constant.api/webrev.03/constants.api.patch On 04/27/2018 01:31 PM, Vicente Romero wrote: > Hi all, > > Please review the current proposal of the constants API, which are > nominal descriptor types defined in pkg java.lang.invoke.constant. The > code can be found at [1]. This API is being developed in the context > of JEP 303: Intrinsics for the LDC and INVOKEDYNAMIC Instructions [2] > > Thanks in advance for your comments, > Vicente > > [1] http://cr.openjdk.java.net/~vromero/constant.api/webrev.00 > [2] http://openjdk.java.net/jeps/303 From vicente.romero at oracle.com Tue May 15 21:36:08 2018 From: vicente.romero at oracle.com (Vicente Romero) Date: Tue, 15 May 2018 17:36:08 -0400 Subject: RFR of constants API In-Reply-To: <17655735-7f4e-3f24-8802-3416eed0f76d@oracle.com> References: <17655735-7f4e-3f24-8802-3416eed0f76d@oracle.com> Message-ID: <5f4fc180-b9d4-29b4-cb09-e9c2d8467090@oracle.com> *note: *forwarding to amber-dev, also I forgot adding that this work was done under JEP 303 but will be put back under its own JEP earlier than 303. Hi all, I've run javadoc [1] for the three following packages: java.lang, java.lang.invoke, and the new java.lang.invoke.constant. The highlights: - java.lang.invoke.constant: The ConstantDesc hierarchy, which models "descriptors" for constant values. (Interfaces in the ConstantDesc hierarchy correspond to the various kinds of constant pool entry in JVMS 4.4. Just as the JVM resolves a constant pool entry in order to yield a value, you can ask a ConstantDesc object to resolve itself in order to yield the value "described" by the object.) Also, the factory interface Constable, which an ordinary class can implement in order to map its constant values to descriptors. - java.lang.invoke: MethodHandle, MethodType, and VarHandle implement Constable. Also, new types that model type descriptors, field descriptors, and method descriptors from JVMS 4.3. Also, the Intrinsics class with methods to instruct the compiler to generate `ldc` and `invokedynamic` bytecodes. - java.lang: Class, String, Integer, etc implement Constable. Also, Class implements j.l.i.FieldTypeDescriptor. Also, String, Integer, etc implement ConstantDesc. Also as a reference [2] is the last webrev. Thanks, Vicente [1] http://cr.openjdk.java.net/~vromero/constant.api/javadoc.03/java.base-summary.html [2] http://cr.openjdk.java.net/~vromero/constant.api/webrev.03/constants.api.patch On 04/27/2018 01:31 PM, Vicente Romero wrote: > Hi all, > > Please review the current proposal of the constants API, which are > nominal descriptor types defined in pkg java.lang.invoke.constant. The > code can be found at [1]. This API is being developed in the context > of JEP 303: Intrinsics for the LDC and INVOKEDYNAMIC Instructions [2] > > Thanks in advance for your comments, > Vicente > > [1] http://cr.openjdk.java.net/~vromero/constant.api/webrev.00 > [2] http://openjdk.java.net/jeps/303 -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Wed May 16 12:39:05 2018 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 16 May 2018 08:39:05 -0400 Subject: RFR of constants API In-Reply-To: <5f4fc180-b9d4-29b4-cb09-e9c2d8467090@oracle.com> References: <17655735-7f4e-3f24-8802-3416eed0f76d@oracle.com> <5f4fc180-b9d4-29b4-cb09-e9c2d8467090@oracle.com> Message-ID: <61866666-B8FB-46C7-8019-F9F79257A218@oracle.com> I?ve split this work off from JEP 303: https://bugs.openjdk.java.net/browse/JDK-8203252 > On May 15, 2018, at 5:36 PM, Vicente Romero wrote: > > note: forwarding to amber-dev, also I forgot adding that this work was done under JEP 303 but will be put back under its own JEP earlier than 303. > > Hi all, > I've run javadoc [1] for the three following packages: java.lang, > java.lang.invoke, and the new java.lang.invoke.constant. The highlights: > > - java.lang.invoke.constant: The ConstantDesc hierarchy, which models > "descriptors" for constant values. (Interfaces in the ConstantDesc > hierarchy correspond to the various kinds of constant pool entry in JVMS > 4.4. Just as the JVM resolves a constant pool entry in order to yield a > value, you can ask a ConstantDesc object to resolve itself in order to > yield the value "described" by the object.) Also, the factory interface > Constable, which an ordinary class can implement in order to map its > constant values to descriptors. > > - java.lang.invoke: MethodHandle, MethodType, and VarHandle implement > Constable. Also, new types that model type descriptors, field > descriptors, and method descriptors from JVMS 4.3. Also, the Intrinsics > class with methods to instruct the compiler to generate `ldc` and > `invokedynamic` bytecodes. > > - java.lang: Class, String, Integer, etc implement Constable. Also, > Class implements j.l.i.FieldTypeDescriptor. Also, String, Integer, etc > implement ConstantDesc. > > Also as a reference [2] is the last webrev. > > Thanks, > Vicente > > > [1] > http://cr.openjdk.java.net/~vromero/constant.api/javadoc.03/java.base-summary.html > [2] > http://cr.openjdk.java.net/~vromero/constant.api/webrev.03/constants.api.patch > > On 04/27/2018 01:31 PM, Vicente Romero wrote: > > Hi all, > > > > Please review the current proposal of the constants API, which are > > nominal descriptor types defined in pkg java.lang.invoke.constant. The > > code can be found at [1]. This API is being developed in the context > > of JEP 303: Intrinsics for the LDC and INVOKEDYNAMIC Instructions [2] > > > > Thanks in advance for your comments, > > Vicente > > > > [1] http://cr.openjdk.java.net/~vromero/constant.api/webrev.00 > > [2] http://openjdk.java.net/jeps/303 > -------------- next part -------------- An HTML attachment was scrubbed... URL: From vicente.romero at oracle.com Wed May 16 13:45:11 2018 From: vicente.romero at oracle.com (Vicente Romero) Date: Wed, 16 May 2018 09:45:11 -0400 Subject: RFR of constants API In-Reply-To: <61866666-B8FB-46C7-8019-F9F79257A218@oracle.com> References: <17655735-7f4e-3f24-8802-3416eed0f76d@oracle.com> <5f4fc180-b9d4-29b4-cb09-e9c2d8467090@oracle.com> <61866666-B8FB-46C7-8019-F9F79257A218@oracle.com> Message-ID: I have uploaded an updated version of the webrev for the API [1] along with an updated version of the javadoc [2]. This is the change: class j.l.i.Intrinsics is not part of this API. Thanks, Vicente [1] http://cr.openjdk.java.net/~vromero/constant.api/webrev.04/ [2] http://cr.openjdk.java.net/~vromero/constant.api/javadoc.04 On 05/16/2018 08:39 AM, Brian Goetz wrote: > I?ve split this work off from JEP 303: > https://bugs.openjdk.java.net/browse/JDK-8203252 > > >> On May 15, 2018, at 5:36 PM, Vicente Romero >> > wrote: >> >> *note: *forwarding to amber-dev, also I forgot adding that this work >> was done under JEP 303 but will be put back under its own JEP earlier >> than 303. >> >> Hi all, >> I've run javadoc [1] for the three following packages: java.lang, >> java.lang.invoke, and the new java.lang.invoke.constant. The >> highlights: - java.lang.invoke.constant: The ConstantDesc hierarchy, >> which models "descriptors" for constant values. (Interfaces in the >> ConstantDesc hierarchy correspond to the various kinds of constant >> pool entry in JVMS 4.4. Just as the JVM resolves a constant pool >> entry in order to yield a value, you can ask a ConstantDesc object to >> resolve itself in order to yield the value "described" by the >> object.) Also, the factory interface Constable, which an ordinary >> class can implement in order to map its constant values to >> descriptors. - java.lang.invoke: MethodHandle, MethodType, and >> VarHandle implement Constable. Also, new types that model type >> descriptors, field descriptors, and method descriptors from JVMS 4.3. >> Also, the Intrinsics class with methods to instruct the compiler to >> generate `ldc` and `invokedynamic` bytecodes. - java.lang: Class, >> String, Integer, etc implement Constable. Also, Class implements >> j.l.i.FieldTypeDescriptor. Also, String, Integer, etc implement >> ConstantDesc. Also as a reference [2] is the last webrev. Thanks, >> Vicente >> >> [1] >> http://cr.openjdk.java.net/~vromero/constant.api/javadoc.03/java.base-summary.html >> [2] >> http://cr.openjdk.java.net/~vromero/constant.api/webrev.03/constants.api.patch >> >> On 04/27/2018 01:31 PM, Vicente Romero wrote: >> > Hi all, >> > >> > Please review the current proposal of the constants API, which are >> > nominal descriptor types defined in pkg java.lang.invoke.constant. The >> > code can be found at [1]. This API is being developed in the context >> > of JEP 303: Intrinsics for the LDC and INVOKEDYNAMIC Instructions [2] >> > >> > Thanks in advance for your comments, >> > Vicente >> > >> > [1] http://cr.openjdk.java.net/~vromero/constant.api/webrev.00 >> > [2] http://openjdk.java.net/jeps/303 >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From daniel.smith at oracle.com Wed May 16 22:17:31 2018 From: daniel.smith at oracle.com (Dan Smith) Date: Wed, 16 May 2018 16:17:31 -0600 Subject: JEP325: Switch expressions spec In-Reply-To: <5A242ACE-EF32-4310-BE13-52A95EC3EC18@oracle.com> References: <8E28CEE7-0F85-485A-9AE7-15801522B06C@oracle.com> <0CF1227E-79B4-48A1-A227-86466EDB6219@oracle.com> <5A242ACE-EF32-4310-BE13-52A95EC3EC18@oracle.com> Message-ID: > On May 8, 2018, at 5:08 PM, Dan Smith wrote: > > 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 Add 15.2, switch expressions don't fall into any of the previous categories of expressions (unless we're willing to call them very verbose unary expressions). -------------- next part -------------- An HTML attachment was scrubbed... URL: From gavin.bierman at oracle.com Thu May 17 08:29:56 2018 From: gavin.bierman at oracle.com (Gavin Bierman) Date: Thu, 17 May 2018 09:29:56 +0100 Subject: JEP325: Switch expressions spec In-Reply-To: References: <8E28CEE7-0F85-485A-9AE7-15801522B06C@oracle.com> <0CF1227E-79B4-48A1-A227-86466EDB6219@oracle.com> <5A242ACE-EF32-4310-BE13-52A95EC3EC18@oracle.com> Message-ID: <310F28C7-06FF-42E2-B955-4B7DA648F88B@oracle.com> > On 16 May 2018, at 23:17, Dan Smith wrote: > >> On May 8, 2018, at 5:08 PM, Dan Smith > wrote: >> >> 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 > > Add 15.2, switch expressions don't fall into any of the previous categories of expressions (unless we're willing to call them very verbose unary expressions). > That *was* the proposal; in the draft spec there is a revised 15.15, where switch expressions are added in the production for UnaryExpressionNotPlusMinus. Gavin -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Thu May 17 15:43:11 2018 From: brian.goetz at oracle.com (Brian Goetz) Date: Thu, 17 May 2018 11:43:11 -0400 Subject: RFR of constants API In-Reply-To: References: <17655735-7f4e-3f24-8802-3416eed0f76d@oracle.com> <5f4fc180-b9d4-29b4-cb09-e9c2d8467090@oracle.com> <61866666-B8FB-46C7-8019-F9F79257A218@oracle.com> Message-ID: <8B8E80CC-6261-4416-A799-51AAFB25C0C4@oracle.com> At this stage we are also happy to take Code review comments as well as API review. Sent from my MacBook Wheel > On May 16, 2018, at 9:45 AM, Vicente Romero wrote: > > I have uploaded an updated version of the webrev for the API [1] along with an updated version of the javadoc [2]. This is the change: class j.l.i.Intrinsics is not part of this API. > > Thanks, > Vicente > > [1] http://cr.openjdk.java.net/~vromero/constant.api/webrev.04/ > [2] http://cr.openjdk.java.net/~vromero/constant.api/javadoc.04 > >> On 05/16/2018 08:39 AM, Brian Goetz wrote: >> I?ve split this work off from JEP 303: >> https://bugs.openjdk.java.net/browse/JDK-8203252 >> >> >>> On May 15, 2018, at 5:36 PM, Vicente Romero wrote: >>> >>> note: forwarding to amber-dev, also I forgot adding that this work was done under JEP 303 but will be put back under its own JEP earlier than 303. >>> >>> Hi all, >>> I've run javadoc [1] for the three following packages: java.lang, >>> java.lang.invoke, and the new java.lang.invoke.constant. The highlights: >>> >>> - java.lang.invoke.constant: The ConstantDesc hierarchy, which models >>> "descriptors" for constant values. (Interfaces in the ConstantDesc >>> hierarchy correspond to the various kinds of constant pool entry in JVMS >>> 4.4. Just as the JVM resolves a constant pool entry in order to yield a >>> value, you can ask a ConstantDesc object to resolve itself in order to >>> yield the value "described" by the object.) Also, the factory interface >>> Constable, which an ordinary class can implement in order to map its >>> constant values to descriptors. >>> >>> - java.lang.invoke: MethodHandle, MethodType, and VarHandle implement >>> Constable. Also, new types that model type descriptors, field >>> descriptors, and method descriptors from JVMS 4.3. Also, the Intrinsics >>> class with methods to instruct the compiler to generate `ldc` and >>> `invokedynamic` bytecodes. >>> >>> - java.lang: Class, String, Integer, etc implement Constable. Also, >>> Class implements j.l.i.FieldTypeDescriptor. Also, String, Integer, etc >>> implement ConstantDesc. >>> >>> Also as a reference [2] is the last webrev. >>> >>> Thanks, >>> Vicente >>> >>> >>> [1] >>> http://cr.openjdk.java.net/~vromero/constant.api/javadoc.03/java.base-summary.html >>> [2] >>> http://cr.openjdk.java.net/~vromero/constant.api/webrev.03/constants.api.patch >>> >>> On 04/27/2018 01:31 PM, Vicente Romero wrote: >>> > Hi all, >>> > >>> > Please review the current proposal of the constants API, which are >>> > nominal descriptor types defined in pkg java.lang.invoke.constant. The >>> > code can be found at [1]. This API is being developed in the context >>> > of JEP 303: Intrinsics for the LDC and INVOKEDYNAMIC Instructions [2] >>> > >>> > Thanks in advance for your comments, >>> > Vicente >>> > >>> > [1] http://cr.openjdk.java.net/~vromero/constant.api/webrev.00 >>> > [2] http://openjdk.java.net/jeps/303 >>> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: