Skip to content

Instantly share code, notes, and snippets.

@erica
Last active July 7, 2020 17:07
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 erica/c8e540ea2f4987d00799fde9fa0f3f96 to your computer and use it in GitHub Desktop.
Save erica/c8e540ea2f4987d00799fde9fa0f3f96 to your computer and use it in GitHub Desktop.
Olivier: I think that's one of the rare cases where fallthough is acceptable
import XCTest
class Tester: XCTestCase {
func testit() {
XCTAssertEqual("a", switchTheFallthroughOrder(foo: .a))
XCTAssertEqual("b", switchTheFallthroughOrder(foo: .b("x")))
XCTAssertEqual("c", switchTheFallthroughOrder(foo: .b("cx")))
XCTAssertEqual("c", switchTheFallthroughOrder(foo: .c))
}
}
Tester.defaultTestSuite.run()
// Goal
func Goal() -> String {
switch foo {
case .a: return "a"
// Error: str must be bound in every pattern
case .b(let str) where str.hasPrefix("c"), .c: return "c"
case .b: return "b"
}
}
// Fallthrough doesn't work
func test1() -> String {
switch foo {
case .a: return "a"
// Error: fallthrough from a case which doesn't bind variable 'str'
case .c: fallthrough
case .b(let str) where str.hasPrefix("c"): return "c"
case .b: return "b"
}
}
func obviousWayButNotDesired() -> String {
switch foo {
case .a: return "a"
case .c: return "c"
case .b(let str) where str.hasPrefix("c"): return "c"
case .b: return "b"
}
}
// By default, the ~= operator compares two values of the same type using the == operator.
func test2() -> String {
switch foo {
case .a: return "a"
// Error: Operator function ~= requires that Foo conform to Equatable
case _ where foo ~= .c : return "c"
case .b(let str) where str.hasPrefix("c"): return "c"
case .b: return "b"
}
}
/*
error: macOS.playground:23:26: error: expected expression for 'where' guard of 'case'
case .c(let _) where let str = "c": fallthrough
^
error: macOS.playground:23:26: error: expected ':' after 'case'
case .c(let _) where let str = "c": fallthrough
^
error: macOS.playground:23:39: error: consecutive statements on a line must be separated by ';'
case .c(let _) where let str = "c": fallthrough
^
;
error: macOS.playground:23:39: error: expected expression
case .c(let _) where let str = "c": fallthrough
^
*/
func test3() -> String {
switch foo {
case .a: return "a"
case .c(let _) where let str = "c": fallthrough
case.b(let str) where str.hasPrefix("c"): return "c"
case .b: return "b"
}
}
// Also a non-winner although it works:
func alsoNotDesired() -> String {
switch foo {
case .a: return "a"
case .b(let str) where !str.hasPrefix("c"): return "b"
default: return "c"
}
}
// Greg Titus: You can fallthrough into scopes with FEWER variables defined, so this order works:
case .b(let str) where str.hasPrefix("c"):
fallthrough
case .c: return "c"
// Suyash Srijan 10:52 AM
// I think the best you can do is something like this:
switch foo {
case .a: return "a"
case .b:
guard case let .b(str) = foo, str.hasPrefix("c") else {
return "b"
}
fallthrough
case .c: return "c"
}
@erica
Copy link
Author

erica commented Jul 7, 2020

@greg’s solution has the advantage of the greatest readability and elegance

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