Draft Proposal: Declare variables in 'case' labels with multiple patterns


(Andrii Chernenko) #1

Hello everyone,

This is a great proposal and indeed it would be nice to have this feature
in Swift.

However, there is another use case I have in mind. It would be nice to
match multiple cases with associated values of different types which
conform to a certain protocol.

I'll illustrate with an example. Suppose I am implementing REST API
requests using enums.

protocol Serializable {
  func serialize() -> NSData
}

struct CreateFooRequest: Serializable {
  let title: String
  let date: NSDate
}

struct UpdateFooRequest: Serializable {}

...

enum APIRequest {
    case .CreateFoo(request: CreateFooRequest),
    case .UpdateFoo(request: UpdateFooRequest)
    ...

    var HTTPRequest: NSHTTPRequest { ... }

    var URL: NSURL { ... }

    var headers: [String: String] { ... }

    var HTTPBody: NSData? {
        switch self {
          case let .CreateFoo(request):
            return request.serialize()
          case let .UpdateFoo(request):
            return request.serialize()
          ...
        }
    }
}

Current proposal aims to eliminate repetitiveness such as in the HTTPBody
property of the APIRequest enum, but does it cover the case where
associated value types are different, but conform to the same protocol? It
is not clear to me.

Just in case, here's the link to the proposal:
https://github.com/apple/swift-evolution/pull/119


(Jordan Rose) #2

You should be able to do this today using "let x as Y":

protocol Serializable {
  func serialize() -> String?
}

struct CreateFooRequest: Serializable {
  let title: String
  func serialize() -> String? { return nil }
}

struct UpdateFooRequest: Serializable {
  func serialize() -> String? { return nil}
}

enum APIRequest {
    case CreateFoo(request: CreateFooRequest)
    case UpdateFoo(request: UpdateFooRequest)
    //...

    var HTTPBody: String? {
        switch self {
        case let .CreateFoo(request as Serializable),
            let .UpdateFoo(request as Serializable):
          return request.serialize()
        }
    }
}

I don't think we want to automatically try to infer a common type—it's too easy for the compiler to pick a surprising type that way—but it's there when you need it.

Jordan

···

On Mar 15, 2016, at 14:17 , Andrii Chernenko via swift-evolution <swift-evolution@swift.org> wrote:

Hello everyone,

This is a great proposal and indeed it would be nice to have this feature in Swift.

However, there is another use case I have in mind. It would be nice to match multiple cases with associated values of different types which conform to a certain protocol.

I'll illustrate with an example. Suppose I am implementing REST API requests using enums.

protocol Serializable {
  func serialize() -> NSData
}

struct CreateFooRequest: Serializable {
  let title: String
  let date: NSDate
}

struct UpdateFooRequest: Serializable {}

...

enum APIRequest {
    case .CreateFoo(request: CreateFooRequest),
    case .UpdateFoo(request: UpdateFooRequest)
    ...

    var HTTPRequest: NSHTTPRequest { ... }

    var URL: NSURL { ... }

    var headers: [String: String] { ... }

    var HTTPBody: NSData? {
        switch self {
          case let .CreateFoo(request):
            return request.serialize()
          case let .UpdateFoo(request):
            return request.serialize()
          ...
        }
    }
}

Current proposal aims to eliminate repetitiveness such as in the HTTPBody property of the APIRequest enum, but does it cover the case where associated value types are different, but conform to the same protocol? It is not clear to me.

Just in case, here's the link to the proposal: https://github.com/apple/swift-evolution/pull/119_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution