模糊使用函数(Swift 4)

Den*_*ink 9 functional-programming overloading swift swift4

我一直试图弄清楚为什么以下代码含糊不清......

public func product <T1: Sequence, T2: Sequence> (_ sequence1: T1, _ sequence2: T2) ->
    AnySequence<(T1.Element, T2.Element)> {
  return AnySequence(
    sequence1.flatMap { element1 in
      sequence2.map { element2 in
        (element1, element2)
      }
    }
  )
}

public func product <T1: LazySequenceProtocol, T2: LazySequenceProtocol> (_ sequence1: T1, _ sequence2: T2) ->
    LazySequence<AnySequence<(T1.Element, T2.Element)>> {
  return AnySequence(
    sequence1.flatMap { element1 in
      sequence2.map { element2 in
        (element1, element2)
      }
    }
  ).lazy
}
Run Code Online (Sandbox Code Playgroud)

...当我用两个惰性序列调用它并调用makeIteratorEXAMPLE时.

_ = product([1, 2].lazy, [3, 4].lazy).makeIterator()
Run Code Online (Sandbox Code Playgroud)

然而,以下代码没有这种模糊性......

public struct Product2Sequence <T1: Sequence, T2: Sequence>: Sequence {
  public typealias Element = (T1.Element, T2.Element)
  public typealias Iterator = AnyIterator<Element>

  private let iterator: Iterator

  internal init (_ sequence1: T1, _ sequence2: T2) {
    self.iterator = AnyIterator(
      sequence1.flatMap { element1 in
        sequence2.map { element2 in
          (element1, element2)
        }
      }.makeIterator()
    )
  }

  public func makeIterator () -> Iterator {
    return self.iterator
  }
}

public struct LazyProduct2Sequence <T1: LazySequenceProtocol, T2: LazySequenceProtocol>: LazySequenceProtocol {
  public typealias Element = (T1.Element, T2.Element)
  public typealias Iterator = AnyIterator<Element>

  private let iterator: Iterator

  internal init (_ sequence1: T1, _ sequence2: T2) {
    self.iterator = AnyIterator(
      sequence1.flatMap { element1 in
        sequence2.map { element2 in
          (element1, element2)
        }
      }.makeIterator()
    )
  }

  public func makeIterator () -> Iterator {
    return self.iterator
  }
}

public func product <T1: Sequence, T2: Sequence> (_ sequence1: T1, _ sequence2: T2) -> Product2Sequence<T1, T2> {
  return Product2Sequence(sequence1, sequence2)
}

public func product <T1: LazySequenceProtocol, T2: LazySequenceProtocol> (_ sequence1: T1, _ sequence2: T2) ->
    LazyProduct2Sequence<T1, T2> {
  return LazyProduct2Sequence(sequence1, sequence2)
}
Run Code Online (Sandbox Code Playgroud)

...当我用两个惰性序列调用它并调用makeIteratorEXAMPLE时.

_ = product([1, 2].lazy, [3, 4].lazy).makeIterator()
Run Code Online (Sandbox Code Playgroud)

我的理由是懒惰序列符合两者LazySequenceProtocol,Sequence因此类型系统不知道product选择哪个.但按照这个定义,第二个版本也应该不起作用.

我正在使用Swift 4.0.

是什么让第二个版本起作用?

Alv*_*vae 3

这是一个已在 4.1 中解决的错误(请参阅https://bugs.swift.org/browse/SR-4509)。类型求解器过去无法在Sequence和之间进行选择LazySequenceProtocol,因为前者显然符合后者。

我不能肯定地说为什么你的第二个版本确实适用于 4.0 并且没有证据支持我的假设,但我猜这与类型求解器能够从更具体的返回类型获取更多信息有关。

无论如何,LazySequenceProtocol现在是首选,以便尽可能长时间地保持懒惰。您的代码在 Swift 4.1 中按预期工作。