> On Oct 12, 2016, at 9:01 AM, Xiaodi Wu via swift-evolution 
> <swift-evolution@swift.org> wrote:
> 
> On Wed, Oct 12, 2016 at 10:31 AM, Karl <razie...@gmail.com 
> <mailto:razie...@gmail.com>> wrote:
> I think he wants convenience accessors for the associated values; the problem 
> is that in his example, he shouldn’t even be using associated values at all.

So, what I want (I’m not the originator of this thread, but I’ve long had 
strong opinions on Swift “enums” and I suspect the OP is looking for similar 
functionality) basically boils down to this:

1. Declare the case name and its values together.
I don’t much care whether it’s like a case:
enum Size {
        let height: Int
        let width: Int
        case small(height: 30, width: 30)
        case medium(height: 60, width: 60)
        case large(height: 120, width: 120)
}
or more like a body (some different options for syntax, pick one obviously):
enum Size {
        let height: Int
        let width: Int
        case small {
                height = 30
                width = 30
        }
        case medium: {
                .height = 60
                .width = 60
        }
        case large = {
                let height = 120
                let width = 120
        }
}
Or, this just occurred to me, maybe require “static” to indicate it’s always 
the same and/or in local storage, and help distinguish it from associated-value 
cases?
enum Size {
        let height: Int
        let width: Int
        static case small(height: 30, width: 30)
        static case medium(height: 60, width: 60)
        static case large(height: 120, width: 120)
}


Or I think I could even deal with using tuples or structs as a 
raw-representable, so long as we get syntax to skip the .rawRepresentable 
ugliness:

enum Size: (width: Int, height: Int) {
        case small = (width: 30, height: 30)
        case medium = (width: 60, height: 60)
        case large = (width: 120, height: 120)
}
struct _Size {
        let width: Int
        let height: Int
}
enum Size: _Size {
        case small = _Size(width: 30, height: 30)
        case medium = _Size(width: 60, height: 60)
        case large = _Size(width: 120, height: 120)
}

I somewhat prefer the first case as it’s closest to what other languages offer, 
but the raw-representable-as-tuple solution is growing on me. 

2. Access the values directly as properties (i.e. without having to go through 
the ugly .rawValue).

func getPerimeter(size: Size) {
        return 2 * size.width + 2 * size.height
}

3. Not need the unnecessary boilerplate to achieve #2.  I mean, really, who 
thinks this is acceptable? 30 lines for what is a great deal more clear written 
in 3?

enum Size {
        case small
        case medium
        case large

        var width: Int {
                switch self {
                case .small:
                        return 30

                case .medium:
                        return 60

                case .large:
                        return 120
                }
        }

        var height: Int {
                switch self {
                case .small:
                        return 30

                case .medium:
                        return 60

                case .large:
                        return 120
                }
        }
}


As long as those are satisfied, I’m not particularly concerned about whether 
the cases are carried around like associated data or an int is passed around 
and the implementation goes to a switch/lookup table for the values; I consider 
that an implementation detail.

