Swift - 在编译时创建一个固定长度的数组

时间:2015-05-04 16:34:57

标签: ios swift tuples compile-time

我想用5个特定类型的元素强制执行(编译时)数组

我找不到解决方案,因此通过创建元组

来采用解决方法

(我知道这是滥用)

typealias FiveElementArray = (MyType,MyType,MyType,MyType,MyType) // mock array by using typed tuple

它适用于我的需求 - 直到我需要在运行时通过索引访问元素。

例如:

var DB = FiveElementArray // the tuple of 5 elements

tableView(tableView : UITableView,cellForRowAtIndexPath:indexPath) -> UITableViewCell {
// would like to populate with the value at index
DB[indexpath.row] // no such syntax for tuples

}

那么如何使用具有静态类型长度的正确swift数组

2 个答案:

答案 0 :(得分:7)

防止对值类型(例如数组)进行不必要更改的方法是在其上放置didSet观察者以充当警卫:

var arr = [1, 2, 3, 4, 5] {
    didSet {
        if arr.count > 5 {arr = oldValue}
    }
}
arr.append(6)
println(arr) // [1, 2, 3, 4, 5], that change was illegal
arr[2] = 100
println(arr) // [1, 2, 100, 4, 5], that change was legal

但如果这还不够好,你需要使用一个包装器,即有一个数组而不是一个数组:

struct FiveElementArray<T> {
    private var arr = Array<T>()
    // methods for access go here
}

“访问方法”可以包括修改您允许的所有数组的所有方法的实现(例如,下标),并且可以简单地不实现您不允许的所有方式(例如追加和扩展)。 / p>

如果你坚持编译时检查,那么只需坚持你的元组,甚至编写你自己的集合。但在那一点上,我认为你只是对你的要求愚蠢。 struct wrapper可以防止不必要的更改;因此它是一种保证,所以不需要在编译时做出保证。

答案 1 :(得分:1)

您可能正在寻找Dependent Types:它使您能够将某个值(数组长度)编码到类型本身中。幸运的是,可以在Swift to some extent中使用依赖类型。

@oisdk还写了a blog post,他创建了一个高效依赖类型的集合结构,您还可以在与the Playground version中的代码交互时阅读该文章。

使用示例:

func onlySameLength<A, B, L : Nat>(lhs: ConstArray<A, L>, rhs: ConstArray<B, L>) {}

let twoLong = emptyArray() +| 1 +| 2         // [1, 2]

let twoChar = emptyArray() +| "a" +| "b"     // ["a", "b"]

onlySameLength(twoLong, rhs: twoChar)

let threeInts = emptyArray() +| 1 +| 2 +| 3  // [1, 2, 3]

//Uncomment for an error
//onlySameLength(twoLong, rhs: threeInts)

我强烈建议您使用Swift的类型推断作为ConstArray的类型String3 ConstArray<String, Succ<SuccSucc<<Zero>>>>

  

好的,[1, 2].lazy.filter {$0 == 1 }.flatMap{ [$0] }之类的内容有LazyCollection<FlattenCollection<LazyMapCollection<LazyFilterCollection<Array<Int>>, [Int]>>>,所以我猜ConstArray并不太糟糕:P