我正在寻找类似的东西:
switch array {
case []:
print("No elements")
case let [x]:
print(x)
case let [a, b]:
print(a)
print(b)
default:
print("More than 2 elements")
}
有没有办法在Swift中实现这一目标?
答案 0 :(得分:0)
你可以这样写,但如果你有多个元素,它会很快变得笨拙:
switch array.count
{
case 0 : print("No elements")
case 1 : let x = array[0]
print(x)
case 2 : let (a,b) = (array[0],array[1])
print(a)
print(b)
default: print("More than 2 elements")
}
答案 1 :(得分:0)
我写了一些最愚蠢的代码来实现这样的目标。
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
) 内或初始化变量,并且没有强制执行默认值。
请不要在实际项目中使用它。或者,我只是一个上网的人,你不必听我的。