我想用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数组
答案 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
的类型String
和3
ConstArray<String, Succ<SuccSucc<<Zero>>>>
好的,
[1, 2].lazy.filter {$0 == 1 }.flatMap{ [$0] }
之类的内容有LazyCollection<FlattenCollection<LazyMapCollection<LazyFilterCollection<Array<Int>>, [Int]>>>
,所以我猜ConstArray
并不太糟糕:P