Skip to content

Instantly share code, notes, and snippets.

@JGiola
Last active January 9, 2016 12:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JGiola/f735212789bf2f697847 to your computer and use it in GitHub Desktop.
Save JGiola/f735212789bf2f697847 to your computer and use it in GitHub Desktop.
Draft for changing the fallthorught keyword in Swift language

Improve Switch Syntax by Removing fallthrough with fallto

Introduction

Since the beginning of the Swift public beta, the switch statement was a safer evolution of the C-style switch, disallowing the implicit fall through behavior between cases, and introducing the fallthrough keyword forcing the developers to explicitly require it.
This proposal wants to improve the switch statement by substituting the fallthrough keyword with a more secure and powerful fallto.

Motivation

In C the switch construct can be applied only to integers or enums, every case must be declared separately and there is no way to specify a where clause for adding additional conditions.
With this landscape the fall through behavior has less impact on the safety of execution of the code inside it, unless if the behavior is for a missing break statement.

In Swift the switch control flow is greatly improved, it can be called against pretty much every type and the various cases can specify a value, a range of values, or more complex matching patterns; it gives even a where clause to check for additional conditions.
Every one of this new features in Swift makes the switch statement more flexible, powerful and safe of the old C-style of which retain the name.

With this in mind the fallthroughkeyword seems an old relic that is here only for easing the translation of C and Obj-C code to Swift.
fallthroughcan lead to subtle bugs that were not possible in C and that for a novice of the language can be seen as odd.

The major complaint against fallthroughis the next excerpt from The Swift Programming Language (Swift 2.1):

NOTE
The fallthrough keyword does not check the case conditions for the switch case that it causes execution to fall into. The fallthrough keyword simply causes code execution to move directly to the statements inside the next case (or default case) block, as in C’s standard switch statement behavior.

As you can read, fallthrough skip the case specified underneath it altogether without checking it, even if it's specifying a where clause. So in a trivial example like this:

let array = [1, 2, 3];
var element = 1;
switch someEnumeration {
case .One:
  // do something
  x = 10
  fallthrough
case .Two where x >= 0 && x < array.count:
  element = array[x];
case .Three:
  // do something else
default:
  break;
}

This code will compile fine but crashes at runtime for someEnumeration = .One.
The developer might even had introduce this bug later on because it has refactored the x control from inside the .Two case to the where.

Another pitfall of fallthrough can be related to wrong refactoring of the code that moves around the cases declaration (maybe for a merge gone wrong) and until runtime the bug can't be spotted without manual review.

Proposed solution

The proposed solution is to change the fallthrough keyword to fallto.
This new keyword will accept an explicit value that must be matched with one of the following cases. The associated where clause of the case will be evaluated and if it fail the code will exit the switch.

let array = [1, 2, 3];
var element = 1;
switch someEnumeration {
case .One:
  // do something
  x = 10
  fallto .Two
case .Two where x >= 0 && x < array.count:
  element = array[x];
case .Three:
  // do something else
default:
  break;
}

In doing so, we can even have a nice flow improvement; we can have two diverse cases fall inside a third one.

let array = [1, 2, 3];
var element = 1;
switch someEnumeration {
case .One:
  // do something
  x = 10
  fallto .Three
case .Two where x >= 0 && x < array.count:
  element = array[x];
  fallto .Three
case .Three:
  // do something else
default:
  break;
}

If the case specified can't be matched against one of the following ones (default is a special case and it can be targeted only specifying default) It will be a compile error.

Detailed design

Impact on existing code

The impact in the existing code will be minimum. An automated translation from fallthrough and the new syntax can be automated for the switch cases with a single defined value in the case next to fallthrough.
For the more complex cases the developer will have to manually change the code.

Alternatives considered

One of the alternative considered for this functionality was a reswitch keyword that will reevaluate the entirety of the switch construct with the new value passed by the developer.

One major flaw of this approach is that can lead to transform the switch control flow in a kind of loop construct and will introduce all the problems associated with it, mainly infinite loop errors.

Improve Switch Syntax by Removing fallthrough with fallto

Introduction

Since the beginning of the Swift public beta, the switch statement was a safer evolution of the C-style switch, disallowing the implicit fall through behavior between cases, and introducing the fallthrough keyword forcing the developers to explicitly require it.
This proposal wants to improve the switch statement by substituting the fallthrough keyword with a more secure and powerful fallto.

Motivation

In C the switch construct can be applied only to integers or enums, every case must be declared separately and there is no way to specify a where clause for adding additional conditions.
With this landscape the fall through behavior has less impact on the safety of execution of the code inside it, unless if the behavior is for a missing break statement.

In Swift the switch control flow is greatly improved, it can be called against pretty much every type and the various cases can specify a value, a range of values, or more complex matching patterns; it gives even a where clause to check for additional conditions.
Every one of this new features in Swift makes the switch statement more flexible, powerful and safe of the old C-style of which retain the name.

With this in mind the fallthroughkeyword seems an old relic that is here only for easing the translation of C and Obj-C code to Swift.
fallthroughcan lead to subtle bugs that were not possible in C and that for a novice of the language can be seen as odd.

The major complaint against fallthroughis the next excerpt from The Swift Programming Language (Swift 2.1):

NOTE
The fallthrough keyword does not check the case conditions for the switch case that it causes execution to fall into. The fallthrough keyword simply causes code execution to move directly to the statements inside the next case (or default case) block, as in C’s standard switch statement behavior.

As you can read, fallthrough skip the case specified underneath it altogether without checking it, even if it's specifying a where clause. So in a trivial example like this:

let array = [1, 2, 3];
var element = 1;
switch someEnumeration {
case .One:
  // do something
  x = 10
  fallthrough
case .Two where x >= 0 && x < array.count:
  element = array[x];
case .Three:
  // do something else
default:
  break;
}

This code will compile fine but crashes at runtime for someEnumeration = .One.
The developer might even had introduce this bug later on because it has refactored the x control from inside the .Two case to the where.

Another pitfall of fallthrough can be related to wrong refactoring of the code that moves around the cases declaration (maybe for a merge gone wrong) and until runtime the bug can't be spotted without manual review.

Proposed solution

The proposed solution is to change the fallthrough keyword to fallto.
This new keyword will accept an explicit value that must be matched with one of the following cases. The associated where clause of the case will be evaluated and if it fail the code will exit the switch.

let array = [1, 2, 3];
var element = 1;
switch someEnumeration {
case .One:
  // do something
  x = 10
  fallto .Two
case .Two where x >= 0 && x < array.count:
  element = array[x];
case .Three:
  // do something else
default:
  break;
}

In doing so, we can even have a nice flow improvement; we can have two diverse cases fall inside a third one.

let array = [1, 2, 3];
var element = 1;
switch someEnumeration {
case .One:
  // do something
  x = 10
  fallto .Three
case .Two where x >= 0 && x < array.count:
  element = array[x];
  fallto .Three
case .Three:
  // do something else
default:
  break;
}

If the case specified can't be matched against one of the following ones (default is a special case and it can be targeted only specifying default) It will be a compile error.

Detailed design

Impact on existing code

The impact in the existing code will be minimum. An automated translation from fallthrough and the new syntax can be automated for the switch cases with a single defined value in the case next to fallthrough.
For the more complex cases the developer will have to manually change the code.

Alternatives considered

One of the alternative considered for this functionality was a reswitch keyword that will reevaluate the entirety of the switch construct with the new value passed by the developer.

One major flaw of this approach is that can lead to transform the switch control flow in a kind of loop construct and will introduce all the problems associated with it, mainly infinite loop errors.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment