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