LazySequenceProtocol示例不起作用

时间:2016-12-29 06:54:43

标签: swift

我正在尝试了解如何实现符合LazySequenceProtocol的扩展。

所以我按照Apple's API reference中的示例代码进行了以下操作:

struct LazyScanIterator<Base : IteratorProtocol, ResultElement>
: IteratorProtocol {
    mutating func next() -> ResultElement? {
        return nextElement.map { result in
            nextElement = base.next().map { nextPartialResult(result, $0) }
            return result
        }
    }
    private var nextElement: ResultElement? // The next result of next().
    private var base: Base                  // The underlying iterator.
    private let nextPartialResult: (ResultElement, Base.Element) -> ResultElement
}

struct LazyScanSequence<Base: Sequence, ResultElement>
    : LazySequenceProtocol // Chained operations on self are lazy, too
{
    func makeIterator() -> LazyScanIterator<Base.Iterator, ResultElement> {
        return LazyScanIterator(nextElement: initial, base: base.makeIterator(), nextPartialResult)
    }

    private let base: Base
    private let initial: ResultElement
    private let nextPartialResult: (ResultElement, Base.Iterator.Element) -> ResultElement
}

extension LazySequenceProtocol {
    func scan<ResultElement>(
        _ initial: ResultElement,
        _ nextPartialResult: (ResultElement, Iterator.Element) -> ResultElement
        ) -> LazyScanSequence<Self, ResultElement> {
        return LazyScanSequence(
            initial: initial, base: self, nextPartialResult)
    }
}

但是XCode说,

  

无法将“ResultElement”类型的值转换为预期的参数类型“_?”

return LazyScanIterator(nextElement: initial, base: base.makeIterator(), nextPartialResult)行。

我想让错误消失,但没有任何效果,所以我刚删除了mutating func next()结构中LazyScanIterator部分的所有代码,只返回base.next()并更改了nextElement的类型{1}} ResultElement代替ResultElement?

嗯,错误消失但现在我在同一行有一个新的。

  

无法转换类型的值'(ResultElement,Base.Iterator.Element) - &gt; ResultElement'到期望的参数类型'(_,_) - &gt; _'

此示例代码有什么问题?

1 个答案:

答案 0 :(得分:1)

我猜问题是构造函数不存在。

这在我的操场上很好用(用Swift 3编写)

import Foundation

struct LazyScanIterator<Base : IteratorProtocol, ResultElement>
: IteratorProtocol {
    private var nextElement: ResultElement? // The next result of next().
    private var base: Base                  // The underlying iterator.
    private let nextPartialResult: (ResultElement, Base.Element) -> ResultElement

    mutating func next() -> ResultElement? {
        return nextElement.map { result in
            nextElement = base.next().map { nextPartialResult(result, $0) }
            return result
        }
    }

    init(nextElement: ResultElement, base: Base, nextPartialResult: @escaping (ResultElement, Base.Element) -> ResultElement) {
        self.nextElement = nextElement
        self.base = base
        self.nextPartialResult = nextPartialResult
    }
}

struct LazyScanSequence<Base: Sequence, ResultElement>
    : LazySequenceProtocol // Chained operations on self are lazy, too
{
    private let base: Base
    private let initial: ResultElement
    private let nextPartialResult: (ResultElement, Base.Iterator.Element) -> ResultElement

    func makeIterator() -> LazyScanIterator<Base.Iterator, ResultElement> {
        return LazyScanIterator(nextElement: initial, base: base.makeIterator(), nextPartialResult: nextPartialResult)
    }

    init(initial: ResultElement, base: Base, nextPartialResult: @escaping (ResultElement, Base.Iterator.Element) -> ResultElement) {
        self.initial = initial
        self.base = base
        self.nextPartialResult = nextPartialResult
    }
}

extension LazySequenceProtocol {
    func scan<ResultElement>(
        _ initial: ResultElement,
        _ nextPartialResult: @escaping (ResultElement, Iterator.Element) -> ResultElement
        ) -> LazyScanSequence<Self, ResultElement> {
        return LazyScanSequence(
            initial: initial, base: self, nextPartialResult: nextPartialResult)
    }
}

Array((1..<6).lazy.scan(0, +)) // will result : [0, 1, 3, 6, 10, 15]