[swift-evolution] [Proposal] Enums with stored properties

Haravikk swift-evolution at haravikk.me
Mon Oct 10 16:42:11 CDT 2016


> On 10 Oct 2016, at 20:34, Mateusz Malczak <mateusz at 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.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20161010/9956cd87/attachment.html>


More information about the swift-evolution mailing list