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.

No comments: