我刚刚将Xcode更新到6.3,过去在Xcode 6.2中编译的Swift代码现在不编译了。
import Foundation
public enum Result<T> {
case Success(@autoclosure() -> T)
case Failure(NSError)
case Cancelled
public init(_ value: T) {
self = .Success(value)
}
public init(_ error: NSError) {
self = .Failure(error)
}
public init() {
self = .Cancelled
}
public var failed: Bool {
switch self {
case .Failure(let error):
return true
default:
return false
}
}
public var error: NSError? {
switch self {
case .Failure(let error):
return error
default:
return nil
}
}
public var value: T? {
switch self {
case .Success(let value):
return value()
default:
return nil
}
}
}
此行:case Success(@autoclosure() -> T)
产生错误:'autoclosure' attribute is only allowed on parameters, not on enum cases
仅仅移除@autoclosure
并不能解决问题。
正确。它已被删除,明确是为了防止出现您提供的情况。自动闭包不打算以这种方式使用,Swift团队故意取消了这样做的能力。在Result
类型中,这是危险的,因为每次访问闭包时都会重新评估它。如果关闭有副作用,这可能会产生非常令人惊讶的影响。即使这不是小事,它也会对性能产生令人惊讶的影响。
这里正确的工具是Box
。请参阅Rob Rix的Result
以获得此类型的良好实现。
我想我已经找到了解决方案。您只需要更改原始实现中的2行即可使其工作:
case Success(() -> T)
和
public init(@autoclosure(escaping) _ value: () -> T) {
对于那些只想要一个简单的解决方案而不需要导入外部框架的人:
public enum Result<T> {
case Success(Box<T>)
case Failure(String)
public init(_ value: T) {
self = .Success(Box(value))
}
public init(_ error: String) {
self = .Failure(error)
}
}
// Due to current swift limitations, we have to include this Box in Result.
final public class Box<T> {
public let unbox: T
public init(_ value: T) { self.unbox = value }
}
public func success<T>(value: T) -> Result<T> {
return .Success(Box(value))
}
public func failure<T>(error: String) -> Result<T> {
return .Failure(error)
}