> On 27 Sep 2016, at 18:55, Joe Groff via swift-evolution 
> <[email protected]> wrote:
> 
> 
>> On Sep 26, 2016, at 8:51 AM, Jérôme Duquennoy via swift-evolution 
>> <[email protected]> wrote:
>> 
>> Summary
>> The aim of this proposal is to offer a new syntax to ease some uses of enums 
>> with payload.
>> 
>> Situation to improve:
>> Enums makes it possible to have explicate typing where it was not possible 
>> before. A classic example of that is filling a dictionary with data coming 
>> from a file or a stream (json, plist, …) : the types of possible values is 
>> finite : arrays, dicts, int, double, bool or string for json for exemple.
>> An enum can represent this finite range of possible types, its make the code 
>> and the API more self-documented.
>> Then, you have two possibilities to deal with this enum:
>> - using switch statements
>> - using the if case syntax introduced by swift 2
>> 
>> The drawback is that those two solutions can lead to writing code with high 
>> visual complexity, even though the logic behind is pretty simple.
>> 
>> Consider this example of a data dictionary, that a web service could have 
>> returned:
>> - book
>>  - title: 
>>  - author:
>>    - name: Apple
>>    - age: 40
>> 
>> We can decode this in a variable of type [String:Value], where Value is:
>> 
>> enum Value {
>>  case integer(value: Int)
>>  case string(value: String)
>>  case dict(value: [String:Value])
>>  case null
>> }
>> 
>> Here is a snippet of code to access the age of the author:
>> 
>> if case .dict(let book) = data {
>>  if case .dict(let author) = book["author"] ?? .null {
>>    if case .integer(let age) = author["age"] ?? .null {
>>      // now we have the age
>>    }
>>  }
>> }
>> 
>> The multiple indentation levels can rapidly make this code unattractive to 
>> read, and we need to add a null case to the enum to deal with optional 
>> values.
>> 
>> Proposed solution:
>> I suggest to add a new syntax, using the case keyword to ease access to the 
>> payload of such enums :
>> 
>> let payloadContent = case? .enumCase(variable)
>> 
>> The payloadContent variable will be an optional, that can be either nil, or 
>> contain the payload of enumCase.
>> If the payload contains multiple variables, payloadContent will be a tupple.
>> This syntax can accommodate an optional variable as an input. If the value 
>> of variable is nil, then payloadContent will be nil.
>> Only enum cases with a payload can be used with this syntax (it would make 
>> no sens for cases without a payload).
>> 
>> With that syntax, the null case of the enum can be removed, and the code to 
>> access the age becomes:
>> 
>> let book = case? .dict(inputData)
>> let author = case? .dict(book?["author"])
>> let age = case? .integer(author?["age"])
>> 
>> Advantages:
>> - It leverages the well established notion of optional, and similar logic 
>> already exists in the language (for the as? operator notably).
>> - It does not add a new keyword
>> - It promotes the use of enum to enforce explicit typing, which leads to 
>> more self-documenting code
>> - It reduces the complexity of the code in situations such as the one of the 
>> exemple
>> 
>> Drawbacks:
>> - It adds a third use of the case keyword. 
>> - In the proposed syntax, the variable between parenthesis is not the 
>> payload, but the variable to decode. This might be disturbing, as it differs 
>> from the other syntax of enum values.
>> - If the payload is an optional, it is not possible to differentiate a 
>> non-matching case and a matching case a nil payload.
>> 
>> Alternatives:
>> - Another syntax without parenthesis could be used to avoid the second 
>> drawback:
>> let payload = case? .enumCase variable
>> 
>> Impact on existing code:
>> None, this is adding a new syntax
>> 
>> 
>> This proposal would have no impact on the ABI, so it probably does not fit 
>> the stage 1 of swift 4’s roadmap. But I would be glad to have your feedback, 
>> so that I can have a proposal ready once we enter stage 2.
>> So what your thoughts on that proposal ?
> 
> I think it's reasonable to want an expression for extracting the payload of a 
> enum case as an Optional. Instead of introducing a new operator, though, we 
> could say that the cases themselves behave as Optional properties of an enum, 
> which would allow you to say:
> 
> if let book = inputData.dict,
>   let author = book["author"].dict,
>   let age = author["age"].integer { ... }
> 
> -Joe
> _______________________________________________
> swift-evolution mailing list
> [email protected]
> https://lists.swift.org/mailman/listinfo/swift-evolution

I was thinking the same thing. I’m finding myself writing a lot of convenience 
accessors of the type:

enum MyEnum<T> {
    case stateOne
    case stateTwo(Array<T>)
    case stateThree(T)
    case stateFour(Error, T)

    var error : (Error, T)? {
        if case .error(let r) = self { return r }
        return .none
    }
}

It would be nice if the compiler could generate these style of accessors, with 
the payload available as an optional tuple. Perhaps it would be called `var 
stateFourData : (Error, T)?` or something predictable.

While I’m on the subject, sometimes I want every case of an enum to be its own 
type, which is a subtype of the enum’s type - e.g. MyEnum<Int>.stateThree.self. 
That would allow you to keep a collection of MyEnum values which are guaranteed 
to all be the same case.
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to