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

Mateusz Malczak mateusz at malczak.info
Wed Oct 12 06:15:16 CDT 2016


> 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 <Rien at 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 at 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
>> +-------------------------------
>> | mateusz at malczak.info
>> | http://malczak.info
>>
>>
>> 2016-10-11 23:42 GMT+02:00 Braeden Profile <jhaezhyr12 at 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 at 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
>>> +-------------------------------
>>> | mateusz at malczak.info
>>> | http://malczak.info
>>>
>>>
>>> 2016-10-10 23:42 GMT+02:00 Haravikk <swift-evolution at haravikk.me>:
>>>
>>>
>>> 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.
>>>
>>> _______________________________________________
>>> swift-evolution mailing list
>>> swift-evolution at swift.org
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>
>>>
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>


More information about the swift-evolution mailing list