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

Rien Rien at Balancingrock.nl
Wed Oct 12 01:42:59 CDT 2016


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