通用类型在不透明类型的帮助下符合Sequence:一些IteratorProtocol

问题描述

protocol TreeNode: AnyObject {
    associatedtype T
    var value: T { get set }
    var children: [Self] { get }
    init(_ value: T)
}

protocol Tree: Sequence {
    associatedtype Node: TreeNode
    var root: Node? { get set }
}

extension Tree {
    typealias T = Node.T
    
    func makeIterator() -> some IteratorProtocol {
        BFSIterator(startFrom: root)
    }
}

这可以编译并且看起来很有希望。
但是随后突然在单元测试行let sum = tree.reduce(0,+)中导致编译错误

无法将类型'(Int)-> Int'的值转换为预期的参数类型 '((Int,(某些IteratorProtocol).Element)抛出-> Int'

为什么编译器无法弄清楚(some IteratorProtocol).Element确实是Int?以及如何帮助呢?

请注意,如果我使用“旧方法”(没有不透明类型): func makeIterator()-> BFSIterator { 一切都能编译并完美运行。

更新:

struct BFSIterator<Node: TreeNode>: IteratorProtocol {
    private var queue: Queue<Node> = []
    
    init(startFrom root: Node?) {
        root.map { queue.push($0) }
    }
    
    mutating func next() -> Node.T? {
        guard let current = queue.pop() else { return nil }
        queue.push(contentsOf: current.children)
        return current.value
    }
}

解决方法

之所以发生这种情况,是因为当前的Swift(5.2)中无法为不透明的返回值指定关联的类型。因此,some IteratorProtocol不足以使编译器确定next()方法应返回哪种值。

语言的这种局限性迫使您在实际使用序列时明确声明迭代器类型。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...