为了实现这样的目标,我编写了一些最愚蠢的代码。
for a in [ [], [0], [0,1], [0,1,2], [0,1,2,3,4], [0,1,2,3,4,5,6] ] {
Switch(a) {
Case { x in
print("Singleton: \(x)")
}
Case { (x, y) in
print("Pair: \(x), \(y)")
}
Case { (x, y, z) in
print("Triple: \(x), \(y), \(z)")
}
Case(a.count == 4 || a.count == 5) {
print("I didn't feel like splitting these up: \(a)")
}
Case(a.count >= 6) { () -> ControlFlow in // Type checker is too slow to leave the type out
print("It's a big one: \(a)")
return .fallthrough
}
Default {
print("This falls out of range of the special overloads: \(a)")
}
}
}
// Implementation below
func Switch<T>(_ v: T, @SwitchBuilder<T> _ cases: () -> [Case<T>]) {
var fallingThrough = false
for c in cases() {
if fallingThrough || c.match(v) {
switch c.run(v) {
case .break:
return
case .fallthrough:
fallingThrough = true
}
}
}
}
@resultBuilder
enum SwitchBuilder<T> {
static func buildExpression(_ d: Default<T>) -> Case<T> {
Case(d)
}
static func buildExpression(_ c: Case<T>) -> Case<T> {
c
}
static func buildBlock(_ cs: Case<T>...) -> [Case<T>] {
cs
}
}
enum ControlFlow {
case `break`
// Be careful with this one, it's probably a bad idea.
case `fallthrough`
}
struct Case<T> {
var match: (T) -> Bool
var run: (T) -> ControlFlow
init(_ condition: @autoclosure @escaping () -> Bool, f: @escaping () -> ControlFlow) {
self.match = { _ in condition() }
self.run = { _ in f() }
}
init(_ condition: @autoclosure @escaping () -> Bool, f: @escaping () -> ()) {
self.match = { _ in condition() }
self.run = { _ in f(); return .break }
}
init<E>(_ f: @escaping (E) -> ControlFlow) where T == [E] {
self.match = { $0.count == 1 }
self.run = { f($0[0]) }
}
init<E>(_ f: @escaping (E) -> ()) where T == [E] {
self.match = { $0.count == 1 }
self.run = { f($0[0]); return .break }
}
init<E>(_ f: @escaping (E,E) -> ControlFlow) where T == [E] {
self.match = { $0.count == 2 }
self.run = { f($0[0], $0[1]) }
}
init<E>(_ f: @escaping (E,E) -> ()) where T == [E] {
self.match = { $0.count == 2 }
self.run = { f($0[0], $0[1]); return .break }
}
init<E>(_ f: @escaping (E,E,E) -> ControlFlow) where T == [E] {
self.match = { $0.count == 3 }
self.run = { f($0[0], $0[1], $0[2]) }
}
init<E>(_ f: @escaping (E,E,E) -> ()) where T == [E] {
self.match = { $0.count == 3 }
self.run = { f($0[0], $0[1], $0[2]); return .break }
}
init<E>(_ f: @escaping (E,E,E,E) -> ControlFlow) where T == [E] {
self.match = { $0.count == 4 }
self.run = { f($0[0], $0[1], $0[2], $0[3]) }
}
init<E>(_ f: @escaping (E,E,E,E) -> ()) where T == [E] {
self.match = { $0.count == 4 }
self.run = { f($0[0], $0[1], $0[2], $0[3]); return .break }
}
init<E>(_ f: @escaping (E,E,E,E,E) -> ControlFlow) where T == [E] {
self.match = { $0.count == 5 }
self.run = { f($0[0], $0[1], $0[2], $0[3], $0[4]) }
}
init<E>(_ f: @escaping (E,E,E,E,E) -> ()) where T == [E] {
self.match = { $0.count == 5 }
self.run = { f($0[0], $0[1], $0[2], $0[3], $0[4]); return .break }
}
init(_ d: Default<T>) {
self.match = { _ in true }
self.run = d.run
}
}
struct Default<T> {
var run: (T) -> ControlFlow
init(_ f: @escaping () -> ControlFlow) {
self.run = { _ in f() }
}
init(_ f: @escaping () -> ()) {
self.run = { _ in f(); return .break }
}
}
如您所料,这是打印出来的
This falls out of range of the special overloads: []
Singleton: 0
Pair: 0, 1
Triple: 0, 1, 2
I didn't feel like splitting these up: [0, 1, 2, 3, 4]
It's a big one: [0, 1, 2, 3, 4, 5, 6]
This falls out of range of the special overloads: [0, 1, 2, 3, 4, 5, 6]
这个实现只允许你解构长度为 5 的数组,但是通过向 Case 添加额外的初始化器来添加更多的情况是微不足道的。
除了如何使用它之外,Swift 不知道这意味着什么,因此您将无法使用它从您的函数中返回(return 内 Case 就像 break 内普通 case ) 或初始化变量,并且没有强制执行默认值。
请不要在实际项目中使用它。或者,我只是一个在互联网上的人,你不必听我的。