break seen as a C archaism
Guy Steele
guy.steele at oracle.com
Fri Mar 16 14:59:39 UTC 2018
> On Mar 16, 2018, at 5:39 AM, Peter Levart <peter.levart at gmail.com> wrote:
>
> Expanding on do…
Well, as long as we are fantasizing:
> On 03/16/18 09:50, Peter Levart wrote:
>> And if "while (false)" could be optional, we get:
>
> Or better yet, make "while (true)" optional even in statement do, so we can finally get away with some more boilerplate:
>
> for (;;) {
> }
>
> or
>
> while (true) {
> }
>
> and simply do:
>
> do {
> }
>
> For e-do, the choice of default "while (true)" is fine, because it aligns with the fact that there has to be a break <value> somewhere to exit it anyway because it has to yield a result. But there will be some danger that a programmer codes an infinite loop by mistake.
This idea of making “while(true)” be the default has made me realize that Java has excellent syntactic space available to support a style of programming that was mildly popular in the late 1970s and early 1980s: Dijkstra’s “guarded commands” as described in his 1976 book “A Discipline of Programming”. It’s a beautifully concise and symmetric theory of control structure, provided that you have committed to a style of programming entirely centered around assignment statements (which explains why it has largely fallen by the wayside). Consider the following tale a trip down memory lane to an alternate universe:
<fantasy serious=“FALSE">
______________________________________________________________________________
Let a guarded command in Java have this form:
case booleanExpression: statement*
(Dijkstra used the form “booleanExpression -> statement*”. It’s more Java-like to use the keyword `case` and a colon.)
______________________________________________________________________________
First, we define a statement form of do:
do { <guarded-command>* }
The semantics are: evaluate the guards of all the guarded commands; if none is true, then terminate, else nondeterministically choose some command whose guard was true, execute its statements, and then repeat this process.
It can be syntactically distinguished from the existing `do` statement in two ways: it contains guarded commands rather than simple statements, and there is no `while (expression)` at the end.
Example: { int j = 0; do { case j < n: a[j] = f(j); ++j; } }
______________________________________________________________________________
Corresponding to that is a statement form of `if`:
if { <guarded-command>* }
The semantics are: evaluate the guards of all the guarded commands; if none is true, then abort (program error), else nondeterministically choose some command whose guard was true and execute its statements.
It can be syntactically distinguished from the existing `if` statement because there is a left-brace after the keyword `if`.
Example: if { case x <= 0: a = -b; case x >= 0: a = b; }
______________________________________________________________________________
Now, to make expression forms of these puppies (something Dijkstra never envisioned), we need a way to yield values. For an `if`, we just use `break`:
int a = if { case x <= 0: break -b; case x >= 0: break b; };
______________________________________________________________________________
In the same manner as for `switch`, we can abbreviate `: break` as `->`:
int a = if { case x <= 0 -> -b; case x >= 0 -> b; };
This feels very much like an expression switch, but with choices made by boolean expressions rather than a switch value.
______________________________________________________________________________
Now, the expression form of `do` is a bit trickier, because the `do` terminates only when no guard is true, so the return value cannot be specified in any of the contained statements. The “obvious” answer is:
do { <guarded-command>* } break expression
and at this point everyone else on this mailing list breaks out the torches and pitchforks to come after me. :-)
______________________________________________________________________________
</fantasy>
—Guy
P.S. “Did you succeed in using your time machine to get guarded commands into Java?”
“Yes, but in a past that hasn’t happened yet—it’s complicated.”
(Tip of the hat to Norm Feuti.)
More information about the amber-spec-experts
mailing list