[Proposal] Enums with stored properties


(J.E. Schotsman) #1

If technically possible I would prefer to directly use types for enum cases.
Reducing a type to a tuple loses the computed properties and methods of the type.
The types must be equatable I suppose.

The current enum rawValues are just indexes or keys which the compiler can autogenerate (like it does for enums without a raw type).
Of course the raw values can be used in some smart way, like for sorting or grouping cases, but this can all be done with general types - and better at that.

So basically you have a struct type and an enum which is just a set of static lets of the struct type.
struct MyStruct {}
enum MyEnum: MyStruct
  {
  case myStruct1
  case myStruct2
  ...
  }

MyStruct need not be created specifically for the enum; it might be useful on its own.
MyEnum can have additional computed properties and methods which are needed for the enumerated values only.

The cases can be accessed like MyStruct instances. No need for .rawValue except in the case of primitive types. Even there there is room for sugar (if a variable is already known to be of type Int we can assign an enum:Int case to it with implied .rawValue).

Jan E.

···

On 12 Oct 2016, at 09:41,Mateusz Malczak 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) #2

I agree, we dont event have to add a new language syntax to get this
feature. Using structs as rawTypes would do the trick but

1. it should be possible to use struct initializer to define enum cases
struct MyStruct {
var width: Int
var height: Int
init(width: Int, height: Int) { ... }
}

enum MyEnum: MyStruct
{
case myStructCase1(width: 30, height: 30)
case myStructCase2(width: 60, height: 60)
...
}

2. calling .rawVaue should not be required in such case to access
stored properties

let e = MyEnum.myStructCase1
let width = e.width // instead of e.rawValue.width

Immutability of all properties in enum struct type is already
implemented in Swift.
At the same time .rawValue stays as it is for primitive types.

···

--

Mateusz Malczak

+-------------------------------

2016-10-12 13:02 GMT+02:00 J.E. Schotsman via swift-evolution <swift-evolution@swift.org>:

On 12 Oct 2016, at 09:41,Mateusz Malczak 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.

If technically possible I would prefer to directly use types for enum cases.
Reducing a type to a tuple loses the computed properties and methods of the
type.
The types must be equatable I suppose.

The current enum rawValues are just indexes or keys which the compiler can
autogenerate (like it does for enums without a raw type).
Of course the raw values can be used in some smart way, like for sorting or
grouping cases, but this can all be done with general types - and better at
that.

So basically you have a struct type and an enum which is just a set of
static lets of the struct type.
struct MyStruct {}
enum MyEnum: MyStruct
{
case myStruct1
case myStruct2
...
}

MyStruct need not be created specifically for the enum; it might be useful
on its own.
MyEnum can have additional computed properties and methods which are needed
for the enumerated values only.

The cases can be accessed like MyStruct instances. No need for .rawValue
except in the case of primitive types. Even there there is room for sugar
(if a variable is already known to be of type Int we can assign an enum:Int
case to it with implied .rawValue).

Jan E.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Karl) #3

You can already use structs as raw types. You just have to implement the RawRepresentable conformance yourself.

RawRep doesn’t affect the enum’s storage, and the shorthand syntax we’ve got saying “case a = 42” and so on is just for the compiler to synthesise a couple of switch statements. The only reason the type needs to be a string/integer literal in that case is so that we can check uniqueness and solve the most common case. If you write your own implementation, you can handle the more nuanced stuff there.

I don’t think there are any restrictions at all on RawRepresentable.RawType (not even Comparable). It can be anything you like.

Karl

···

On 12 Oct 2016, at 13:22, Mateusz Malczak via swift-evolution <swift-evolution@swift.org> wrote:

I agree, we dont event have to add a new language syntax to get this
feature. Using structs as rawTypes would do the trick but

1. it should be possible to use struct initializer to define enum cases
struct MyStruct {
var width: Int
var height: Int
init(width: Int, height: Int) { ... }
}

enum MyEnum: MyStruct
{
case myStructCase1(width: 30, height: 30)
case myStructCase2(width: 60, height: 60)
...
}

2. calling .rawVaue should not be required in such case to access
stored properties

let e = MyEnum.myStructCase1
let width = e.width // instead of e.rawValue.width

Immutability of all properties in enum struct type is already
implemented in Swift.
At the same time .rawValue stays as it is for primitive types.

--
> Mateusz Malczak
+-------------------------------

2016-10-12 13:02 GMT+02:00 J.E. Schotsman via swift-evolution
<swift-evolution@swift.org>:

On 12 Oct 2016, at 09:41,Mateusz Malczak 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.

If technically possible I would prefer to directly use types for enum cases.
Reducing a type to a tuple loses the computed properties and methods of the
type.
The types must be equatable I suppose.

The current enum rawValues are just indexes or keys which the compiler can
autogenerate (like it does for enums without a raw type).
Of course the raw values can be used in some smart way, like for sorting or
grouping cases, but this can all be done with general types - and better at
that.

So basically you have a struct type and an enum which is just a set of
static lets of the struct type.
struct MyStruct {}
enum MyEnum: MyStruct
{
case myStruct1
case myStruct2
...
}

MyStruct need not be created specifically for the enum; it might be useful
on its own.
MyEnum can have additional computed properties and methods which are needed
for the enumerated values only.

The cases can be accessed like MyStruct instances. No need for .rawValue
except in the case of primitive types. Even there there is room for sugar
(if a variable is already known to be of type Int we can assign an enum:Int
case to it with implied .rawValue).

Jan E.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


#4

I think your second point is quite interesting!

We should consider expanding this so that we can get any associated value:

// from the Swift book
enum Barcode {
    case upc(Int, Int, Int, Int)
    case qrCode(String)
}

let code = Barcode.upc(9,2,3,4)
if let upcCode = code.upc {
    // upcCode: (Int, Int, Int, Int)
    upcCode.0 // 9 : Int
}
// direct access
code.upc?.0 // 9 : Int?

This would also increase performance if the following example is not optimized:

enum Term {
    case sum([Term])
    case number(Double)
}

var term = Term.sum([..., ..., ...........])
// appending an element to the array
if var .sum(array) = term {
    // in the worst case the whole array will be copied
    array.insert(.number(1.0) at: 0)
    term = .sum(array)
} else {
    fatalError()
}

// in contrast the proposed version
// here you are sure that the array won't be copied
term.sum!.insert(.number(1.0), at: 0)

I don't know wether this impacts ABI so I would defer this idea if not.

Best regards
Maximilian

···

Am 12.10.2016 um 13:22 schrieb Mateusz Malczak via swift-evolution <swift-evolution@swift.org>:

I agree, we dont event have to add a new language syntax to get this
feature. Using structs as rawTypes would do the trick but

1. it should be possible to use struct initializer to define enum cases
struct MyStruct {
var width: Int
var height: Int
init(width: Int, height: Int) { ... }
}

enum MyEnum: MyStruct
{
case myStructCase1(width: 30, height: 30)
case myStructCase2(width: 60, height: 60)
...
}

2. calling .rawVaue should not be required in such case to access
stored properties

let e = MyEnum.myStructCase1
let width = e.width // instead of e.rawValue.width

Immutability of all properties in enum struct type is already
implemented in Swift.
At the same time .rawValue stays as it is for primitive types.

--
> Mateusz Malczak
+-------------------------------

2016-10-12 13:02 GMT+02:00 J.E. Schotsman via swift-evolution
<swift-evolution@swift.org>:

On 12 Oct 2016, at 09:41,Mateusz Malczak 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.

If technically possible I would prefer to directly use types for enum cases.
Reducing a type to a tuple loses the computed properties and methods of the
type.
The types must be equatable I suppose.

The current enum rawValues are just indexes or keys which the compiler can
autogenerate (like it does for enums without a raw type).
Of course the raw values can be used in some smart way, like for sorting or
grouping cases, but this can all be done with general types - and better at
that.

So basically you have a struct type and an enum which is just a set of
static lets of the struct type.
struct MyStruct {}
enum MyEnum: MyStruct
{
case myStruct1
case myStruct2
...
}

MyStruct need not be created specifically for the enum; it might be useful
on its own.
MyEnum can have additional computed properties and methods which are needed
for the enumerated values only.

The cases can be accessed like MyStruct instances. No need for .rawValue
except in the case of primitive types. Even there there is room for sugar
(if a variable is already known to be of type Int we can assign an enum:Int
case to it with implied .rawValue).

Jan E.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Kenny Leung) #5

I’ve wondered this for a while now. Why must enums implement RawRepresentable?

-Kenny

···

On Oct 12, 2016, at 4:37 AM, Karl via swift-evolution <swift-evolution@swift.org> wrote:

You can already use structs as raw types. You just have to implement the RawRepresentable conformance yourself.

RawRep doesn’t affect the enum’s storage, and the shorthand syntax we’ve got saying “case a = 42” and so on is just for the compiler to synthesise a couple of switch statements. The only reason the type needs to be a string/integer literal in that case is so that we can check uniqueness and solve the most common case. If you write your own implementation, you can handle the more nuanced stuff there.

I don’t think there are any restrictions at all on RawRepresentable.RawType (not even Comparable). It can be anything you like.

Karl

On 12 Oct 2016, at 13:22, Mateusz Malczak via swift-evolution <swift-evolution@swift.org> wrote:

I agree, we dont event have to add a new language syntax to get this
feature. Using structs as rawTypes would do the trick but

1. it should be possible to use struct initializer to define enum cases
struct MyStruct {
var width: Int
var height: Int
init(width: Int, height: Int) { ... }
}

enum MyEnum: MyStruct
{
case myStructCase1(width: 30, height: 30)
case myStructCase2(width: 60, height: 60)
...
}

2. calling .rawVaue should not be required in such case to access
stored properties

let e = MyEnum.myStructCase1
let width = e.width // instead of e.rawValue.width

Immutability of all properties in enum struct type is already
implemented in Swift.
At the same time .rawValue stays as it is for primitive types.

--
> Mateusz Malczak
+-------------------------------

2016-10-12 13:02 GMT+02:00 J.E. Schotsman via swift-evolution
<swift-evolution@swift.org>:

On 12 Oct 2016, at 09:41,Mateusz Malczak 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.

If technically possible I would prefer to directly use types for enum cases.
Reducing a type to a tuple loses the computed properties and methods of the
type.
The types must be equatable I suppose.

The current enum rawValues are just indexes or keys which the compiler can
autogenerate (like it does for enums without a raw type).
Of course the raw values can be used in some smart way, like for sorting or
grouping cases, but this can all be done with general types - and better at
that.

So basically you have a struct type and an enum which is just a set of
static lets of the struct type.
struct MyStruct {}
enum MyEnum: MyStruct
{
case myStruct1
case myStruct2
...
}

MyStruct need not be created specifically for the enum; it might be useful
on its own.
MyEnum can have additional computed properties and methods which are needed
for the enumerated values only.

The cases can be accessed like MyStruct instances. No need for .rawValue
except in the case of primitive types. Even there there is room for sugar
(if a variable is already known to be of type Int we can assign an enum:Int
case to it with implied .rawValue).

Jan E.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution