Extend switch .. case statement for all types and simple expressions (2nd update)
Ulf Zibis
Ulf.Zibis at gmx.de
Thu May 28 07:40:42 PDT 2009
I just want to see the switch..case construct serving as general purpose
_n-way fork_ in program flow. IMHO it's a smart syntax providing perfect
readability.
Only for _2-way fork_ the if..else construct is smart syntax.
Additionally if..else_if..else_if.. construct has the disadvantage of
missing fall-through facility.
I have rethought my proposal and come to more general syntax:
Proposal for SYNTAX SPECIFICATION:
switch (expression1 | booleanExpressionTemplate(?) |
substitution_of_?) {
case: [booleanOperator ]expression2 | substitution_of_? |
booleanExpressionTemplate(?)
{...}
...
}
if 'booleanOperator' is missing:
- expression1 is primitive value --> execute: expression1 == expression2
- expression1 is reference --> execute:
expression1.equals(expression2)
(sophisticated special case to aviod potential NPE):
- expression1 is reference and expression2 is CONSTANT --> execute:
expression2.equals(expression1)
Examples for booleanExpressionTemplate(?) and it's possible substitution:
"Math.sin(?) > 0.5" --> foo(bar), floatVar, intVar, PRIM_CONST
(including autoboxed Number objects)
"? >= 10 && ? < 20" --> foo(bar), primitiveVar, PRIM_CONS (including
autoboxed Number objects)
"?.equals(objectExp)" --> foo(bar), objectVar, OBJ_CONST (allows
objectVar to be null)
"objectExp.equals(?)" --> foo(bar), objectVar, OBJ_CONST (allows ? to
be null)
"stringExp.equalsIgnoreCase(?)" --> string(bar), stringVar,
STRING_CONST, "litteral"
Examples for "expression1.. [booleanOperator ]expression2" and mixed :
switch (stringExp) {
case == STRING_CONST1 : // compare for identity
{...}
case STRING_CONST2 : // compare for equality
{...}
case STRING_CONST3.equals(?) : // compare for equality, avoiding NPE
{...}
case STRING_CONST4.equalsIgnoreCase(?) : // compare for equality
ignoring case
{...}
case ?.subString(?.indexOf(STRING_CONST5)).startsWith(STRING_CONST6)
: // sophisticated
{...}
default:
{...}
}
switch (primitiveExp) {
case == CONST1 : // compare for equality
{...}
case CONST2 : // compare for equality
{...}
case myList.get(3) : // autoboxing
{...}
case > CONST3 : // compare for greater than
{...}
case ? >= 10 && ? < 20 : // range check
{...}
...
}
-Ulf
Am 31.03.2009 00:13, Ulf Zibis schrieb:
> AUTHOR(S): Ulf Zibis, Cologne, Germany
>
> OVERVIEW
> FEATURE SUMMARY: Extend switch .. case statement for all types and simple expressions.
> MAJOR ADVANTAGE:
> - Increases readability of source in concurrence to if .. else if .. else syntax.
> - Sophisticated jumps.
> - maybe in some cases javac and hotspot has chance to compute better optimized code.
> MAJOR BENEFIT:
> Stop some programmers escaping to some modern scripting language.
> MAJOR DISADVANTAGE:
> Programmers from other languages, especially C, may be confused about such rich syntax.
>
> EXAMPLES
> SIMPLE EXAMPLE:
> (1):
> switch( myObject) {
> case CONSTANT1 : doSomething(); break;
> case CONSTANT2 : doSomethingElse(); break;
> default : doSomethingDefault();
> }
> (2):
> switch( myString) {
> case equals("red") : stop(); break;
> case equals("green") : go(); break;
> default : openYourEyesForCrossingTraffic();
> }
> (3):
> switch( myString) {
> case equalsIgnoreCase("RED") : sureStop(); break;
> case equalsIgnoreCase("GREEN") : sureGo(); break;
> default : beAwareOfPoliceWachtingYou();
> }
>
> ADVANCED EXAMPLE:
> (4):
> switch( primitiveInt) {
> case == 10 : doOnlyIf10(); // alternative syntax for 'case 10:'
> case < 10 :
> case >= 20 : break;
> default : doOnlyInRange();
> }
> (5):
> switch( primitiveInt) {
> case (>= 10 && < 20) : doOnlyInRange();
> default : throw new Exception("Out of range");
> }
> (6):
> switch( myString) {
> case contains("foo") : doSomething(); break;
> case regionMatches(true, 2, otherString, 4, 6) : doSomethingElse(); break;
> default : doSomethingDefault();
> }
> (7):
> switch( myString.equals()) { // alternative: myString.equals(..)
> case "foo" : foo(); break;
> case "bar" : bar(); break;
> default : dontCare();
> }
> (8):
> switch( className.startsWith("String", ..)) { // alternative: className.startsWith("String", ?)
> case 0 : doForSimpleName(); break;
> case 9 : doForFullName(); break;
> default : canNotDecide();
> }
> (9):
> switch( anyObjectOrPrimitive instanceof) { // note, that casting is solved implicit
> case boolean, byte, ... float : break; // Don't do anything
> case double : forDouble(anyObjectOrPrimitive);
> case HashMap :
> case TreeMap : forPlattformMap(anyObjectOrPrimitive); break;
> case Map : forOtherMap(anyObjectOrPrimitive); break;
> default : forObject(anyObjectOrPrimitive);
> }
> (10): (minimizee chance for NPE)
> switch( .equals(myString)) { // alternative: ?.equals(myString)
> case "foo" : foo(); break;
> case "bar" : bar(); break;
> default : dontCare();
> }
> (11):
> switch( some_lethargic_function_we_cant_call_much().equals(..) ) {
> case "this":
> case "that": this_or_that(); break;
> case "bigjump": big(); // fall
> case "jump": jump(); break;
> case "secondlastchance":
> case "lastchance": last_chance(); break;
> default: do_default();
> }
> .. as replacement for:
> String sSomeString = some_lethargic_function_we_cant_call_much();
> if( sSomeString.equals( "this" ) || sSomeString.equals( "that" ) )
> this_or_that();
> else if( sSomeString.equals( "jump" ) || sSomeString.equals( "bigjump" ) )
> {
> if( sSomeString.equals( "bigjump" ) )
> big();
> jump();
> } else if( sSomeString.equals( "secondlastchance" ) ||
> sSomeString.equals( "lastchance" ) )
> {
> last_chance();
> } else do_default();
>
> ALTERNATIVES:
> (12):
> switch( myString) { // note the '.', I personally would prefer this alternative!
> case .equals("red") : stop(); break;
> case .equals("green") : go(); break;
> default : openYourEyesForCrossingTraffic();
> }
> (13):
> switch( primitiveInt) { // note the '.'
> case (. >= 10 && . < 20) : doOnlyInRange();
> // case (? >= 10 && ? < 20) : doOnlyInRange(); // alternative
> default : throw new Exception("Out of range");
> }
>
>
> DETAILS
> SPECIFICATION:
> The new syntax should be interpreted as
> switch ( leftExpressionPart ) {
> case rightExpressionPart1 :
> case rightExpressionPart2 :
> ...
> default :
> }
> The result of entire expression should be boolean type.
> There is shortcut for:
> leftExpressionPart: intVariable
> rightExpressionPart: == intLiteral
> (the '==' could be ommitted.)
>
> COMPILATION:
> Compiler could first pre-compile to appropriate if..then..else syntax.
> Bytecode would not be affected, but in special cases it could be more compact, if noted
> pre-compilation would be replaced by sophisticated optimization.
> TESTING:
> Compiler byte-code results for new syntax should be same than from equivalent hand-coded legacy
> if..then..else syntax
> . Exception: sophisticated optimization.
> LIBRARY SUPPORT: No supporting libraries are needed for the feature?
> REFLECTIVE APIS: There should not be any affection to reflection API.
> OTHER CHANGES: No.
> MIGRATION:
> No refactoring is needed to stay compatible.
>
> COMPATIBILITY
> BREAKING CHANGES:
> No previously valid programs are now invalid.
> ... but ATTENTION:
> If proposals from some other guys regarding "Strings in switch" would be taken into JDK 7, there
> won't be any compatible way to implement my more general proposal in future version of JDK !!!
> --> So switch .. case statement should compare for IDENTITY if not syntactically determined otherwise.
> --> compare for EQUALITY would also break semantic of existing switch .. case statement.
> Another reason, why I'm against comparing for equality by default syntax, is, that it is good
> practice to use String constants instead of widely spreaded String literals with same signature for
> numerous reasons (performance, error prone, ...). The "only-for-String" syntax would lead
> programmers to stay on widely spreaded String literals of same value.
> If constant is not available for switch variable (e.g. if read from stream), variable could be
> internalized before, so it's instance becomes identical to the existing constant.
> ===>> If just "Strings in switch" is taken over for JDK 7, there is NO NEED, to compare for equality.
> EXISTING PROGRAMS:
> Source and class files of earlier platform versions interact with the feature without any notice.
>
> REFERENCES
> http://mail.openjdk.java.net/pipermail/coin-dev/2009-February/000001.html
> http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/000213.html
> http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/000855.html
> http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/001089.html
> http://forums.java.net/jive/thread.jspa?messageID=27781沅
> http://forums.java.net/jive/thread.jspa?messageID=15769㶙
> http://forums.java.net/jive/thread.jspa?messageID=27773汽
> http://forums.java.net/jive/thread.jspa?messageID=11393ⲁ
> http://lasu2string.blogspot.com/2008/12/string-switch-small-language-changes-on.html
> EXISTING BUGS:
> http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5012262
> URL FOR PROTOTYPE (optional):
>
>
>
>
>
>
>
>
More information about the coin-dev
mailing list