【问题标题】:'Array<Element>' is not convertible to 'Array<Int>''Array<Element>' 不能转换为 'Array<Int>'
【发布时间】: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]) -&gt; AnyIterator&lt;[Int]&gt;
  • 您使用的是哪个版本的 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) 中有一个 implicit self 引用,因为 prefixesInt 是一个实例方法 - 在这种情况下, self 不是 [Int] 类型。这给你带来了两个问题,错误的类型,即使它是正确的类型,你也隐式地绑定了self。如果你定义一个 static prefixesInt 方法,它接受一个 [Int] 并简单地调用其 arg 上的实例版本,将它传递给 encodeTransformDecode,你会走得更远。 (我已经让你的代码在 10.0 中“工作”了,但它会喷出 RUNTIME BUG,所以不会发布!)

标签: swift generics functional-programming lazy-sequences


【解决方案1】:

正如我的评论中所指出的并且您在自己的答案中进行了探索,您代码中的核心问题是您的 prefixesInt 类型不正确。实例方法具有以下形式的类型:

(<object type>) -> (<argument types>) -> <return type>

&lt;object type&gt; 传递的值是函数中绑定到self 的值。所以prefixesInt的类型是:

([Int]) -> () -> AnyIterator<[Int]>

要修复您的代码,您只需更改prefixes2

func prefixes2() -> LazyMapSequence<AnyIterator<[Int]>, [Element]>
{
   return encodeTransformDecode(transform: { $0.prefixesInt() } )
}

类型已更改为包含 AnyIterator&lt;[Int]&gt; 而不是 AnyIterator&lt;[Element]&gt; 并且传递了闭包 { $0.prefixesInt() } 而不仅仅是 prefixesInt(前者将数组作为参数,而编译器传递后者,这是一个简写对于self.prefixesInt,作为具有self 预绑定当前值的闭包——selfArray&lt;Equatable&gt; prefixes2 被调用)。

HTH


要查看与您生成的代码的联系,请考虑:

<value>.method(<args>)

只是以下的简写:

<type of value>.method(<value>)(<args>)

在这种情况下意味着:

$0.prefixesInt()

是以下的简写:

Array<Int>.prefixesInt($0)()

这是您制作的,但在 prefixes() (Array&lt;Int&gt;.prefixesInt) 和 encodeTransformDecode (transform(encode())()) 之间分配。通过使用简写并传递闭包,无需更改 encodeTransformDecode

【讨论】:

  • 感谢 CRD。您的回答确实进一步阐明了我的理解。非常感谢。
【解决方案2】:

在@Carpsen90 和@CRD 的帮助下(感谢两位!),并参考了优秀的书籍“obj Functional Swift”(没有个人联系),我找到了一个解决方案。

实例方法的类型与静态方法不同,如下所示:

extension Int {
  static func doubleStatic(_ x: Int) -> Int { return x * 2 }
  func doubleInstance() -> Int { return self * 2 }
}
print( type(of: Int.doubleStatic) )    // Prints: (Int) -> Int
print( type(of: Int.doubleInstance) )  // Prints: (Int) -> () -> Int

在问题中prefixesInt 的类型实际上是:(Array&lt;Int&gt;) -&gt; () -&gt; AnyIterator&lt;[Int]&gt;
考虑到这一点,我们可以将encodeTransformDecode 重写如下:

extension Array where Element: Equatable {
  func encodeTransformDecode(transform: (Array<Int>) -> () -> AnyIterator<[Int]> ) -> LazyMapSequence<AnyIterator<[Int]>, [Element]> {
    return transform(encode())().lazy.map { $0.decode(self) }
  }
}

其次,当我们在prefixes2 中使用prefixesInt 时,我们需要告诉编译器更多关于prefixesInt 的类型,所以:

extension Array where Element: Equatable {
  func prefixes2() -> LazyMapSequence<AnyIterator<[Int]>, [Element]> {
    return encodeTransformDecode(transform: Array<Int>.prefixesInt)
  }
}

现在根据需要:

for prefix in ["A","B","C"].prefixes2() {
  print(prefix)
}

给我们:

["A"]
["A", "B"]
["A", "B", "C"]

现在我们可以非常简洁地使用其他功能进行扩展:

extension Array where Element == Int {
  func suffixesInt() -> AnyIterator<[Element]> {
    var length = 0
    return AnyIterator {
      guard length < self.count else { return nil }
      length += 1
      return Array(self.suffix(length))
    }
  }
}

extension Array where Element: Equatable {
  func suffixes2() -> LazyMapSequence<AnyIterator<[Int]>, [Element]> {
    return encodeTransformDecode(transform: Array<Int>.suffixesInt)
  }
}

for suffix in ["A","B","C"].suffixes2() {
  print(suffix)
}

【讨论】:

  • 可以说这句话:transform(encode())().lazy.map { $0.decode(self) } 是神秘的,可能会更好:let encoded = encode()let transformFunction = transform(encoded)let transformIterator = transformFunction()let lazyTransformIterator = transformIterator.lazyreturn lazyTransformIterator.map { $0.decode(self) }
猜你喜欢
  • 1970-01-01
  • 2016-06-10
  • 2011-05-20
  • 2015-04-25
  • 2015-01-09
  • 1970-01-01
  • 2016-08-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多