通用协议上的Swift 4扩展函数,以通用函数为参数
给定一个定义通用生产者(源)的简单协议: 以及能够在源类型之间转换的映射:通用协议上的Swift 4扩展函数,以通用函数为参数,swift,generics,Swift,Generics,给定一个定义通用生产者(源)的简单协议: 以及能够在源类型之间转换的映射: protocol Source { associatedtype T func produce() -> T } 我可以用它来,例如,计数字符 struct TextSource : Source { private let text : String init(_ text: String) { self.text = text } func
protocol Source {
associatedtype T
func produce() -> T
}
我可以用它来,例如,计数字符
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
接近A
let t = TextSource("Hi!").map { (text: String) -> Int in
return text.count
}
扩展源{
func映射(ublock:@escaping Mapping.Transformation)->Source{
返回映射(self,block)
}
}
被swift编译器拒绝的:
extension Source {
func map<T, U : Source>(_ block: @escaping Mapping<T, U>.Transformation) -> Source {
return Mapping(self, block)
}
}
错误:函数签名中未使用泛型参数“U”
func映射(ublock:@escaping Mapping.Transformation)->Source{
^
方法B
error: generic parameter 'U' is not used in function signature
func map<T, U : Source>(_ block: @escaping Mapping<T, U>.Transformation) -> Source {
^
扩展源{
func映射(ublock:@escaping Mapping.Transformation)->Source{
返回映射(self,block)
}
}
在这种情况下,编译器会抱怨缺少类型参数:
extension Source {
func map<T>(_ block: @escaping Mapping<T, U>.Transformation) -> Source {
return Mapping(self, block)
}
}
错误:使用未声明的类型“U”
func映射(ublock:@escaping Mapping.Transformation)->Source{
^
问题
为了满足编译器的要求,需要在
map
扩展函数上指定哪些类型参数和约束?您不能将Source
用作map
的具体返回类型,因为它是一个具有相关类型要求的协议
要解决此问题,可以使用映射
函数返回映射
:
扩展源{
func映射(u变换:@转义(T)->结果)->映射{
返回映射(自映射、转换)
}
}
该函数现在有一个
Self
需求。生成的Mapping
类型有一个泛型类型参数Self
,它被Source
的具体实现所取代,例如Mapping
或TextSource,非常感谢。这正是我在Swift 5.1中寻找的可以指定不透明的结果类型(即,->某些源代码而不是->映射
。您介意更新/扩展您的答案吗?请注意,不透明的返回类型有一些限制。如果您有某些源代码
,您将丢失关联类型T
的类型信息,因此您无法真正使用它。TextSource(“嗨!”)例如.map{$0.count}.map{$0+42}
将不再编译,因为在第二个闭包中,不再可能知道T
指的是什么。因此我认为某些源代码
在这里不是一个好的解决方案。当Swift得到广义存在论时,可能会这样做。
error: generic parameter 'U' is not used in function signature
func map<T, U : Source>(_ block: @escaping Mapping<T, U>.Transformation) -> Source {
^
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 {
^
extension Source {
func map<Result>(_ transform: @escaping (T) -> Result) -> Mapping<Result, Self> {
return Mapping(self, transform)
}
}