在将旧的(不是我的)代码从swift 2转换为swift 4之后,我需要泛型和返回类型的帮助
let cryptedJsonData = packet.encodeJSON()
.flatMap { $0.gzippedData() } //here I am getting error
Cannot convert value of type 'Result<Data, Error>' to closure result type 'Result<T, E>'
flatmap函数
extension Result {
func map<U>( _ function: @escaping (T) -> U ) -> Result<U, E> {
return flatMap { .success( function( $0 ) ) }
}
func flatMap<U>( _ function: (T) -> Result<U, E> ) -> Result<U, E> {
switch self {
case .success(let value): return function(value)
case .failure(let error): return .failure(error)
}
}
}
gzippedData()
private let CHUNK_SIZE: Int = 2 ^ 14
func gzippedData() -> Result<Data, Error> {
var data = Data(count: CHUNK_SIZE)
return .success( data as Data)
}
结果
enum Result<T, E> {
case success(T)
case failure(E)
}
答案 0 :(得分:1)
如果您定义了自己的Result
类型,我怀疑问题是由于不同模块中Result
的两个定义之间的类型不兼容引起的。
请注意,Swift的标准库中已经定义了一种Result
类型(请参见https://developer.apple.com/documentation/swift/result),其实现与您发布的内容非常接近。如果您实际定义了自己的类型,则Result
返回的encodeJSON()
与Result
返回的gzippedData()
可能会有所不同。不幸的是,Swift处理冲突名称的能力很差,尤其是当这些冲突与标准库中的名称发生时。
这是一种复制问题的方法:
// This enum is defined in my own source.
enum Result<T, E> {
case success(T)
case failure(E)
}
// This is an dummy error type, with the sole purpose of specializing `Result`.
enum SomeError: Error {}
// This extension has for sole purpose to add a method to `String` that returns
// an instance of *my* `Result` type.
extension String {
func foo() -> Result<String, SomeError> {
return .success(self)
}
}
// Now assume this function comes from a third party library that uses Swift's
// `Result` type, from the standard library.
func bar() -> Swift.Result<String, SomeError> {
return .success("Hello, World!")
}
// The following line will trigger the exact same error as yours, because the
// `Result` type that expects `flatMap`'s argument is not *my* `Result` type,
// but that of Swift's standard library.
bar().flatMap { $0.foo() }
请注意,如果您在Swift.Result
的共域上简单地用Result
替换bar
,则此示例可以很好地编译(假设您还提供了flatMap
的定义)。
如果您定义了自己的Result
类型,建议您使用Swift的类型(我猜它的行为与您的预期完全相同),或者重命名您自己的类型,以使其定义不再与Swift的标准库中的定义冲突。