> The example was about getting a size (a pair of numbers) based on the case of 
> an enum.
> In that case, you need to write a switch statement to return the size. You 
> can either do that every time you need a size from the enum, or you can 
> extend the enum and make it a computed property.
> 
> I do sometimes wonder why we don’t have better accessors. We have the “if 
> case let” thing, but that’s horrible. On the rare occasion where it’s 
> appropriate, it always takes me 4 or 5 attempts to get the incantation 
> correct (single equals!):
> 
> if case .anotherThing(let theError) = myValue {
>     print(“oh, no! an error! \(theError)”)
> }
> 
> Urf.
> 
> I entirely agree with everything you just said. And FWIW, this really is the 
> single most unwieldy incantation in all of Swift--and I think incantation is 
> the right word here. I'd love it if we could sugar to something like `if let 
> theError = myValue.anotherThing?.associatedValue` or something, but of course 
> we could bikeshed this yet again for ages to little end. Perhaps a topic for 
> the coming spring.
>  
> - Karl
> 
>> On 12 Oct 2016, at 17:12, Xiaodi Wu <xiaodi...@gmail.com 
>> <mailto:xiaodi...@gmail.com>> wrote:
>> 
>> 
>> 
>> On Wed, Oct 12, 2016 at 10:07 AM, Karl via swift-evolution 
>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>> Not at all - his proposal looks like the enum cases have an associated 
>> value, when that is exactly what you _don’t_ want. It’s wasted storage 
>> because they have a handful of known values.
>> 
>> It’s a PITA, I get it, I go through it all the time, too; but really this is 
>> the very definition of a computed property. There is nothing to be stored 
>> here. Meanwhile, something like:
>> 
>> enum Something {
>>    case oneThing(UIView)
>>    case anotherThing(Error)
>>    case yetAnotherThing(Int)
>> }
>> 
>> …which is dangerously similar to Braeden’s example, really does store an 
>> instance of UIView or Error or Int along with it. The size of the value is 
>> the maximum of those, plus a couple of bits to record which case it is and 
>> what the type of the payload is.
>> 
>> Confusing those things just because you don’t like writing switch statements 
>> would be bad, IMO. It’s not that much code, and once you’ve done a few of 
>> them you can make it quite compact. If you have a boatload of associated 
>> values, wrap them in a struct.
>> Some more convenient generated accessors for the associated data might be 
>> nice, but that’s been proposed and discussed to death. Others who have 
>> followed the lists more closely can maybe tell you why we don’t have an 
>> accepted proposal for it.
>> 
>> I agree with Karl on this. There should be clarity here as to what's 
>> proposed. If it's a change to how enums are laid out in memory, then you'll 
>> need to show we're not sacrificing performance/size in the overwhelmingly 
>> more common use cases, and why the extra storage is useful in the first 
>> place; if it's syntactic sugar, that has already been proposed multiple 
>> times and really isn't in scope for this phase of Swift 4--nor does it 
>> really enable any new use cases not possible now.
>>  
>> - Karl
>> 
>> > On 12 Oct 2016, at 13:52, Rien <r...@balancingrock.nl 
>> > <mailto:r...@balancingrock.nl>> wrote:
>> >
>> > I read Braeden’s example such that this proposal is in reality “just” 
>> > syntactic sugar. AFAIAC it does not change how enums are implemented after 
>> > compilation.
>> >
>> > Like sugar, it makes working with enums clearer and therefore easier. All 
>> > initialisation values are defined right there with the ‘case’ instead of 
>> > hidden in a tree of multiple ‘var’s.
>> > While I was sceptical about this proposal, Braeden’s example makes it a +1.
>> >
>> > Rien.
>> >
>> > Btw: I made the almost identical suggestion you did ;-)
>> >
>> >
>> >> On 12 Oct 2016, at 13:31, Karl <razie...@gmail.com 
>> >> <mailto:razie...@gmail.com>> wrote:
>> >>
>> >> I very much disagree with the proposal, and all of the things supporting 
>> >> it (like deriving enums from other types and whatnot). I think you need 
>> >> to take a step up from caring about whether it’s a struct or enum and 
>> >> think about what you are trying to model; that will guide you towards the 
>> >> correct type(s) to use.
>> >>
>> >> You have only shown a handful of fixed size values, so I would suggest a 
>> >> computed property in your case:
>> >>
>> >> enum FixedSize {
>> >> case small
>> >> case medium
>> >> case large
>> >>
>> >> struct Size { let width : Int; let height: Int }
>> >>
>> >> var size : Size {
>> >>   switch self {
>> >>       case .small: return Size(width: 30, height: 30)
>> >>       // … etc
>> >>   }
>> >> }
>> >> }
>> >>
>> >> There is no need for these sizes to be stored at all. If you want them 
>> >> baked in to your enum’s values, clearly you expect them to be specific 
>> >> values. It’s more efficient to just drop the stored data altogether in 
>> >> this case; this enum will get lowered in to single byte, which is more 
>> >> efficient to store and transport.
>> >>
>> >> Karl
>> >>
>> >>> On 12 Oct 2016, at 13:15, Mateusz Malczak via swift-evolution 
>> >>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>> >>>
>> >>>> Mateusz, you lost me with “store some extra data”.
>> >>>> Does that mean something extra besides the code that Braeden suggested?
>> >>>
>> >>> What I meant by “store some extra data” was, to be able to define
>> >>> immutable properties of any type, as a part of enum instead of
>> >>> defining getters witch switches. I think Braeden example explains the
>> >>> whole idea of that proposal.
>> >>>
>> >>> --
>> >>> | Mateusz Malczak
>> >>>
>> >>>
>> >>> 2016-10-12 8:42 GMT+02:00 Rien <r...@balancingrock.nl 
>> >>> <mailto:r...@balancingrock.nl>>:
>> >>>> I’d give a +1 for the suggestion of Braeden.
>> >>>>
>> >>>> Mateusz, you lost me with “store some extra data”.
>> >>>> Does that mean something extra besides the code that Braeden suggested?
>> >>>>
>> >>>> Rien.
>> >>>>
>> >>>>> On 12 Oct 2016, at 00:13, Mateusz Malczak via swift-evolution 
>> >>>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>> >>>>>
>> >>>>> That's exactly what this proposal is about. I would like to
>> >>>>> keep all enum properties but add an extra feature, so that enums can
>> >>>>> store some extra data.
>> >>>>> --
>> >>>>> | Mateusz Malczak
>> >>>>> +-------------------------------
>> >>>>> | mate...@malczak.info <mailto:mate...@malczak.info>
>> >>>>> | http://malczak.info <http://malczak.info/>
>> >>>>>
>> >>>>>
>> >>>>> 2016-10-11 23:42 GMT+02:00 Braeden Profile <jhaezhy...@gmail.com 
>> >>>>> <mailto:jhaezhy...@gmail.com>>:
>> >>>>>> So, just to recap, the proposed solution is to help enums expose 
>> >>>>>> associated
>> >>>>>> values via properties, and is not to create enums that are open to 
>> >>>>>> extra
>> >>>>>> unnamed cases (RectSize(width:0,height:10))?  What I see is that 
>> >>>>>> enums would
>> >>>>>> still maintain their standing where an instance is just a selection 
>> >>>>>> of a
>> >>>>>> finite number of options, possibly with data attached.  In proposal 
>> >>>>>> 1, we
>> >>>>>> want some sort of syntax where this…
>> >>>>>>
>> >>>>>> enum RectSize
>> >>>>>> {
>> >>>>>> let height:Int
>> >>>>>> let width:Int
>> >>>>>> case small(width: 30, height: 30)
>> >>>>>> case medium(width: 60, height: 60)
>> >>>>>> case large(width: 120, height: 120)
>> >>>>>> }
>> >>>>>>
>> >>>>>> …is syntactically just like writing this…
>> >>>>>>
>> >>>>>> enum RectSize
>> >>>>>> {
>> >>>>>> case small
>> >>>>>> case medium
>> >>>>>> case large
>> >>>>>> var height:Int
>> >>>>>> {
>> >>>>>>   switch self
>> >>>>>>   {
>> >>>>>>      case .small: return 30
>> >>>>>>      case .medium: return 60
>> >>>>>>      case .large: return 90
>> >>>>>>   }
>> >>>>>> }
>> >>>>>> let width:Int
>> >>>>>> {
>> >>>>>>   switch self
>> >>>>>>   {
>> >>>>>>      case .small: return 30
>> >>>>>>      case .medium: return 60
>> >>>>>>      case .large: return 90
>> >>>>>>   }
>> >>>>>> }
>> >>>>>> }
>> >>>>>>
>> >>>>>> …right?  That way, you can write this:
>> >>>>>>
>> >>>>>> var size: RectSize = .small
>> >>>>>> size.height == 30 // true
>> >>>>>> size.rawValue // Error:  RectSizes has no property `rawValue`.
>> >>>>>> size.height = 40 // Error:  `height` is immutable
>> >>>>>> size = .medium
>> >>>>>>
>> >>>>>> I think we were also (separately) proposing to extend `rawValue` to 
>> >>>>>> take all
>> >>>>>> kinds of statically known values, like structs or tuples.  Doing that 
>> >>>>>> would
>> >>>>>> accomplish much of the same thing.
>> >>>>>>
>> >>>>>> Someone fact-check me here!  I really do think something like this 
>> >>>>>> would be
>> >>>>>> a good idea, if we could get the right syntax.
>> >>>>>>
>> >>>>>> On Oct 11, 2016, at 7:06 AM, Mateusz Malczak via swift-evolution
>> >>>>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>> >>>>>>
>> >>>>>> Hi,
>> >>>>>> I think we are here discussing two different aspects of introducing
>> >>>>>> this new feature - code syntax and underlying implementation.
>> >>>>>> In terms of code syntax I would go with first proposal as it seems to
>> >>>>>> me the simplest approach. When it comes to underlying implementation,
>> >>>>>> I can imagine that during compilation internal struct is created, as
>> >>>>>> well as any required property getters. This way you could get a
>> >>>>>> variation of rawValue implementation, at least from theoretical point
>> >>>>>> of view :D
>> >>>>>>
>> >>>>>> --
>> >>>>>> | Mateusz Malczak
>> >>>>>> +-------------------------------
>> >>>>>> | mate...@malczak.info <mailto:mate...@malczak.info>
>> >>>>>> | http://malczak.info <http://malczak.info/>
>> >>>>>>
>> >>>>>>
>> >>>>>> 2016-10-10 23:42 GMT+02:00 Haravikk <swift-evolut...@haravikk.me 
>> >>>>>> <mailto:swift-evolut...@haravikk.me>>:
>> >>>>>>
>> >>>>>>
>> >>>>>> On 10 Oct 2016, at 20:34, Mateusz Malczak <mate...@malczak.info 
>> >>>>>> <mailto:mate...@malczak.info>> wrote:
>> >>>>>>
>> >>>>>> I know, but what I'm saying is that this problem could be solved in 
>> >>>>>> the
>> >>>>>> multiple values case by allowing tuples as raw values for enums, 
>> >>>>>> since that
>> >>>>>> would allow you to specify both width and height. So it'd look 
>> >>>>>> something
>> >>>>>> like this:
>> >>>>>>
>> >>>>>>
>> >>>>>> We have three different possible solution
>> >>>>>> 1. stored properties defined as part of enumeration type
>> >>>>>> enum RectSizes: MyRect
>> >>>>>> {
>> >>>>>> let height:Int
>> >>>>>> let width:Int
>> >>>>>> case Small(width: 30, height: 30)
>> >>>>>> case Medium(width: 60, height: 60)
>> >>>>>> case Large(width: 120, height: 120)
>> >>>>>> }
>> >>>>>>
>> >>>>>> 2. struct as rawValue
>> >>>>>> struct MyRect
>> >>>>>> {
>> >>>>>> var height:Int
>> >>>>>> var width:Int
>> >>>>>> var area:Int {return height:Int*width}
>> >>>>>> }
>> >>>>>>
>> >>>>>> enum RectSizes: MyRect
>> >>>>>> {
>> >>>>>> case Small(30,30)
>> >>>>>> case Medium(60,60)
>> >>>>>> case Large(120,120)
>> >>>>>> }
>> >>>>>>
>> >>>>>> 3. tuples as rawValue
>> >>>>>> enum Format : (width:Int, height:Int) {
>> >>>>>> case small(30, 30)
>> >>>>>> case medium(60, 60)
>> >>>>>> case large(120, 120)
>> >>>>>>
>> >>>>>> var width:Int { return self.rawValue.width }
>> >>>>>> var height:Int { return self.rawValue.height }
>> >>>>>> }
>> >>>>>>
>> >>>>>> Solutions 2 and 3 are quire similar, to get value of a stored property
>> >>>>>> we need to use rawValue or define value getters. In addition in
>> >>>>>> solution 2 we define an additional data type just to be used as an
>> >>>>>> enumeration type rawValue type. In my opinion, first approach would be
>> >>>>>> a best solution, type definition is clear and self-explanatory because
>> >>>>>> it is similar to how enums/classes are defined.
>> >>>>>>
>> >>>>>>
>> >>>>>> --
>> >>>>>> | Mateusz Malczak
>> >>>>>>
>> >>>>>>
>> >>>>>> Actually I'd say your option 2 here is more similar to option 1 (you 
>> >>>>>> seem to
>> >>>>>> be using a struct to define the stored properties instead). The issue 
>> >>>>>> here
>> >>>>>> is that storing properties conflicts with what you're actually doing, 
>> >>>>>> which
>> >>>>>> is storing case-specific values, which is what rawValue already does, 
>> >>>>>> it's
>> >>>>>> just too limited for your current use-case (multiple values).
>> >>>>>>
>> >>>>>> The complete solution would be to introduce the concept of tuples as
>> >>>>>> literals (even though they can't currently conform to types); this 
>> >>>>>> would
>> >>>>>> make it a lot easier to support the use of any type as a fixed value 
>> >>>>>> for
>> >>>>>> each case (not just tuples). For example, say we introduced as new 
>> >>>>>> protocol:
>> >>>>>>
>> >>>>>> protocol ExpressableByTuple {
>> >>>>>> associatedtype TupleType // somehow force this to be a tuple or
>> >>>>>> ExpressableByType type
>> >>>>>> init(tupleLiteral:TupleType)
>> >>>>>> }
>> >>>>>>
>> >>>>>> With a bit of magic all tuples could conform to this protocol with
>> >>>>>> themselves as the literal type, allowing us to use them as enum raw 
>> >>>>>> values;
>> >>>>>> likewise this could then be used to more easily enable any custom
>> >>>>>> struct/class for storage in enum cases, as instead of supporting their
>> >>>>>> constructors directly we can just support construction via a tuple 
>> >>>>>> literal.
>> >>>>>>
>> >>>>>>
>> >>>>>> My other reason I don't favour option 1, while it looks a bit 
>> >>>>>> prettier, is
>> >>>>>> that it's a bit confusing; enums have two types of stored properties, 
>> >>>>>> ones
>> >>>>>> that can be changed (and inspected) which is what you get when you 
>> >>>>>> declare
>> >>>>>> case small(Int, Int) for example, these are stored as part of the enum
>> >>>>>> itself (so in that example it's 17-bytes on a 64-bit system). However
>> >>>>>> rawValues are more like constants/static values, and don't increase 
>> >>>>>> the size
>> >>>>>> of the type, and I just feel that this is the right way to do what 
>> >>>>>> you're
>> >>>>>> proposing.
>> >>>>>>
>> >>>>>> _______________________________________________
>> >>>>>> swift-evolution mailing list
>> >>>>>> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
>> >>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> >>>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>> >>>>>>
>> >>>>>>
>> >>>>> _______________________________________________
>> >>>>> swift-evolution mailing list
>> >>>>> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
>> >>>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> >>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>> >>>>
>> >>> _______________________________________________
>> >>> swift-evolution mailing list
>> >>> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
>> >>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> >>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>> >>
>> >
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to