I tried to find out why the following code is ambiguous ...
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 }
... when I call it two lazy sequences and call makeIterator EXAMPLE .
_ = product([1, 2].lazy, [3, 4].lazy).makeIterator()
However, the following code does not have this ambiguity ...
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) }
... when I call it two lazy sequences and call makeIterator EXAMPLE .
_ = product([1, 2].lazy, [3, 4].lazy).makeIterator()
My reasoning is that a lazy sequence matches both LazySequenceProtocol and Sequence , so the type system does not know which product to choose. But by this definition, the second version should not work either.
I am using Swift 4.0.
What does the second version of the work do?