Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to specialize a generic enum in Swift

Tags:

generics

swift

I'm using the antitypical/result package to provide a generic Result type. This package defines Result as follows:

public enum Result<T, Error> {
     ...
}

Now, I only wish to return errors of type NSError in my code, so it would be nice if I didn't have to keep doing things this:

func myFunc() -> Result<String, NSError> { ... }

Instead, I want to create a derived StdResult type so that I can do this instead:

func myFunc() -> StdResult<String> { ... }

I've tried various things but I can't find a solution. This, for example, doesn't work:

typealias StdResult<T> = Result<T, NSError>

Is there a solution which will work?

like image 938
tarmes Avatar asked May 29 '15 07:05

tarmes


People also ask

How do I create an enum instance in Swift?

two is (String) -> Example , where the closures expressed by these two cases yield different results; instances of . one(...) and . two(...) , respectively. Hence, instead of writing your own method to "clone" a given case, you could simply have a computed property which returns the already existing closures Example.

Is enum generic?

The enum is a default subclass of the generic Enum<T> class, where T represents generic enum type. This is the common base class of all Java language enumeration types. The transformation from enum to a class is done by the Java compiler during compilation. This extension need not be stated explicitly in code.

Can we define method in enum Swift?

Swift enum syntax To define an enum in Swift, use the keyword enum followed by the name of the enum. The name of an enum in Swift should follow the PascalCase naming convention in which the first letter of each word in a compound word is capitalized.

Can enum conform to Swift protocol?

Yes, enums can conform protocols. You can use Swift's own protocols or custom protocols. By using protocols with Enums you can add more capabilities.


2 Answers

Unfortunately we're pretty limited here. Swift doesn't support generic typealias, so we can do this as a sort of hack with struct:

struct StdResult<T> {
    typealias Type = Test<T, NSError>
}

func myFunc() -> StdResult<String>.Type {

}

Does that fit what you were looking for closely enough?

like image 152
tbondwilkinson Avatar answered Oct 19 '22 19:10

tbondwilkinson


At the moment, there's no generic typealias support nor enumeration inheritance, but you could use RawRepresentable protocol. It's not as easy as if a generic typealias exists, but it may fit your needs.

RawRepresentable

From Apple's documentation:

A type that can be converted to an associated "raw" type, then converted back to produce an instance equivalent to the original.

public protocol RawRepresentable {
  typealias RawValue
  public init?(rawValue: Self.RawValue)
  public var rawValue: Self.RawValue { get }
}

That said, your raw value must be Result<T, NSError>:

enum StdResult<T>: RawRepresentable {

  var rawValue: Result<T, NSError> {
    switch self {
    case .Success(let value):
      return Result.Success(value)
    case .Failure(let error):
      return Result.Failure(error)
    }
  }
  
  init?(rawValue: Result<T, NSError>) {
    switch rawValue {
    case .Success(let value):
      self = .Success(value)
    case .Failure(let error):
      self = .Failure(error)
    }
  }

  case Success(T)
  case Failure(NSError)
}

func myFunc() -> StdResult<String> { }

Note: Properties and methods of original Result enumeration are only accessible from rawValue property, so, for example, if you want to compare your new StdResult with another, you must use rawValue property or reimplement these protocols yourself.

like image 20
Wallace Campos Avatar answered Oct 19 '22 19:10

Wallace Campos