I made a bunch of functions and an enumeration, that together allow me to write something like a switch expression. It's not as powerful as Swift switch statements, since it's lacking pattern matching and I don't intend to use this in real code, it was just an experiment. Here is what I got:
enum Caze<T: ForwardIndexType where T: Equatable> {
case RangeCaze(Range<T>)
case ArrayCaze([T])
func contains(elem: T) -> Bool {
switch self {
case let .RangeCaze(r):
return r.contains(elem)
case let .ArrayCaze(arr):
return arr.contains(elem)
}
}
}
func caze<T: ForwardIndexType, R where T: Equatable>(vals: T..., @autoclosure(escaping) ret f: () -> R) -> (Caze<T>, () -> R) {
return (.ArrayCaze(vals), f)
}
func caze<T: ForwardIndexType, R where T: Equatable>(vals: Range<T>, @autoclosure(escaping) ret f: () -> R) -> (Caze<T>, () -> R) {
return (.RangeCaze(vals), f)
}
func caze<T: Equatable, R>(vals: T..., @autoclosure(escaping) ret f: () throws -> R) -> ([T], () throws -> R) {
return (vals, f)
}
func schwitch<T: ForwardIndexType, R where T: Equatable>(value: T, _ cases: (Caze<T>, () -> R)..., @autoclosure def: () throws -> R) rethrows -> R {
for (vals, f) in cases {
if vals.contains(value) {
return f()
}
}
return try def()
}
func schwitch<T: Equatable, R>(value: T, _ cases: ([T], () -> R)..., @autoclosure def: () throws -> R) rethrows -> R {
for (vals, f) in cases {
if vals.contains(value) {
return f()
}
}
return try def()
}
This allows me to write code like:
schwitch(5, // results in "lol"
caze(0, ret: "hello"),
caze(1, 2, ret: "test"),
caze(3..<7, ret: "lol"),
def: "nop")
schwitch("helloo", //results in "nop"
caze("hello", "Hello", ret: "test"),
def: "nop")
I think there are a few problems with this though.
- There is quite a bit of code duplication due to a few nearly identical functions being needed.
- The closure sent to the
caze
functions are escaping, though they are intended to never actually escape beyond a very defined scope. - If code in a
caze
function throws, it doesn't get rethrown. I also considered an alternative implementation for the
schwitch
functions but am worried that it takes brevity a bit too far:(cases.filter{$0.contains(value)}.first ?? def)()
Are there any ways to improve on these 4 points and are there any other things that I missed or could have done better?