泛型类型在不透明类型的帮助下符合序列:一些 IteratorProtocol

Posted

技术标签:

【中文标题】泛型类型在不透明类型的帮助下符合序列:一些 IteratorProtocol【英文标题】:Generic type conforms to Sequence with help of opaque type: some IteratorProtocol 【发布时间】:2021-02-18 05:45:20 【问题描述】:
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, (some IteratorProtocol).Element) throws -> 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
    

【问题讨论】:

什么是BFSIterator @NewDev struct BFSIterator: IteratorProtocol mutating func next() -> Node.T? 请补充问题...似乎是相关部分 【参考方案1】:

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

如果您想实际使用序列,语言的这种限制会强制您显式声明迭代器类型。

【讨论】:

以上是关于泛型类型在不透明类型的帮助下符合序列:一些 IteratorProtocol的主要内容,如果未能解决你的问题,请参考以下文章

如何在不知道项目泛型类型参数的情况下对作为泛型给出的列表进行浅表复制? [复制]

我如何在不使用Delphi约束的情况下确定泛型类型为nil?

c# 在不知道类型的情况下,如何判断并使用带泛型的扩展方法?

如何在不使用 foreach 的情况下将 ArrayList 转换为强类型泛型列表?

1-25泛型

我们如何在不使用泛型类型进行自定义的情况下处理身份核心用户管理和用户存储的多个用户使用情况?