【发布时间】:2018-05-17 05:11:37
【问题描述】:
swift --version
Swift version 4.1 (swift-4.1-RELEASE)
Target: x86_64-unknown-linux-gnu
给定一个定义通用生产者的简单协议(来源):
protocol Source {
associatedtype T
func produce() -> T
}
以及能够在源类型之间转换的映射:
struct Mapping<T, U : Source> : Source {
typealias Transformation = (U.T) -> T
private let upstream : U
private let block : Transformation
init(_ upstream: U, _ block : @escaping Transformation) {
self.upstream = upstream
self.block = block
}
func produce() -> T {
return block(upstream.produce())
}
}
还有一个生成静态文本的示例源:
struct TextSource : Source {
private let text : String
init(_ text: String) {
self.text = text
}
func produce() -> String {
return text
}
}
我可以用它来计算字符数……
let t = TextSource("Hi!")
let f = Mapping(t, { (text: String) -> Int in
return text.count
})
print(f.produce()) // output: 3
但我更愿意在 Source 上使用通用的 map 扩展函数,以便可以链接转换,例如:
let t = TextSource("Hi!").map { (text: String) -> Int in
return text.count
}
方法 A
extension Source {
func map<T, U : Source>(_ block: @escaping Mapping<T, U>.Transformation) -> Source {
return Mapping(self, block)
}
}
这被 swift 编译器拒绝:
error: generic parameter 'U' is not used in function signature
func map<T, U : Source>(_ block: @escaping Mapping<T, U>.Transformation) -> Source {
^
方法 B
extension Source {
func map<T>(_ block: @escaping Mapping<T, U>.Transformation) -> Source {
return Mapping(self, block)
}
}
在这种情况下,编译器会抱怨缺少类型参数:
error: use of undeclared type 'U'
func map<T>(_ block: @escaping Mapping<T, U>.Transformation) -> Source {
^
问题
需要在map扩展函数上指定哪些类型参数和约束才能满足编译器要求?
【问题讨论】: