【发布时间】:2018-11-16 09:56:21
【问题描述】:
我可以创建一个迭代器来创建前缀:
extension Array where Element == Int {
func prefixesInt() -> AnyIterator<[Element]> {
var length = 0
return AnyIterator {
guard length < self.count else { return nil }
length += 1
return Array(self.prefix(length))
}
}
}
for prefix in [1,10,5].prefixesInt() {
print(prefix) // Prints: [1] then [1, 10] then [1, 10, 5]
}
现在我想通过以下方式实现与其他类型相同的效果:
1) 将类型编码为 Ints
2) 使用相同的前缀函数
3) 解码回原来的类型
[我知道可能有其他方法可以实现这一点,但出于各种原因,我想遵循这条路线,也想了解更多。]
所以我需要:
extension Array where Element: Equatable {
func encode() -> [Int] {
return map { self.firstIndex(of: $0)! }
}
}
print(["A", "B", "A", "C"].encode()) // Prints: [0, 1, 0, 3]
extension Array where Element == Int {
func decode<Output>(_ original: [Output]) -> [Output] {
return map { original[$0] }
}
}
print([2,3,0].decode(["P", "Q", "R", "S"])) // Prints: ["R", "S", "P"]
我现在可以做我想做的事了:
extension Array where Element: Equatable {
func prefixes() -> LazyMapSequence<AnyIterator<[Int]>, [Element]> {
return encode().prefixesInt().lazy.map { $0.decode(self) }
}
}
for prefix in ["H","A","T"].prefixes() {
print(prefix)
}
我现在想更进一步,将转换(在本例中为前缀)转换为参数,我的尝试是:
extension Array where Element: Equatable {
func encodeTransformDecode(transform: ([Int]) -> AnyIterator<[Int]> ) -> LazyMapSequence<AnyIterator<[Int]>, [Element]> {
return transform(encode()).lazy.map { $0.decode(self) }
}
}
编译得很好,但是当我尝试时:
extension Array where Element: Equatable {
func prefixes2() -> LazyMapSequence<AnyIterator<[Element]>, [Element]> {
return encodeTransformDecode(transform: prefixesInt) //ERROR: 'Array<Element>' is not convertible to 'Array<Int>'
}
}
for prefix in ["A","B","C"].prefixes2() {
print(prefix)
}
然后我得到指示的错误
我被困住了。任何帮助表示赞赏。
完整代码:
print("========== prefixesInt")
extension Array where Element == Int {
func prefixesInt() -> AnyIterator<[Element]> {
var length = 0
return AnyIterator {
guard length < self.count else { return nil }
length += 1
return Array(self.prefix(length))
}
}
}
for prefix in [1,10,5].prefixesInt() {
print(prefix) // Prints: [1] then [1, 10] then [1, 10, 5]
}
print("============ encode")
extension Array where Element: Equatable {
func encode() -> [Int] {
return map { self.firstIndex(of: $0)! }
}
}
print(["A", "B", "A", "C"].encode()) // Prints: [0, 1, 0, 3]
print("============ decode")
extension Array where Element == Int {
func decode<Output>(_ original: [Output]) -> [Output] {
return map { original[$0] }
}
}
print([2,3,0].decode(["P", "Q", "R", "S"])) // Prints: ["R", "S", "P"]
print("============ prefixes")
extension Array where Element: Equatable {
func prefixes() -> LazyMapSequence<AnyIterator<[Int]>, [Element]> {
return encode().prefixesInt().lazy.map { $0.decode(self) }
}
}
for prefix in ["H","A","T"].prefixes() {
print(prefix)
}
extension Array where Element: Equatable {
func encodeTransformDecode(transform: ([Int]) -> AnyIterator<[Int]> ) -> LazyMapSequence<AnyIterator<[Int]>, [Element]> {
return transform(encode()).lazy.map { $0.decode(self) }
}
}
print("============ prefixes2")
extension Array where Element: Equatable {
func prefixes2() -> LazyMapSequence<AnyIterator<[Element]>, [Element]> {
return encodeTransformDecode(transform: prefixesInt)
}
}
for prefix in ["A","B","C"].prefixes2() {
print(prefix)
}
【问题讨论】:
-
prefixesInt仅在Array where Element == Int上定义,而不是一般数组 -
但 encodeTransformDecode 的签名要求转换的类型为:([Int]) -> AnyIterator 所以对消息不清楚?
-
您不能从数组中调用
prefixesInt,其中对元素的唯一约束是相等的。加上prefixesInt的签名不是([Int]) -> AnyIterator<[Int]> -
您使用的是哪个版本的 Xcode/Swift?在 Xcode 10.0/Swift 4.2 Playground 中最后注释掉你的错误并运行会产生预期的输出加上
SWIFT RUNTIME BUG: unable to demangle type of field '_transform'. mangled type name is 'q_7ElementSTQzc' -
我认为您缺少的一件事是,在
encodeTransformDecode(transform: prefixesInt)中有一个 implicitself引用,因为prefixesInt是一个实例方法 - 在这种情况下,self不是[Int]类型。这给你带来了两个问题,错误的类型,即使它是正确的类型,你也隐式地绑定了self。如果你定义一个staticprefixesInt方法,它接受一个[Int]并简单地调用其 arg 上的实例版本,将它传递给encodeTransformDecode,你会走得更远。 (我已经让你的代码在 10.0 中“工作”了,但它会喷出 RUNTIME BUG,所以不会发布!)
标签: swift generics functional-programming lazy-sequences