[swift-evolution] Proposal: Stored properties for enums

Jonathan Hise Kaldma info at hisekaldma.com
Thu Dec 10 04:14:22 CST 2015


> 10 dec. 2015 kl. 02:01 skrev Chris Lattner <clattner at apple.com>:
> 
>> On Dec 9, 2015, at 12:28 PM, Jonathan Hise Kaldma via swift-evolution <swift-evolution at swift.org> wrote:
>> But it breaks down if you need to keep track of more data for each tree node, e.g. if you’re making a parser and need to keep track of source location. This could easily be solved with stored properties:
>> 
>> enum Expression {
>>   case Number(Double)
>>   case Variable(String)
>>   indirect case Unary(Operator, Expression)
>>   indirect case Binary(Operator, Expression, Expression)
>> 
>>   var location: Int = 0
>>   var length: Int = 0
>> }
> 
> The concern with doing this is that Swift currently distinguishes clearly between product & sum types, and this is a good thing.  With your proposal, there would be no difference between:
> 
> struct X {
>  var a, b : Int
> }
> 
> and:
> 
> enum X {
>  var a, b : Int
> }

The difference would be that you can't initialize the enum, since it doesn't have any cases. Essentially a struct would be an enum with zero cases.

> As such, there would be no reason to have concepts in the language.  Some might argue that this is good (fewer things == better), but I’d argue that this is worse, because it can be better for clearly different things to be... different.

Struct would be the zero-case subset of enum. Related, but different.

> Further, Swift has a simple way to express this today use: an enum inside of a struct.  As far as I can tell, the only bad thing about this is that it breaks pattern matching over the recursive case.  However, this is a already an annoying aspect of swift’s current design that show up in other ways: for example, structs are generally more powerful than tuples, except that tuples can be pattern matched over.

The problem with an enum inside a struct, is that, as Dave pointed out, it puts more focus on the things that are similar, and less on the things that are different, which is often the opposite of what you want.

Also, it usually doesn't really capture what you're trying to model.

struct Block {
  var type: BlockType
  var pos, length : Float
}

enum BlockType {
  case Audio(AudioData)
  case Video(VideoData)
}

Why is BlockType a different thing? A block can be audio or video, not something else. And modeling different cases of something, isn't that what enums are for? It would be much more elegant and readable to just say:

enum Block {
  case Audio(AudioData)
  case Video(VideoData)
  var pos, length : Float
}

> IMO, the right way to fix this is to introduce the concept of pattern matching over structs and classes.  If you dig through history, you’ll see that Joe Groff implemented a sketch of this functionality in the compiler, but it was never fully baked so it was turned off before Swift 1.0, and eventually got removed.  A better baked out design and implementation could fix the problems you raise without causing a conflation between structs and enums.
> 
> - Chris

Thanks! I'll take a look.

And thanks for a great language!

Best,
Jonathan


More information about the swift-evolution mailing list