对于枚举案例,Swift @autoclosure破坏了v1.2中的兼容性

时间:2015-04-09 13:25:47

标签: xcode swift

我只是将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并不能解决问题。

3 个答案:

答案 0 :(得分:3)

正确。这已被删除,明确是为了防止您提供的情况。 Autoclosures并不打算以这种方式使用,Swift团队故意删除了这样做的能力。在Result类型中,这很危险,因为每次访问时都会重新关闭闭包。如果关闭中存在副作用,这可能会产生相当惊人的影响。即使它只是非平凡的,它也会产生令人惊讶的性能影响。

这里的正确工具是Box。请参阅Rob Rix的Result以获得此类型的良好实现。

答案 1 :(得分:1)

我认为我找到了解决方案。您只需在原始实现中更改2行即可使其正常工作:

case Success(() -> T)

public init(@autoclosure(escaping) _ value: () -> T) {

答案 2 :(得分:0)

对于那些只需要简单解决方案而无需导入外部框架的人:

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)
}