Default values for enum associated values


(African Swift) #1

Swift enum cases with associated values are quite similar to function
parameters, except that currently flexible specification with enum
associated values, is only possible by using Parameter Objects.

The proposed solution is to enhance Swift enum associated values to support
default values in a functionally equivalent way to default parameters on
functions.

<https://gist.github.com/AfricanSwift/bfeab7d930785ed5096939ce24bd6cbf#detailed-design>Detailed
design

For example, let's say we define a person case with associated values for
firstname and surname:

enum ... {
   case person(firstname: String, surname: String)
}

... then down the line let's say we want to extend it with a person's
age, however
unlike functions, we're left only with imperfect options:

   - break the API
   - create a new case, e.g. person2(firstname: String, surname: String,
   age: Int)
   - re-implement case with a parameter object

Pitch

Should it be possible to assign defaults to *enum associated values*, with
a functional equivalence to function default parameter values (flexible
API), for example:

enum ... {
   case person(firstname: String, surname: String, age: Int? = nil)
}

Summary

Support defaults for enum associated values: to ensure that all the places
where the *associated value case* was used would continue to work when new
parameters (associated values) are added.


(Chris Lattner) #2

This is an additive proposal, thus out of scope for Swift 3. Please wait for post-swift-3 planning to start, which is after August 1.

-Chris

···

On Jul 18, 2016, at 12:49 PM, African Swift via swift-evolution <swift-evolution@swift.org> wrote:

Swift enum cases with associated values are quite similar to function parameters, except that currently flexible specification with enum associated values, is only possible by using Parameter Objects.


(Svein Halvor Halvorsen) #3

Could this be revisited?

I sometimes find myself writing stuff like this:

enum Foo {
    case bar(Int, String?)
    case qux

    static func bar(_ value: Int) -> Foo {
        return .bar(value, nil)
    }
}

let foo: Foo = .bar(1)  // same as .bar(1, nil)

The static func trick works well as long as there is only one "optional" associated value, but when the list grows, I can't use a single static func as a factory method since the func will be flagged as a redefinition of the related case:

enum Foo {
    case bar(Int, String?, Double?)
    case qux

    static func bar(_ a: Int, _ b: String? = nil, _ b: Double? = nil) -> Foo {
        // Definition conflicts with previous value
        // Invalid redeclaration of 'bar'
        return .bar(a, b, c)
    }
}

It would be nice to be able to simply write:

enum Foo {
    case bar(Int, String? = nil, Double? = nil)
    case qux
}

(Alejandro Alonso) #4

This is technically already accepted in SE-0155 https://github.com/apple/swift-evolution/blob/master/proposals/0155-normalize-enum-case-representation.md which @codafi has an initial implementation for here: https://github.com/apple/swift/pull/21381


(Svein Halvor Halvorsen) #5

Niceness!