Swift 4. 使用 PAT。允许相互引用的协议吗?我收到一个我不明白的错误
Swift 4. Using PATs. Are protocols which reference each other allowed? I'm getting an error I don't understand
在下面的代码中,我在一个简单的 Graph 项目中设置了顶点和边的协议。顶点引用边,边引用顶点。在 neighbours()
函数中,我在 edges
数组上调用 map()
并收到此错误:
'map' produces '[T]', not the expected contextual result type '[Self.VertexType]'.
import Foundation
protocol EdgeProtocol {
associatedtype VertexType: VertexProtocol
var from : VertexType { get set }
var to : VertexType { get set }
init(from: VertexType, to:VertexType)
}
protocol VertexProtocol {
associatedtype EdgeType: EdgeProtocol
associatedtype VertexType: VertexProtocol
var id: String { get set }
var edges: [EdgeType] { get set }
func neighbours() -> [VertexType]
}
extension VertexProtocol {
func neighbours() -> [VertexType] {
return edges.map { [=11=].to } // 'map' produces '[T]', not the expected
// contextual result type '[Self.VertexType]'
}
}
struct Edge: EdgeProtocol {
typealias VertexType = Vertex // leave out -> no compile error
var from: Vertex
var to: Vertex
init(from: Vertex, to:Vertex) {
self.from = from
self.to = to
}
}
class Vertex: VertexProtocol {
typealias VertexType = Vertex // leave out -> compile error
typealias EdgeType = Edge // leave out -> no compile error
var id: String
var edges = [Edge]()
init(name: String) { id = name }
}
我的代码 "knows" edges
是 [Vertex:VertexProtocol]
类型,但是 map()
将其解释为 [T]。这是因为 Swift 4 不允许协议之间的交叉引用还是其他原因?我必须承认我并不真正理解 PAT(具有关联类型的协议),正如我的评论行所表明的那样。任何指导表示赞赏
问题是虽然edges
符合EdgeProtocol
,并且EdgeProtocol
包含一个VertexType
关联类型,编译器无法知道这将是与 VertexProtocol
's VertexType
associated type. Both protocols' VertexType
相同的类型将符合 VertexProtocol
,但它们不一定是同一类型。因此 edges.map { [=20=].to }
returns [EdgeType.VertexType]
,但是你的函数被声明为 return [Self.VertexType]
,所以它是类型不匹配。
您可以通过明确指定两个 VertexType
相同来解决此问题。您可以在定义中这样做:
protocol VertexProtocol {
associatedtype VertexType
associatedtype EdgeType: EdgeProtocol where EdgeType.VertexType == VertexType
// ...
}
或者,如果这不切实际,您可以限制扩展名:
extension VertexProtocol where EdgeType.VertexType == VertexType {
func neighbours() -> [VertexType] {
return edges.map { [=11=].to }
}
}
这两种方法中的任何一种都应该生成可编译的代码。
在下面的代码中,我在一个简单的 Graph 项目中设置了顶点和边的协议。顶点引用边,边引用顶点。在 neighbours()
函数中,我在 edges
数组上调用 map()
并收到此错误:
'map' produces '[T]', not the expected contextual result type '[Self.VertexType]'.
import Foundation
protocol EdgeProtocol {
associatedtype VertexType: VertexProtocol
var from : VertexType { get set }
var to : VertexType { get set }
init(from: VertexType, to:VertexType)
}
protocol VertexProtocol {
associatedtype EdgeType: EdgeProtocol
associatedtype VertexType: VertexProtocol
var id: String { get set }
var edges: [EdgeType] { get set }
func neighbours() -> [VertexType]
}
extension VertexProtocol {
func neighbours() -> [VertexType] {
return edges.map { [=11=].to } // 'map' produces '[T]', not the expected
// contextual result type '[Self.VertexType]'
}
}
struct Edge: EdgeProtocol {
typealias VertexType = Vertex // leave out -> no compile error
var from: Vertex
var to: Vertex
init(from: Vertex, to:Vertex) {
self.from = from
self.to = to
}
}
class Vertex: VertexProtocol {
typealias VertexType = Vertex // leave out -> compile error
typealias EdgeType = Edge // leave out -> no compile error
var id: String
var edges = [Edge]()
init(name: String) { id = name }
}
我的代码 "knows" edges
是 [Vertex:VertexProtocol]
类型,但是 map()
将其解释为 [T]。这是因为 Swift 4 不允许协议之间的交叉引用还是其他原因?我必须承认我并不真正理解 PAT(具有关联类型的协议),正如我的评论行所表明的那样。任何指导表示赞赏
问题是虽然edges
符合EdgeProtocol
,并且EdgeProtocol
包含一个VertexType
关联类型,编译器无法知道这将是与 VertexProtocol
's VertexType
associated type. Both protocols' VertexType
相同的类型将符合 VertexProtocol
,但它们不一定是同一类型。因此 edges.map { [=20=].to }
returns [EdgeType.VertexType]
,但是你的函数被声明为 return [Self.VertexType]
,所以它是类型不匹配。
您可以通过明确指定两个 VertexType
相同来解决此问题。您可以在定义中这样做:
protocol VertexProtocol {
associatedtype VertexType
associatedtype EdgeType: EdgeProtocol where EdgeType.VertexType == VertexType
// ...
}
或者,如果这不切实际,您可以限制扩展名:
extension VertexProtocol where EdgeType.VertexType == VertexType {
func neighbours() -> [VertexType] {
return edges.map { [=11=].to }
}
}
这两种方法中的任何一种都应该生成可编译的代码。