[swift-evolution] Proposal: Stored properties for enums
Jonathan Hise Kaldma
info at hisekaldma.com
Thu Dec 10 06:34:41 CST 2015
Not really. It certainly works, but it's hard to follow. Also, this example was imagining some type of editor with blocks on a timeline. So the pos and length should really be properties of the block, not of the data.
Without enum properties, I agree with Chris: enum inside struct is the best way to model this type of thing.
My problem isn't really that you can't do these things today, it's that the solutions are ugly, hard to read, and 10x as long as they need to be. Expressions for example can easily be modeled with structs conforming to a protocol:
protocol Expression {
var loc, len : Int
}
struct ValueExpression: Expression {
var value: Double
var loc, len : Int
}
struct UnaryExpression: Expression {
var op: Operator
var expr: Expression
var loc, len : Int
}
struct BinaryExpression: Expression {
var op: Operator
var left, right : Expression
var loc, len : Int
}
But that's a lot of boilerplate to express something that's actually pretty simple conceptually. With enum properties it is just:
enum Expression {
case Value(Double)
indirect case Unary(Operator, Expression)
indirect case Binary(Operator, Expression, Expression)
var pos, len : Int
}
Since readability is one of the main goals for Swift, I think it makes sense to include them.
Best,
Jonathan
> 10 dec. 2015 kl. 12:00 skrev Al Skipp <al_skipp at fastmail.fm>:
>
> Would the following construction address your use case?
>
> struct DataInfo<DataType> {
> var data: DataType
> var pos, length: Float
> }
>
> enum Block {
> case Audio(DataInfo<AudioData>)
> case Video(DataInfo<VideoData>)
> }
>
>
>> On 10 Dec 2015, at 10:14, Jonathan Hise Kaldma via swift-evolution <swift-evolution at swift.org> wrote:
>>
>>
>>>> 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
>> _______________________________________________
>> 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