Saturday, December 23, 2017

Switch Expressions Coming to Java?

A JEP draft has been created with the title, "Switch Expressions for the Java Language." The current "Summary" states, "Extend the switch statement so that it can be used as either a statement or an expression, and improve how switch handles nulls. These will simplify everyday coding, as well as prepare the way for the use of pattern matching in switch." There are several promising characteristics of the proposed Java switch expression in its own right in addition to its enabling of the exciting Pattern Matching JEP (305).

The Java Tutorial defines a Java statement as a "complete unit of execution" that is "roughly equivalent to sentences in natural languages." It defines a Java expression as "a construct made up of variables, operators, and method invocations ... that evaluates to a single value." The current Java switch is a statement, but this draft JEP proposes that switch be supported as an expression as well.

The Switch Expression draft JEP states in its "Motivation" section, "As we prepare to enhance the Java Language to support pattern matching, several irregularities of the existing switch statement -- which have long been an irritation to users -- become impediments." The draft JEP is highly readable and contains interesting discussion points and illustrative code examples of how Java switch statement is currently often used within other Java constructors to effectively serve as an expression. The JEP draft shows how the proposal to extend switch to work as an expression in addition to being supported as a statement would improve the readability and maintainability of the code.

Java expressions need to "evaluate to a single value." The currently proposed switch expression would allow the break keyword to serve like a return in a Java method. A value could be specified following the break keyword and that value would be "returned" from the switch expression.

Because a Java expression "evaluates to a single value," a Java switch used as an expression would necessarily be required to provide a default value. An interesting twist on this covered in the draft JEP is for enums. The draft JEP states, "... in the case of an enum switch expression that covers all known cases (and eventually, switch expressions over sealed types), a default clause can be inserted by the compiler that indicates that the enum definition has changed between compile time and runtime. (This is what developers do by hand today, but having the compiler insert it is both less intrusive and likely to have a more descriptive error message than the ones written by hand.)" I found this particularly interesting because I've seen many cases where developers have either not written a "default" for a switch on the enum because all enum values at that time were covered by cases or have written a very generic error message. In fact, running into multiple examples of the latter are what finally led me to write my blog post "Log Unexpected Switch Options."

The draft JEP also covers some proposed enhancements that would benefit both the current switch statement and the new switch expression. One of these is the ability to indicate how to handle a null reference type passed to the switch statement. Today, for example, if one passes a null String to a switch statement, a NullPointerException is thrown. With this proposal, the developer could specify a case null clause. The current proposal would treat any null not explicitly handled as null is treated in switch today (by throwing a NullPointerException).

A second proposed beneficial feature for both current switch statement and proposed switch expression is to allow an individual case clause to support multiple potential matching values separated by commas. Three values for which the same behavior applies could be specified with a single case rather than with three case clauses sharing a single break.

The "switch expression draft" is still a draft that doesn't even have a number assigned to it yet and therefore is highly vulnerable to potential changes. Indeed, the proposal has already been discussed in the mailing lists and modified quite a bit, with an example being "Switch expressions -- some revisions." I found one message on the mailing list, "Switching on float/double/long," to be particularly interesting. This interesting message is full or technical and historical details including background on why today's switch statement does not support long and an interesting analysis provided by "resident floating-point expert" Joe Darcy regarding floating-point comparisons.

David Goldberg's 1991 article "What Every Computer Scientist Should Know About Floating-Point Arithmetic" is a well-known resource on understanding the complexities of floating-point arithmetic and representation. Darcy provides some interesting insight into some of these concerns and the IEEE 754 floating-point. He writes, "To address some common misunderstandings of floating-point, while it is often recommended to *not* compare floating-point values for equality, it is perfectly well-defined to do such comparisons, it just might not do what you want." Darcy addresses handling of NaN, positive zero and negative zero, and positive infinity and negative infinity. An interesting conclusion is that allowing switch on floating-point numeric type float could be implemented to really switch on the value provided by Float.floatToIntBits(float).

It appears that there could be some exciting times ahead for Java's switch if it is extended so that it can be used as an expression in addition to its current use as a statement. It's a development that could lead to cleaner code with less room for errors.

11 comments:

@DustinMarx said...

A recent amber-dev mailing list post titled "Switch expression fall through" explains that the switch expression will have fall-through just as the current switch statement does because "expression switches and statement switches are the same construct." More detailed explanations for this decision can be found in the post "break seen as a C archaism".

@DustinMarx said...

A recent amber-spec-observers list post titled "Feedback wanted: switch expression typing" requests input regarding syntax of switch expressions handling of typing related to conditional expressions handling of typing.

@DustinMarx said...

Another recent amber-spec-observers mailing list post (this one titled "Expression switch exception naming") asks for (and gets lots of) opinions on what to call the exception that is thrown when a switch expression lacks a pattern match and does not have a 'default' pattern specified.

@DustinMarx said...

The post "Compile-time type hierarchy information in pattern switch" on the amber-spec-observers mailing list starts "a conversation about expectations for what we should do for a switch at runtime that would no longer compile due to post-compilation hierarchy changes (new supertypes, hierarchy inversions, removed supertypes, final <--> nonfinal, etc.)."

@DustinMarx said...

The post "Switch translation" on the amber-spec-observers mailing list by Maurizio Cimadamore and Brian Goetz "outlines our story for translating improved switches, including both the switch improvements coming as part of JEP 325, and follow-on work to add pattern matching to switches." This extremely detailed post summarizes how current switching is supported on integer primitives, boxed integer primitives, enums, and Strings before moving onto the proposed "more general scheme."

@DustinMarx said...

Stephen Colebourne starts a thread on the amber-dev mailing list called "Expression switch feedback" that provides "some feedback on expression switches" and in which Colebourne states that he's "uncomfortable" with switch expressions being modeled as "just switches [statements] with a few enhancements." There is a lengthy series of posts that follow, including Brian Goetz's direct response.

@DustinMarx said...

Brian Goetz's message "Switch expressions -- gathering the threads" on the amber-spec-observers mailing list summarizes the "active discussion" regarding "Is this the switch expression
construct we're looking for" on the amber-dev mailing list. The message summarizes the current state of the switch expression proposal, summarizes recent conversation on the proposal, outlines some of the proposed alternatives, and focuses on issues still considered "open."

@DustinMarx said...

Gavin Bierman has posted the message "JEP325: Switch expressions spec" on the amber-spec-observers mailing list. Bierman provides a link to the specification and highlights three portions of the specification that are still not resolved.

@DustinMarx said...

Today's post "[switch] Further unification on switch" by Brian Goetz on the amber-spec-observers mailing list reviews "the work to date on switch expressions" and "a possible place we might move to" with regards to implementation of the switch expression.

@DustinMarx said...

The OpenJDK mailing list message "Next draft of JEP 325 Switch Expressions available" announces a new (June 2018) version of the "Specification for JEP 325: Switch Expressions".

@DustinMarx said...

JEP 325 ["Switch Expressions (Preview)"] has been targeted for JDK 12/Java SE 12 as described in the OpenJDK mailing list messages "JSR 386 (Java SE 12) JEP Propose to Target: 325: Switch Expressions (Preview)" and "JEP proposed to target JDK 12: 325: Switch Expressions (Preview)".