[Proposal] Enums with stored properties


(Mateusz Malczak) #1

Hi all,
I would like to know you opinion on one feature I feel would be a real
'nice to have' extension to currently available enumeration type. Which is
an enumeration type with stored properties. It is sometimes useful to store
some extra informations along with enumeration cases. Idea here is to add
possibility to define an enumeration type with stored, immutable,
properties, defined at compile time for all cases. In opposition to
currently available associated values, stored properties should be constant
values stored as a part of enumeration case. Proposed feature would be
treated as a new feature along the associated values and raw values.

Please take a look at an example to illustrate this:

enum Format {
    case SMALL(30, 30)
    case MEDIUM(60, 60)
    case LARGE(120, 120)
    var width: Double
    var height: Double
    init(width: Double, height: Double) {
        self.width = width
        self.height = height
    }
}

Similar feature is currently available for example in Java (
http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html).

Currently there are at least tree ways to solve this limitation.

1. use enumeration type with custom struct as a rawValue cons:
a lot of additional code to define structs and implement
`ExpressibleByStringLiteral`
not really possible for more complex types, where a complex string parser
would be required

example:

struct FormatStruct: ExpressibleByStringLiteral, Equatable {
    var width: Int = 0
    var height: Int = 0
    public init(width: Int, height: Int) {
        self.width = width
        self.height = height
    }
    public init(stringLiteral value: String) {
        let set = CharacterSet(charactersIn: "x")
        let values = value.components(separatedBy: set)
        if let width = Int(values[0]), let height = Int(values[1]) {
            self.init(width: width, height: height)
        } else {
            self.init(width: 0, height: 0)
        }
    }
    init(extendedGraphemeClusterLiteral value: String){
        self.init(stringLiteral: value)
    }
    init(unicodeScalarLiteral value: String) {
        self.init(stringLiteral: value)
    }
    static func ==(lhs: FormatStruct, rhs: FormatStruct) -> Bool {
        return (lhs.width == rhs.width) && (lhs.height == rhs.height)
    }
    static let A = FormatStruct(width: 30, height: 30)
}
enum Format: FormatStruct {
    case SMALL = "30x30"
    case MEDIUM = "60x60"
    case LARGE = "120x120"
    var width: Int {
        return rawValue.width
    }
    var height: Int {
        return rawValue.height
    }
}

2. static struct values to mimic enumeration type
cons:
enum should be used to define a closed set of possible values

example:

struct Format: ExpressibleByStringLiteral, Equatable {
    var width: Int = 0
    var height: Int = 0
    public init(width: Int, height: Int) {
        self.width = width
        self.height = height
    }
    static let SMALL = FormatStruct(width: 30, height: 30)
    static let MEDIUM = FormatStruct(width: 60, height: 60)
    static let LARGE = FormatStruct(width: 120, height: 120)
}

3. define enum with getters
cons:
additional, repeated `switch` clauses in getters

example:

enum Format2 { case SMALL case MEDIUM case LARGE var width: Int { switch
self { case .SMALL: return 30 case .MEDIUM: return 60 case .LARGE: return
120 } } var height: Int { switch self { case .SMALL: return 30 case
.MEDIUM: return 60 case .LARGE: return 120 } } }

What is your opinion on this feature? Or maybe that was not implemented for
some reason - if so can I get an few word of explaination what was the
motivation for not adding this to the language?

best regards

···

--

Mateusz Malczak


(Tim Vermeulen) #2

This is precisely what a struct is for, why would you want to be able to do this with enums instead?

···

Hi all,
I would like to know you opinion on one feature I feel would be a real 'nice to have' extension to currently available enumeration type. Which is an enumeration type with stored properties. It is sometimes useful to store some extra informations along with enumeration cases. Idea here is to add possibility to define an enumeration type with stored, immutable, properties, defined at compile time for all cases. In opposition to currently available associated values, stored properties should be constant values stored as a part of enumeration case. Proposed feature would be treated as a new feature along the associated values and raw values.

Please take a look at an example to illustrate this:

enum Format {
case SMALL(30, 30)
case MEDIUM(60, 60)
case LARGE(120, 120)
var width: Double
var height: Double
init(width: Double, height: Double) {
self.width = width
self.height = height
}
}

Similar feature is currently available for example in Java (http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html).

Currently there are at least tree ways to solve this limitation.

1. use enumeration type with custom struct as a rawValue cons:
a lot of additional code to define structs and implement `ExpressibleByStringLiteral`
not really possible for more complex types, where a complex string parser would be required

example:

struct FormatStruct: ExpressibleByStringLiteral, Equatable {
var width: Int = 0
var height: Int = 0
public init(width: Int, height: Int) {
self.width = width
self.height = height
}
public init(stringLiteral value: String) {
let set = CharacterSet(charactersIn: "x")
let values = value.components(separatedBy: set)
if let width = Int(values[0]), let height = Int(values[1]) {
self.init(width: width, height: height)
} else {
self.init(width: 0, height: 0)
}
}
init(extendedGraphemeClusterLiteral value: String){
self.init(stringLiteral: value)
}
init(unicodeScalarLiteral value: String) {
self.init(stringLiteral: value)
}
static func ==(lhs: FormatStruct, rhs: FormatStruct) ->Bool {
return (lhs.width == rhs.width)&&(lhs.height == rhs.height)
}
static let A = FormatStruct(width: 30, height: 30)
}
enum Format: FormatStruct {
case SMALL = "30x30"
case MEDIUM = "60x60"
case LARGE = "120x120"
var width: Int {
return rawValue.width
}
var height: Int {
return rawValue.height
}
}

2. static struct values to mimic enumeration type
cons:
enum should be used to define a closed set of possible values

example:

struct Format: ExpressibleByStringLiteral, Equatable {
var width: Int = 0
var height: Int = 0
public init(width: Int, height: Int) {
self.width = width
self.height = height
}
static let SMALL = FormatStruct(width: 30, height: 30)
static let MEDIUM = FormatStruct(width: 60, height: 60)
static let LARGE = FormatStruct(width: 120, height: 120)
}

3. define enum with getters
cons:
additional, repeated `switch` clauses in getters

example:

enum Format2 { case SMALL case MEDIUM case LARGE var width: Int { switch self { case .SMALL: return 30 case .MEDIUM: return 60 case .LARGE: return 120 } } var height: Int { switch self { case .SMALL: return 30 case .MEDIUM: return 60 case .LARGE: return 120 } } }

What is your opinion on this feature? Or maybe that was not implemented for some reason - if so can I get an few word of explaination what was the motivation for not adding this to the language?

best regards
--
> Mateusz Malczak_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Mateusz Malczak) #3

I agree, you can achieve similar result using structs (as shown in my
example 2). But it feels more natural to define it using an
enumeration type. Enumeration defines a type with well defined set of
possible values. Sometimes where are additional informations liked
with enumeration cases (like in example). Using structs for this is
more like a walk-around because you are using an open type to mimic a
closed set of possible value. What do you think about that?

···

2016-10-09 0:29 GMT+02:00 Tim Vermeulen <tvermeulen@me.com>:

This is precisely what a struct is for, why would you want to be able to do this with enums instead?

Hi all,
I would like to know you opinion on one feature I feel would be a real 'nice to have' extension to currently available enumeration type. Which is an enumeration type with stored properties. It is sometimes useful to store some extra informations along with enumeration cases. Idea here is to add possibility to define an enumeration type with stored, immutable, properties, defined at compile time for all cases. In opposition to currently available associated values, stored properties should be constant values stored as a part of enumeration case. Proposed feature would be treated as a new feature along the associated values and raw values.

Please take a look at an example to illustrate this:

enum Format {
case SMALL(30, 30)
case MEDIUM(60, 60)
case LARGE(120, 120)
var width: Double
var height: Double
init(width: Double, height: Double) {
self.width = width
self.height = height
}
}

Similar feature is currently available for example in Java (http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html).

Currently there are at least tree ways to solve this limitation.

1. use enumeration type with custom struct as a rawValue cons:
a lot of additional code to define structs and implement `ExpressibleByStringLiteral`
not really possible for more complex types, where a complex string parser would be required

example:

struct FormatStruct: ExpressibleByStringLiteral, Equatable {
var width: Int = 0
var height: Int = 0
public init(width: Int, height: Int) {
self.width = width
self.height = height
}
public init(stringLiteral value: String) {
let set = CharacterSet(charactersIn: "x")
let values = value.components(separatedBy: set)
if let width = Int(values[0]), let height = Int(values[1]) {
self.init(width: width, height: height)
} else {
self.init(width: 0, height: 0)
}
}
init(extendedGraphemeClusterLiteral value: String){
self.init(stringLiteral: value)
}
init(unicodeScalarLiteral value: String) {
self.init(stringLiteral: value)
}
static func ==(lhs: FormatStruct, rhs: FormatStruct) ->Bool {
return (lhs.width == rhs.width)&&(lhs.height == rhs.height)
}
static let A = FormatStruct(width: 30, height: 30)
}
enum Format: FormatStruct {
case SMALL = "30x30"
case MEDIUM = "60x60"
case LARGE = "120x120"
var width: Int {
return rawValue.width
}
var height: Int {
return rawValue.height
}
}

2. static struct values to mimic enumeration type
cons:
enum should be used to define a closed set of possible values

example:

struct Format: ExpressibleByStringLiteral, Equatable {
var width: Int = 0
var height: Int = 0
public init(width: Int, height: Int) {
self.width = width
self.height = height
}
static let SMALL = FormatStruct(width: 30, height: 30)
static let MEDIUM = FormatStruct(width: 60, height: 60)
static let LARGE = FormatStruct(width: 120, height: 120)
}

3. define enum with getters
cons:
additional, repeated `switch` clauses in getters

example:

enum Format2 { case SMALL case MEDIUM case LARGE var width: Int { switch self { case .SMALL: return 30 case .MEDIUM: return 60 case .LARGE: return 120 } } var height: Int { switch self { case .SMALL: return 30 case .MEDIUM: return 60 case .LARGE: return 120 } } }

What is your opinion on this feature? Or maybe that was not implemented for some reason - if so can I get an few word of explaination what was the motivation for not adding this to the language?

best regards
--
> Mateusz Malczak_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Robert Widmann) #4

I’ve started doing this to try and mimic “Smart Constructors” in Haskell and I think it works quite well.

struct Format {
  enum FormatBacking {
    case SMALL(Int, Int)
    case MEDIUM(Int, Int)
    case LARGE(Int, Int)
  }
  private let unFormat : FormatBacking

  static var Small : Format {
    return Format(unFormat: .SMALL(30, 30))
  }

  static var Medium : Format {
    return Format(unFormat: .MEDIUM(60, 60))
  }

  static var Large : Format {
    return Format(unFormat: .LARGE(120, 120))
  }

  var width : Int {
    switch self.unFormat {
    case let .SMALL(w, _):
      return w
    case let .MEDIUM(w, _):
      return w
    case let .LARGE(w, _):
      return w
    }
  }

  var height : Int {
    switch self.unFormat {
    case let .SMALL(_, h):
      return h
    case let .MEDIUM(_, h):
      return h
    case let .LARGE(_, h):
      return h
    }
  }
}

Yeah, you’re still subject the switching stuff you mentioned before, but I don’t think this is a whole lot of code. Java’s constants are convenient but they are an oddly structural feature in a particularly nominal language which makes it not scale particularly cleanly.

~Robert Widmann

···

On Oct 8, 2016, at 6:50 PM, Mateusz Malczak via swift-evolution <swift-evolution@swift.org> wrote:

I agree, you can achieve similar result using structs (as shown in my
example 2). But it feels more natural to define it using an
enumeration type. Enumeration defines a type with well defined set of
possible values. Sometimes where are additional informations liked
with enumeration cases (like in example). Using structs for this is
more like a walk-around because you are using an open type to mimic a
closed set of possible value. What do you think about that?

2016-10-09 0:29 GMT+02:00 Tim Vermeulen <tvermeulen@me.com>:

This is precisely what a struct is for, why would you want to be able to do this with enums instead?

Hi all,
I would like to know you opinion on one feature I feel would be a real 'nice to have' extension to currently available enumeration type. Which is an enumeration type with stored properties. It is sometimes useful to store some extra informations along with enumeration cases. Idea here is to add possibility to define an enumeration type with stored, immutable, properties, defined at compile time for all cases. In opposition to currently available associated values, stored properties should be constant values stored as a part of enumeration case. Proposed feature would be treated as a new feature along the associated values and raw values.

Please take a look at an example to illustrate this:

enum Format {
case SMALL(30, 30)
case MEDIUM(60, 60)
case LARGE(120, 120)
var width: Double
var height: Double
init(width: Double, height: Double) {
self.width = width
self.height = height
}
}

Similar feature is currently available for example in Java (http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html).

Currently there are at least tree ways to solve this limitation.

1. use enumeration type with custom struct as a rawValue cons:
a lot of additional code to define structs and implement `ExpressibleByStringLiteral`
not really possible for more complex types, where a complex string parser would be required

example:

struct FormatStruct: ExpressibleByStringLiteral, Equatable {
var width: Int = 0
var height: Int = 0
public init(width: Int, height: Int) {
self.width = width
self.height = height
}
public init(stringLiteral value: String) {
let set = CharacterSet(charactersIn: "x")
let values = value.components(separatedBy: set)
if let width = Int(values[0]), let height = Int(values[1]) {
self.init(width: width, height: height)
} else {
self.init(width: 0, height: 0)
}
}
init(extendedGraphemeClusterLiteral value: String){
self.init(stringLiteral: value)
}
init(unicodeScalarLiteral value: String) {
self.init(stringLiteral: value)
}
static func ==(lhs: FormatStruct, rhs: FormatStruct) ->Bool {
return (lhs.width == rhs.width)&&(lhs.height == rhs.height)
}
static let A = FormatStruct(width: 30, height: 30)
}
enum Format: FormatStruct {
case SMALL = "30x30"
case MEDIUM = "60x60"
case LARGE = "120x120"
var width: Int {
return rawValue.width
}
var height: Int {
return rawValue.height
}
}

2. static struct values to mimic enumeration type
cons:
enum should be used to define a closed set of possible values

example:

struct Format: ExpressibleByStringLiteral, Equatable {
var width: Int = 0
var height: Int = 0
public init(width: Int, height: Int) {
self.width = width
self.height = height
}
static let SMALL = FormatStruct(width: 30, height: 30)
static let MEDIUM = FormatStruct(width: 60, height: 60)
static let LARGE = FormatStruct(width: 120, height: 120)
}

3. define enum with getters
cons:
additional, repeated `switch` clauses in getters

example:

enum Format2 { case SMALL case MEDIUM case LARGE var width: Int { switch self { case .SMALL: return 30 case .MEDIUM: return 60 case .LARGE: return 120 } } var height: Int { switch self { case .SMALL: return 30 case .MEDIUM: return 60 case .LARGE: return 120 } } }

What is your opinion on this feature? Or maybe that was not implemented for some reason - if so can I get an few word of explaination what was the motivation for not adding this to the language?

best regards
--
> Mateusz Malczak_______________________________________________
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


(Jay) #5

Mateusz,

To me, "Enumeration defines a type with well defined set of possible
values" seems to contradict the idea of having properties that can have
different values. What could you do with this special enum - what would the
code that uses it look like?

···

On Sun, 9 Oct 2016 at 04:56 Robert Widmann via swift-evolution < swift-evolution@swift.org> wrote:

I’ve started doing this to try and mimic “Smart Constructors” in Haskell
and I think it works quite well.

struct Format {
  enum FormatBacking {
    case SMALL(Int, Int)
    case MEDIUM(Int, Int)
    case LARGE(Int, Int)
  }
  private let unFormat : FormatBacking

  static var Small : Format {
    return Format(unFormat: .SMALL(30, 30))
  }

  static var Medium : Format {
    return Format(unFormat: .MEDIUM(60, 60))
  }

  static var Large : Format {
    return Format(unFormat: .LARGE(120, 120))
  }

  var width : Int {
    switch self.unFormat {
    case let .SMALL(w, _):
      return w
    case let .MEDIUM(w, _):
      return w
    case let .LARGE(w, _):
      return w
    }
  }

  var height : Int {
    switch self.unFormat {
    case let .SMALL(_, h):
      return h
    case let .MEDIUM(_, h):
      return h
    case let .LARGE(_, h):
      return h
    }
  }
}

Yeah, you’re still subject the switching stuff you mentioned before, but I
don’t think this is a whole lot of code. Java’s constants are convenient
but they are an oddly structural feature in a particularly nominal language
which makes it not scale particularly cleanly.

~Robert Widmann

On Oct 8, 2016, at 6:50 PM, Mateusz Malczak via swift-evolution < > swift-evolution@swift.org> wrote:

I agree, you can achieve similar result using structs (as shown in my
example 2). But it feels more natural to define it using an
enumeration type. Enumeration defines a type with well defined set of
possible values. Sometimes where are additional informations liked
with enumeration cases (like in example). Using structs for this is
more like a walk-around because you are using an open type to mimic a
closed set of possible value. What do you think about that?

2016-10-09 0:29 GMT+02:00 Tim Vermeulen <tvermeulen@me.com>:

This is precisely what a struct is for, why would you want to be able to
do this with enums instead?

Hi all,
I would like to know you opinion on one feature I feel would be a real
'nice to have' extension to currently available enumeration type. Which is
an enumeration type with stored properties. It is sometimes useful to store
some extra informations along with enumeration cases. Idea here is to add
possibility to define an enumeration type with stored, immutable,
properties, defined at compile time for all cases. In opposition to
currently available associated values, stored properties should be constant
values stored as a part of enumeration case. Proposed feature would be
treated as a new feature along the associated values and raw values.

Please take a look at an example to illustrate this:

enum Format {
case SMALL(30, 30)
case MEDIUM(60, 60)
case LARGE(120, 120)
var width: Double
var height: Double
init(width: Double, height: Double) {
self.width = width
self.height = height
}
}

Similar feature is currently available for example in Java (
http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html).

Currently there are at least tree ways to solve this limitation.

1. use enumeration type with custom struct as a rawValue cons:
a lot of additional code to define structs and implement
`ExpressibleByStringLiteral`
not really possible for more complex types, where a complex string parser
would be required

example:

struct FormatStruct: ExpressibleByStringLiteral, Equatable {
var width: Int = 0
var height: Int = 0
public init(width: Int, height: Int) {
self.width = width
self.height = height
}
public init(stringLiteral value: String) {
let set = CharacterSet(charactersIn: "x")
let values = value.components(separatedBy: set)
if let width = Int(values[0]), let height = Int(values[1]) {
self.init(width: width, height: height)
} else {
self.init(width: 0, height: 0)
}
}
init(extendedGraphemeClusterLiteral value: String){
self.init(stringLiteral: value)
}
init(unicodeScalarLiteral value: String) {
self.init(stringLiteral: value)
}
static func ==(lhs: FormatStruct, rhs: FormatStruct) ->Bool {
return (lhs.width == rhs.width)&&(lhs.height == rhs.height)
}
static let A = FormatStruct(width: 30, height: 30)
}
enum Format: FormatStruct {
case SMALL = "30x30"
case MEDIUM = "60x60"
case LARGE = "120x120"
var width: Int {
return rawValue.width
}
var height: Int {
return rawValue.height
}
}

2. static struct values to mimic enumeration type
cons:
enum should be used to define a closed set of possible values

example:

struct Format: ExpressibleByStringLiteral, Equatable {
var width: Int = 0
var height: Int = 0
public init(width: Int, height: Int) {
self.width = width
self.height = height
}
static let SMALL = FormatStruct(width: 30, height: 30)
static let MEDIUM = FormatStruct(width: 60, height: 60)
static let LARGE = FormatStruct(width: 120, height: 120)
}

3. define enum with getters
cons:
additional, repeated `switch` clauses in getters

example:

enum Format2 { case SMALL case MEDIUM case LARGE var width: Int { switch
self { case .SMALL: return 30 case .MEDIUM: return 60 case .LARGE: return
120 } } var height: Int { switch self { case .SMALL: return 30 case
.MEDIUM: return 60 case .LARGE: return 120 } } }

What is your opinion on this feature? Or maybe that was not implemented
for some reason - if so can I get an few word of explaination what was the
motivation for not adding this to the language?

best regards
--
> Mateusz Malczak_______________________________________________
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


(Mateusz Malczak) #6

Hi,
Im currently using similar structure in my projects. But every time I
use this kind of code to carry over some extra information with enum
cases I see it as a walk-around for language limitation. Enumeration
type in swift is already powerful with associated values and
rawValues. If you look at it from that perspective you will see that
having stored properties is an extension to rawType usage.

Java’s constants are convenient but they are an oddly structural feature in a particularly nominal language
which makes it not scale particularly cleanly.

why do you think such a feature would not scale cleanly? can you
elaborate a bit more on that sentence please

···

--

Mateusz Malczak

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

mateusz@malczak.info
http://malczak.info

2016-10-09 5:55 GMT+02:00 Robert Widmann <devteam.codafi@gmail.com>:

I’ve started doing this to try and mimic “Smart Constructors” in Haskell and
I think it works quite well.

struct Format {
  enum FormatBacking {
    case SMALL(Int, Int)
    case MEDIUM(Int, Int)
    case LARGE(Int, Int)
  }
  private let unFormat : FormatBacking

  static var Small : Format {
    return Format(unFormat: .SMALL(30, 30))
  }

  static var Medium : Format {
    return Format(unFormat: .MEDIUM(60, 60))
  }

  static var Large : Format {
    return Format(unFormat: .LARGE(120, 120))
  }

  var width : Int {
    switch self.unFormat {
    case let .SMALL(w, _):
      return w
    case let .MEDIUM(w, _):
      return w
    case let .LARGE(w, _):
      return w
    }
  }

  var height : Int {
    switch self.unFormat {
    case let .SMALL(_, h):
      return h
    case let .MEDIUM(_, h):
      return h
    case let .LARGE(_, h):
      return h
    }
  }
}

Yeah, you’re still subject the switching stuff you mentioned before, but I
don’t think this is a whole lot of code. Java’s constants are convenient
but they are an oddly structural feature in a particularly nominal language
which makes it not scale particularly cleanly.

~Robert Widmann

On Oct 8, 2016, at 6:50 PM, Mateusz Malczak via swift-evolution > <swift-evolution@swift.org> wrote:

I agree, you can achieve similar result using structs (as shown in my
example 2). But it feels more natural to define it using an
enumeration type. Enumeration defines a type with well defined set of
possible values. Sometimes where are additional informations liked
with enumeration cases (like in example). Using structs for this is
more like a walk-around because you are using an open type to mimic a
closed set of possible value. What do you think about that?

2016-10-09 0:29 GMT+02:00 Tim Vermeulen <tvermeulen@me.com>:

This is precisely what a struct is for, why would you want to be able to do
this with enums instead?

Hi all,
I would like to know you opinion on one feature I feel would be a real 'nice
to have' extension to currently available enumeration type. Which is an
enumeration type with stored properties. It is sometimes useful to store
some extra informations along with enumeration cases. Idea here is to add
possibility to define an enumeration type with stored, immutable,
properties, defined at compile time for all cases. In opposition to
currently available associated values, stored properties should be constant
values stored as a part of enumeration case. Proposed feature would be
treated as a new feature along the associated values and raw values.

Please take a look at an example to illustrate this:

enum Format {
case SMALL(30, 30)
case MEDIUM(60, 60)
case LARGE(120, 120)
var width: Double
var height: Double
init(width: Double, height: Double) {
self.width = width
self.height = height
}
}

Similar feature is currently available for example in Java
(http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html).

Currently there are at least tree ways to solve this limitation.

1. use enumeration type with custom struct as a rawValue cons:
a lot of additional code to define structs and implement
`ExpressibleByStringLiteral`
not really possible for more complex types, where a complex string parser
would be required

example:

struct FormatStruct: ExpressibleByStringLiteral, Equatable {
var width: Int = 0
var height: Int = 0
public init(width: Int, height: Int) {
self.width = width
self.height = height
}
public init(stringLiteral value: String) {
let set = CharacterSet(charactersIn: "x")
let values = value.components(separatedBy: set)
if let width = Int(values[0]), let height = Int(values[1]) {
self.init(width: width, height: height)
} else {
self.init(width: 0, height: 0)
}
}
init(extendedGraphemeClusterLiteral value: String){
self.init(stringLiteral: value)
}
init(unicodeScalarLiteral value: String) {
self.init(stringLiteral: value)
}
static func ==(lhs: FormatStruct, rhs: FormatStruct) ->Bool {
return (lhs.width == rhs.width)&&(lhs.height == rhs.height)
}
static let A = FormatStruct(width: 30, height: 30)
}
enum Format: FormatStruct {
case SMALL = "30x30"
case MEDIUM = "60x60"
case LARGE = "120x120"
var width: Int {
return rawValue.width
}
var height: Int {
return rawValue.height
}
}

2. static struct values to mimic enumeration type
cons:
enum should be used to define a closed set of possible values

example:

struct Format: ExpressibleByStringLiteral, Equatable {
var width: Int = 0
var height: Int = 0
public init(width: Int, height: Int) {
self.width = width
self.height = height
}
static let SMALL = FormatStruct(width: 30, height: 30)
static let MEDIUM = FormatStruct(width: 60, height: 60)
static let LARGE = FormatStruct(width: 120, height: 120)
}

3. define enum with getters
cons:
additional, repeated `switch` clauses in getters

example:

enum Format2 { case SMALL case MEDIUM case LARGE var width: Int { switch
self { case .SMALL: return 30 case .MEDIUM: return 60 case .LARGE: return
120 } } var height: Int { switch self { case .SMALL: return 30 case .MEDIUM:
return 60 case .LARGE: return 120 } } }

What is your opinion on this feature? Or maybe that was not implemented for
some reason - if so can I get an few word of explaination what was the
motivation for not adding this to the language?

best regards
--
> Mateusz Malczak_______________________________________________
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


(Erica Sadun) #7

I would love to be able to have stored properties in addition to the varying elements.

Now, I end up creating a secondary struct T and doing case a(T, whatever), b(T, whatever), c(T, whatever), etc. where the same associated structure is every case, *or* I end up putting the enum into a struct which means the guiding semantics are the struct and not the enumeration. Both approaches are ugly.

-- E

···

On Oct 9, 2016, at 6:03 PM, Jay Abbott via swift-evolution <swift-evolution@swift.org> wrote:

Mateusz,

To me, "Enumeration defines a type with well defined set of possible values" seems to contradict the idea of having properties that can have different values. What could you do with this special enum - what would the code that uses it look like?

On Sun, 9 Oct 2016 at 04:56 Robert Widmann via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
I’ve started doing this to try and mimic “Smart Constructors” in Haskell and I think it works quite well.

struct Format {
  enum FormatBacking {
    case SMALL(Int, Int)
    case MEDIUM(Int, Int)
    case LARGE(Int, Int)
  }


(David Hart) #8

Perhaps it is a bit ugly, but I don’t know if allowing stored properties on enums is the solution: that looks very ugly to me too.

···

On 10 Oct 2016, at 02:36, Erica Sadun via swift-evolution <swift-evolution@swift.org> wrote:

I would love to be able to have stored properties in addition to the varying elements.

Now, I end up creating a secondary struct T and doing case a(T, whatever), b(T, whatever), c(T, whatever), etc. where the same associated structure is every case, *or* I end up putting the enum into a struct which means the guiding semantics are the struct and not the enumeration. Both approaches are ugly.

-- E

On Oct 9, 2016, at 6:03 PM, Jay Abbott via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Mateusz,

To me, "Enumeration defines a type with well defined set of possible values" seems to contradict the idea of having properties that can have different values. What could you do with this special enum - what would the code that uses it look like?

On Sun, 9 Oct 2016 at 04:56 Robert Widmann via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
I’ve started doing this to try and mimic “Smart Constructors” in Haskell and I think it works quite well.

struct Format {
  enum FormatBacking {
    case SMALL(Int, Int)
    case MEDIUM(Int, Int)
    case LARGE(Int, Int)
  }

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


(Mateusz Malczak) #9

Hi Jay,

To me, "Enumeration defines a type with well defined set of possible values"
seems to contradict the idea of having properties that can have different
values.

I think its more about the way you see enumeration type. In most cases
enum cases just carry over some information. When you need to get that
additional
information you will use switch or rawValue. On one hand we currently
do have an enums with associated values, where you can attach
different values with single enum case. On the other hand we do have
enums with rawType where you can already store some information in
enum cases. Having possibility to store properties would just be an
extension to the rawType case.

What could you do with this special enum - what would the code that
uses it look like?

I don't see it as special type of enums, its more or less the same
case as accessing rawValue property (please look at my examples in
initial mail). You can think of them as enums that are able carry over
some more information than only a RawType value.

Let me once again share a code from initial proposal email :
enum Format {
    case SMALL(30, 30)
    case MEDIUM(60, 60)
    case LARGE(120, 120)
    var width: Double
    var height: Double
    init(width: Double, height: Double) {
        self.width = width
        self.height = height
    }
}

In that example you have an enum carrying over some extra informations.

regards

···

--

Mateusz Malczak

2016-10-10 2:03 GMT+02:00 Jay Abbott <jay@abbott.me.uk>:

Mateusz,

To me, "Enumeration defines a type with well defined set of possible values"
seems to contradict the idea of having properties that can have different
values. What could you do with this special enum - what would the code that
uses it look like?

On Sun, 9 Oct 2016 at 04:56 Robert Widmann via swift-evolution > <swift-evolution@swift.org> wrote:

I’ve started doing this to try and mimic “Smart Constructors” in Haskell
and I think it works quite well.

struct Format {
  enum FormatBacking {
    case SMALL(Int, Int)
    case MEDIUM(Int, Int)
    case LARGE(Int, Int)
  }
  private let unFormat : FormatBacking

  static var Small : Format {
    return Format(unFormat: .SMALL(30, 30))
  }

  static var Medium : Format {
    return Format(unFormat: .MEDIUM(60, 60))
  }

  static var Large : Format {
    return Format(unFormat: .LARGE(120, 120))
  }

  var width : Int {
    switch self.unFormat {
    case let .SMALL(w, _):
      return w
    case let .MEDIUM(w, _):
      return w
    case let .LARGE(w, _):
      return w
    }
  }

  var height : Int {
    switch self.unFormat {
    case let .SMALL(_, h):
      return h
    case let .MEDIUM(_, h):
      return h
    case let .LARGE(_, h):
      return h
    }
  }
}

Yeah, you’re still subject the switching stuff you mentioned before, but I
don’t think this is a whole lot of code. Java’s constants are convenient
but they are an oddly structural feature in a particularly nominal language
which makes it not scale particularly cleanly.

~Robert Widmann

On Oct 8, 2016, at 6:50 PM, Mateusz Malczak via swift-evolution >> <swift-evolution@swift.org> wrote:

I agree, you can achieve similar result using structs (as shown in my
example 2). But it feels more natural to define it using an
enumeration type. Enumeration defines a type with well defined set of
possible values. Sometimes where are additional informations liked
with enumeration cases (like in example). Using structs for this is
more like a walk-around because you are using an open type to mimic a
closed set of possible value. What do you think about that?

2016-10-09 0:29 GMT+02:00 Tim Vermeulen <tvermeulen@me.com>:

This is precisely what a struct is for, why would you want to be able to
do this with enums instead?

Hi all,
I would like to know you opinion on one feature I feel would be a real
'nice to have' extension to currently available enumeration type. Which is
an enumeration type with stored properties. It is sometimes useful to store
some extra informations along with enumeration cases. Idea here is to add
possibility to define an enumeration type with stored, immutable,
properties, defined at compile time for all cases. In opposition to
currently available associated values, stored properties should be constant
values stored as a part of enumeration case. Proposed feature would be
treated as a new feature along the associated values and raw values.

Please take a look at an example to illustrate this:

enum Format {
case SMALL(30, 30)
case MEDIUM(60, 60)
case LARGE(120, 120)
var width: Double
var height: Double
init(width: Double, height: Double) {
self.width = width
self.height = height
}
}

Similar feature is currently available for example in Java
(http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html).

Currently there are at least tree ways to solve this limitation.

1. use enumeration type with custom struct as a rawValue cons:
a lot of additional code to define structs and implement
`ExpressibleByStringLiteral`
not really possible for more complex types, where a complex string parser
would be required

example:

struct FormatStruct: ExpressibleByStringLiteral, Equatable {
var width: Int = 0
var height: Int = 0
public init(width: Int, height: Int) {
self.width = width
self.height = height
}
public init(stringLiteral value: String) {
let set = CharacterSet(charactersIn: "x")
let values = value.components(separatedBy: set)
if let width = Int(values[0]), let height = Int(values[1]) {
self.init(width: width, height: height)
} else {
self.init(width: 0, height: 0)
}
}
init(extendedGraphemeClusterLiteral value: String){
self.init(stringLiteral: value)
}
init(unicodeScalarLiteral value: String) {
self.init(stringLiteral: value)
}
static func ==(lhs: FormatStruct, rhs: FormatStruct) ->Bool {
return (lhs.width == rhs.width)&&(lhs.height == rhs.height)
}
static let A = FormatStruct(width: 30, height: 30)
}
enum Format: FormatStruct {
case SMALL = "30x30"
case MEDIUM = "60x60"
case LARGE = "120x120"
var width: Int {
return rawValue.width
}
var height: Int {
return rawValue.height
}
}

2. static struct values to mimic enumeration type
cons:
enum should be used to define a closed set of possible values

example:

struct Format: ExpressibleByStringLiteral, Equatable {
var width: Int = 0
var height: Int = 0
public init(width: Int, height: Int) {
self.width = width
self.height = height
}
static let SMALL = FormatStruct(width: 30, height: 30)
static let MEDIUM = FormatStruct(width: 60, height: 60)
static let LARGE = FormatStruct(width: 120, height: 120)
}

3. define enum with getters
cons:
additional, repeated `switch` clauses in getters

example:

enum Format2 { case SMALL case MEDIUM case LARGE var width: Int { switch
self { case .SMALL: return 30 case .MEDIUM: return 60 case .LARGE: return
120 } } var height: Int { switch self { case .SMALL: return 30 case .MEDIUM:
return 60 case .LARGE: return 120 } } }

What is your opinion on this feature? Or maybe that was not implemented
for some reason - if so can I get an few word of explaination what was the
motivation for not adding this to the language?

best regards
--
> Mateusz Malczak_______________________________________________
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


(Mateusz Malczak) #10

Hi,

Perhaps it is a bit ugly, but I don’t know if allowing stored properties on
enums is the solution: that looks very ugly to me too.

That may look ugly, but can be very useful, if only you think
rawValue's are useful then you should also agree that stored
properties would be useful :slight_smile:

···

--

Mateusz Malczak

2016-10-10 9:26 GMT+02:00 David Hart via swift-evolution <swift-evolution@swift.org>:

Perhaps it is a bit ugly, but I don’t know if allowing stored properties on
enums is the solution: that looks very ugly to me too.

On 10 Oct 2016, at 02:36, Erica Sadun via swift-evolution > <swift-evolution@swift.org> wrote:

I would love to be able to have stored properties in addition to the varying
elements.

Now, I end up creating a secondary struct T and doing case a(T, whatever),
b(T, whatever), c(T, whatever), etc. where the same associated structure is
every case, *or* I end up putting the enum into a struct which means the
guiding semantics are the struct and not the enumeration. Both approaches
are ugly.

-- E

On Oct 9, 2016, at 6:03 PM, Jay Abbott via swift-evolution > <swift-evolution@swift.org> wrote:

Mateusz,

To me, "Enumeration defines a type with well defined set of possible values"
seems to contradict the idea of having properties that can have different
values. What could you do with this special enum - what would the code that
uses it look like?

On Sun, 9 Oct 2016 at 04:56 Robert Widmann via swift-evolution > <swift-evolution@swift.org> wrote:

I’ve started doing this to try and mimic “Smart Constructors” in Haskell
and I think it works quite well.

struct Format {
  enum FormatBacking {
    case SMALL(Int, Int)
    case MEDIUM(Int, Int)
    case LARGE(Int, Int)
  }

_______________________________________________
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


(Jay) #11

Thanks for the explanation Mateusz, I think I understand. So the enum still
only has 3 cases, SMALL, MEDIUM, and LARGE, but an instance also has some
properties?

So some code to use it might be:
var aFormat = Format.LARGE
aFormat.width = 150 // aFormat is still Format.LARGE - this doesn't change

Is that right?

···

On Mon, 10 Oct 2016 at 09:06 Mateusz Malczak via swift-evolution < swift-evolution@swift.org> wrote:

Hi,
> Perhaps it is a bit ugly, but I don’t know if allowing stored properties
on
> enums is the solution: that looks very ugly to me too.

That may look ugly, but can be very useful, if only you think
rawValue's are useful then you should also agree that stored
properties would be useful :slight_smile:

--
> Mateusz Malczak

2016-10-10 9:26 GMT+02:00 David Hart via swift-evolution
<swift-evolution@swift.org>:
> Perhaps it is a bit ugly, but I don’t know if allowing stored properties
on
> enums is the solution: that looks very ugly to me too.
>
> On 10 Oct 2016, at 02:36, Erica Sadun via swift-evolution > > <swift-evolution@swift.org> wrote:
>
> I would love to be able to have stored properties in addition to the
varying
> elements.
>
> Now, I end up creating a secondary struct T and doing case a(T,
whatever),
> b(T, whatever), c(T, whatever), etc. where the same associated structure
is
> every case, *or* I end up putting the enum into a struct which means the
> guiding semantics are the struct and not the enumeration. Both approaches
> are ugly.
>
> -- E
>
> On Oct 9, 2016, at 6:03 PM, Jay Abbott via swift-evolution > > <swift-evolution@swift.org> wrote:
>
> Mateusz,
>
> To me, "Enumeration defines a type with well defined set of possible
values"
> seems to contradict the idea of having properties that can have different
> values. What could you do with this special enum - what would the code
that
> uses it look like?
>
>
>
> On Sun, 9 Oct 2016 at 04:56 Robert Widmann via swift-evolution > > <swift-evolution@swift.org> wrote:
>>
>> I’ve started doing this to try and mimic “Smart Constructors” in Haskell
>> and I think it works quite well.
>>
>> struct Format {
>> enum FormatBacking {
>> case SMALL(Int, Int)
>> case MEDIUM(Int, Int)
>> case LARGE(Int, Int)
>> }
>
>
> _______________________________________________
> 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


(Mateusz Malczak) #12

I think, I have used quite unfortunate naming, which is a root of an
misunderstanding here. By saying 'enums with stored properties' what I
was really thinking about, was enumeration type with stored constant,
immutable properties (constants). I don't want to duplicate 'struct'
type here, but instead I would like to make it possible to store a
const values in enumeration cases. So going back to my example once
again:

Lest define an enumeration type `Format` with 3 possible cases. Each
case will be able to carry over some additional information - in this
case a pair of numbers (but in fact Any? should be possible)

enum Format {
    case SMALL(30, 30)
    case MEDIUM(60, 60)
    case LARGE(120, 120)
    var width: Double
    var height: Double
    init(width: Double, height: Double) {
        self.width = width
        self.height = height
    }
}

I'm not sure about 'var' clause in that example as it causes all the confusion.

I can access additional info stored in enum case, but it cannot be
modified. Format.SMALL doesn't change, as well as non of its
properties.

// allowed usage
let format = Format.SMALL
let width = format.width // this would be equal to 30 (const value
assigned to 'width' property on enum case .SMALL)

// not allowed usage
let format = Format.SMALL
format.width = 40 // error, stored values are immutable and can not be modified

We get all advantages of enumeration type, and, assuming all cases are
describing the same possible state, we can store some extra
information in each case. This can be called a third enumeration type
feature, right next to associated values and rawType.

···

--

Mateusz Malczak

2016-10-10 13:40 GMT+02:00 Jay Abbott <jay@abbott.me.uk>:

Thanks for the explanation Mateusz, I think I understand. So the enum still
only has 3 cases, SMALL, MEDIUM, and LARGE, but an instance also has some
properties?

So some code to use it might be:
var aFormat = Format.LARGE
aFormat.width = 150 // aFormat is still Format.LARGE - this doesn't change

Is that right?

On Mon, 10 Oct 2016 at 09:06 Mateusz Malczak via swift-evolution > <swift-evolution@swift.org> wrote:

Hi,
> Perhaps it is a bit ugly, but I don’t know if allowing stored properties
> on
> enums is the solution: that looks very ugly to me too.

That may look ugly, but can be very useful, if only you think
rawValue's are useful then you should also agree that stored
properties would be useful :slight_smile:

--
> Mateusz Malczak

2016-10-10 9:26 GMT+02:00 David Hart via swift-evolution
<swift-evolution@swift.org>:
> Perhaps it is a bit ugly, but I don’t know if allowing stored properties
> on
> enums is the solution: that looks very ugly to me too.
>
> On 10 Oct 2016, at 02:36, Erica Sadun via swift-evolution >> > <swift-evolution@swift.org> wrote:
>
> I would love to be able to have stored properties in addition to the
> varying
> elements.
>
> Now, I end up creating a secondary struct T and doing case a(T,
> whatever),
> b(T, whatever), c(T, whatever), etc. where the same associated structure
> is
> every case, *or* I end up putting the enum into a struct which means the
> guiding semantics are the struct and not the enumeration. Both
> approaches
> are ugly.
>
> -- E
>
> On Oct 9, 2016, at 6:03 PM, Jay Abbott via swift-evolution >> > <swift-evolution@swift.org> wrote:
>
> Mateusz,
>
> To me, "Enumeration defines a type with well defined set of possible
> values"
> seems to contradict the idea of having properties that can have
> different
> values. What could you do with this special enum - what would the code
> that
> uses it look like?
>
>
>
> On Sun, 9 Oct 2016 at 04:56 Robert Widmann via swift-evolution >> > <swift-evolution@swift.org> wrote:
>>
>> I’ve started doing this to try and mimic “Smart Constructors” in
>> Haskell
>> and I think it works quite well.
>>
>> struct Format {
>> enum FormatBacking {
>> case SMALL(Int, Int)
>> case MEDIUM(Int, Int)
>> case LARGE(Int, Int)
>> }
>
>
> _______________________________________________
> 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


(Jay) #13

Is this what you're trying to achieve, only using a nicer syntax to
represent it?
http://swiftlang.ng.bluemix.net/#/repl/57fb8ac27365890cc848f831

···

On Mon, 10 Oct 2016 at 13:04 Mateusz Malczak <mateusz@malczak.info> wrote:

I think, I have used quite unfortunate naming, which is a root of an
misunderstanding here. By saying 'enums with stored properties' what I
was really thinking about, was enumeration type with stored constant,
immutable properties (constants). I don't want to duplicate 'struct'
type here, but instead I would like to make it possible to store a
const values in enumeration cases. So going back to my example once
again:

Lest define an enumeration type `Format` with 3 possible cases. Each
case will be able to carry over some additional information - in this
case a pair of numbers (but in fact Any? should be possible)

enum Format {
    case SMALL(30, 30)
    case MEDIUM(60, 60)
    case LARGE(120, 120)
    var width: Double
    var height: Double
    init(width: Double, height: Double) {
        self.width = width
        self.height = height
    }
}

I'm not sure about 'var' clause in that example as it causes all the
confusion.

I can access additional info stored in enum case, but it cannot be
modified. Format.SMALL doesn't change, as well as non of its
properties.

// allowed usage
let format = Format.SMALL
let width = format.width // this would be equal to 30 (const value
assigned to 'width' property on enum case .SMALL)

// not allowed usage
let format = Format.SMALL
format.width = 40 // error, stored values are immutable and can not be
modified

We get all advantages of enumeration type, and, assuming all cases are
describing the same possible state, we can store some extra
information in each case. This can be called a third enumeration type
feature, right next to associated values and rawType.

--
> Mateusz Malczak

2016-10-10 13:40 GMT+02:00 Jay Abbott <jay@abbott.me.uk>:
> Thanks for the explanation Mateusz, I think I understand. So the enum
still
> only has 3 cases, SMALL, MEDIUM, and LARGE, but an instance also has some
> properties?
>
> So some code to use it might be:
> var aFormat = Format.LARGE
> aFormat.width = 150 // aFormat is still Format.LARGE - this doesn't
change
>
> Is that right?
>
> On Mon, 10 Oct 2016 at 09:06 Mateusz Malczak via swift-evolution > > <swift-evolution@swift.org> wrote:
>>
>> Hi,
>> > Perhaps it is a bit ugly, but I don’t know if allowing stored
properties
>> > on
>> > enums is the solution: that looks very ugly to me too.
>>
>> That may look ugly, but can be very useful, if only you think
>> rawValue's are useful then you should also agree that stored
>> properties would be useful :slight_smile:
>>
>> --
>> > Mateusz Malczak
>>
>>
>> 2016-10-10 9:26 GMT+02:00 David Hart via swift-evolution
>> <swift-evolution@swift.org>:
>> > Perhaps it is a bit ugly, but I don’t know if allowing stored
properties
>> > on
>> > enums is the solution: that looks very ugly to me too.
>> >
>> > On 10 Oct 2016, at 02:36, Erica Sadun via swift-evolution > >> > <swift-evolution@swift.org> wrote:
>> >
>> > I would love to be able to have stored properties in addition to the
>> > varying
>> > elements.
>> >
>> > Now, I end up creating a secondary struct T and doing case a(T,
>> > whatever),
>> > b(T, whatever), c(T, whatever), etc. where the same associated
structure
>> > is
>> > every case, *or* I end up putting the enum into a struct which means
the
>> > guiding semantics are the struct and not the enumeration. Both
>> > approaches
>> > are ugly.
>> >
>> > -- E
>> >
>> > On Oct 9, 2016, at 6:03 PM, Jay Abbott via swift-evolution > >> > <swift-evolution@swift.org> wrote:
>> >
>> > Mateusz,
>> >
>> > To me, "Enumeration defines a type with well defined set of possible
>> > values"
>> > seems to contradict the idea of having properties that can have
>> > different
>> > values. What could you do with this special enum - what would the code
>> > that
>> > uses it look like?
>> >
>> >
>> >
>> > On Sun, 9 Oct 2016 at 04:56 Robert Widmann via swift-evolution > >> > <swift-evolution@swift.org> wrote:
>> >>
>> >> I’ve started doing this to try and mimic “Smart Constructors” in
>> >> Haskell
>> >> and I think it works quite well.
>> >>
>> >> struct Format {
>> >> enum FormatBacking {
>> >> case SMALL(Int, Int)
>> >> case MEDIUM(Int, Int)
>> >> case LARGE(Int, Int)
>> >> }
>> >
>> >
>> > _______________________________________________
>> > 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


(Haravikk) #14

Can't this problem most easily be solved by a raw value? Like so:

enum Format : Int {
    case small = 30
    case medium = 60
    case large = 120

    var width:Int { return self.rawValue }
    var height:Int { return self.rawValue }
}

Granted this becomes more complex if you want to specify widths and heights that do not match, as you can't currently specify a tuple as the raw value, but if you could then that seems like it would be a better solution to this problem surely?

···

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

I think, I have used quite unfortunate naming, which is a root of an
misunderstanding here. By saying 'enums with stored properties' what I
was really thinking about, was enumeration type with stored constant,
immutable properties (constants). I don't want to duplicate 'struct'
type here, but instead I would like to make it possible to store a
const values in enumeration cases. So going back to my example once
again:

Lest define an enumeration type `Format` with 3 possible cases. Each
case will be able to carry over some additional information - in this
case a pair of numbers (but in fact Any? should be possible)

enum Format {
   case SMALL(30, 30)
   case MEDIUM(60, 60)
   case LARGE(120, 120)
   var width: Double
   var height: Double
   init(width: Double, height: Double) {
       self.width = width
       self.height = height
   }
}

I'm not sure about 'var' clause in that example as it causes all the confusion.

I can access additional info stored in enum case, but it cannot be
modified. Format.SMALL doesn't change, as well as non of its
properties.

// allowed usage
let format = Format.SMALL
let width = format.width // this would be equal to 30 (const value
assigned to 'width' property on enum case .SMALL)

// not allowed usage
let format = Format.SMALL
format.width = 40 // error, stored values are immutable and can not be modified

We get all advantages of enumeration type, and, assuming all cases are
describing the same possible state, we can store some extra
information in each case. This can be called a third enumeration type
feature, right next to associated values and rawType.

--
> Mateusz Malczak


(Rien) #15

Maybe I am missing something, but is this what you want?

class Size {
   let width: Double
   let height: Double
   init(width: Double, height: Double) { … }
}

enum Format {
  case SMALL
  case MEDIUM
        case LARGE
  var size: Size {
             switch self {
                   case SMALL: return Size(width: 100, height: 100)
                   case MEDIUM: …
                   ….
             }
        }
}

let format = Format.SMALL
let width = format.size.width

format.size.width = 50 // error, immutable

···

On 10 Oct 2016, at 14:35, Jay Abbott via swift-evolution <swift-evolution@swift.org> wrote:

Is this what you're trying to achieve, only using a nicer syntax to represent it?
http://swiftlang.ng.bluemix.net/#/repl/57fb8ac27365890cc848f831

On Mon, 10 Oct 2016 at 13:04 Mateusz Malczak <mateusz@malczak.info> wrote:
I think, I have used quite unfortunate naming, which is a root of an
misunderstanding here. By saying 'enums with stored properties' what I
was really thinking about, was enumeration type with stored constant,
immutable properties (constants). I don't want to duplicate 'struct'
type here, but instead I would like to make it possible to store a
const values in enumeration cases. So going back to my example once
again:

Lest define an enumeration type `Format` with 3 possible cases. Each
case will be able to carry over some additional information - in this
case a pair of numbers (but in fact Any? should be possible)

enum Format {
    case SMALL(30, 30)
    case MEDIUM(60, 60)
    case LARGE(120, 120)
    var width: Double
    var height: Double
    init(width: Double, height: Double) {
        self.width = width
        self.height = height
    }
}

I'm not sure about 'var' clause in that example as it causes all the confusion.

I can access additional info stored in enum case, but it cannot be
modified. Format.SMALL doesn't change, as well as non of its
properties.

// allowed usage
let format = Format.SMALL
let width = format.width // this would be equal to 30 (const value
assigned to 'width' property on enum case .SMALL)

// not allowed usage
let format = Format.SMALL
format.width = 40 // error, stored values are immutable and can not be modified

We get all advantages of enumeration type, and, assuming all cases are
describing the same possible state, we can store some extra
information in each case. This can be called a third enumeration type
feature, right next to associated values and rawType.

--
> Mateusz Malczak

2016-10-10 13:40 GMT+02:00 Jay Abbott <jay@abbott.me.uk>:
> Thanks for the explanation Mateusz, I think I understand. So the enum still
> only has 3 cases, SMALL, MEDIUM, and LARGE, but an instance also has some
> properties?
>
> So some code to use it might be:
> var aFormat = Format.LARGE
> aFormat.width = 150 // aFormat is still Format.LARGE - this doesn't change
>
> Is that right?
>
> On Mon, 10 Oct 2016 at 09:06 Mateusz Malczak via swift-evolution > > <swift-evolution@swift.org> wrote:
>>
>> Hi,
>> > Perhaps it is a bit ugly, but I don’t know if allowing stored properties
>> > on
>> > enums is the solution: that looks very ugly to me too.
>>
>> That may look ugly, but can be very useful, if only you think
>> rawValue's are useful then you should also agree that stored
>> properties would be useful :slight_smile:
>>
>> --
>> > Mateusz Malczak
>>
>>
>> 2016-10-10 9:26 GMT+02:00 David Hart via swift-evolution
>> <swift-evolution@swift.org>:
>> > Perhaps it is a bit ugly, but I don’t know if allowing stored properties
>> > on
>> > enums is the solution: that looks very ugly to me too.
>> >
>> > On 10 Oct 2016, at 02:36, Erica Sadun via swift-evolution > >> > <swift-evolution@swift.org> wrote:
>> >
>> > I would love to be able to have stored properties in addition to the
>> > varying
>> > elements.
>> >
>> > Now, I end up creating a secondary struct T and doing case a(T,
>> > whatever),
>> > b(T, whatever), c(T, whatever), etc. where the same associated structure
>> > is
>> > every case, *or* I end up putting the enum into a struct which means the
>> > guiding semantics are the struct and not the enumeration. Both
>> > approaches
>> > are ugly.
>> >
>> > -- E
>> >
>> > On Oct 9, 2016, at 6:03 PM, Jay Abbott via swift-evolution > >> > <swift-evolution@swift.org> wrote:
>> >
>> > Mateusz,
>> >
>> > To me, "Enumeration defines a type with well defined set of possible
>> > values"
>> > seems to contradict the idea of having properties that can have
>> > different
>> > values. What could you do with this special enum - what would the code
>> > that
>> > uses it look like?
>> >
>> >
>> >
>> > On Sun, 9 Oct 2016 at 04:56 Robert Widmann via swift-evolution > >> > <swift-evolution@swift.org> wrote:
>> >>
>> >> I’ve started doing this to try and mimic “Smart Constructors” in
>> >> Haskell
>> >> and I think it works quite well.
>> >>
>> >> struct Format {
>> >> enum FormatBacking {
>> >> case SMALL(Int, Int)
>> >> case MEDIUM(Int, Int)
>> >> case LARGE(Int, Int)
>> >> }
>> >
>> >
>> > _______________________________________________
>> > 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
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Mateusz Malczak) #16

Is this what you're trying to achieve, only using a nicer syntax to
represent it?
http://swiftlang.ng.bluemix.net/#/repl/57fb8ac27365890cc848f831

Yes
This similar to example shown in my original email, where struct is
used as a rawType and custom string literal parsing to assign values
to enum cases.
http://swiftlang.ng.bluemix.net/#/repl/57fb8e3e4f9bcf25fdd415cd

What I would like to achieve is (more or less)
http://swiftlang.ng.bluemix.net/#/repl/57fb98074f9bcf25fdd415d8

regards

···

--

Mateusz Malczak

2016-10-10 14:35 GMT+02:00 Jay Abbott <jay@abbott.me.uk>:

Is this what you're trying to achieve, only using a nicer syntax to
represent it?
http://swiftlang.ng.bluemix.net/#/repl/57fb8ac27365890cc848f831

On Mon, 10 Oct 2016 at 13:04 Mateusz Malczak <mateusz@malczak.info> wrote:

I think, I have used quite unfortunate naming, which is a root of an
misunderstanding here. By saying 'enums with stored properties' what I
was really thinking about, was enumeration type with stored constant,
immutable properties (constants). I don't want to duplicate 'struct'
type here, but instead I would like to make it possible to store a
const values in enumeration cases. So going back to my example once
again:

Lest define an enumeration type `Format` with 3 possible cases. Each
case will be able to carry over some additional information - in this
case a pair of numbers (but in fact Any? should be possible)

enum Format {
    case SMALL(30, 30)
    case MEDIUM(60, 60)
    case LARGE(120, 120)
    var width: Double
    var height: Double
    init(width: Double, height: Double) {
        self.width = width
        self.height = height
    }
}

I'm not sure about 'var' clause in that example as it causes all the
confusion.

I can access additional info stored in enum case, but it cannot be
modified. Format.SMALL doesn't change, as well as non of its
properties.

// allowed usage
let format = Format.SMALL
let width = format.width // this would be equal to 30 (const value
assigned to 'width' property on enum case .SMALL)

// not allowed usage
let format = Format.SMALL
format.width = 40 // error, stored values are immutable and can not be
modified

We get all advantages of enumeration type, and, assuming all cases are
describing the same possible state, we can store some extra
information in each case. This can be called a third enumeration type
feature, right next to associated values and rawType.

--
> Mateusz Malczak

2016-10-10 13:40 GMT+02:00 Jay Abbott <jay@abbott.me.uk>:
> Thanks for the explanation Mateusz, I think I understand. So the enum
> still
> only has 3 cases, SMALL, MEDIUM, and LARGE, but an instance also has
> some
> properties?
>
> So some code to use it might be:
> var aFormat = Format.LARGE
> aFormat.width = 150 // aFormat is still Format.LARGE - this doesn't
> change
>
> Is that right?
>
> On Mon, 10 Oct 2016 at 09:06 Mateusz Malczak via swift-evolution >> > <swift-evolution@swift.org> wrote:
>>
>> Hi,
>> > Perhaps it is a bit ugly, but I don’t know if allowing stored
>> > properties
>> > on
>> > enums is the solution: that looks very ugly to me too.
>>
>> That may look ugly, but can be very useful, if only you think
>> rawValue's are useful then you should also agree that stored
>> properties would be useful :slight_smile:
>>
>> --
>> > Mateusz Malczak
>>
>>
>> 2016-10-10 9:26 GMT+02:00 David Hart via swift-evolution
>> <swift-evolution@swift.org>:
>> > Perhaps it is a bit ugly, but I don’t know if allowing stored
>> > properties
>> > on
>> > enums is the solution: that looks very ugly to me too.
>> >
>> > On 10 Oct 2016, at 02:36, Erica Sadun via swift-evolution >> >> > <swift-evolution@swift.org> wrote:
>> >
>> > I would love to be able to have stored properties in addition to the
>> > varying
>> > elements.
>> >
>> > Now, I end up creating a secondary struct T and doing case a(T,
>> > whatever),
>> > b(T, whatever), c(T, whatever), etc. where the same associated
>> > structure
>> > is
>> > every case, *or* I end up putting the enum into a struct which means
>> > the
>> > guiding semantics are the struct and not the enumeration. Both
>> > approaches
>> > are ugly.
>> >
>> > -- E
>> >
>> > On Oct 9, 2016, at 6:03 PM, Jay Abbott via swift-evolution >> >> > <swift-evolution@swift.org> wrote:
>> >
>> > Mateusz,
>> >
>> > To me, "Enumeration defines a type with well defined set of possible
>> > values"
>> > seems to contradict the idea of having properties that can have
>> > different
>> > values. What could you do with this special enum - what would the
>> > code
>> > that
>> > uses it look like?
>> >
>> >
>> >
>> > On Sun, 9 Oct 2016 at 04:56 Robert Widmann via swift-evolution >> >> > <swift-evolution@swift.org> wrote:
>> >>
>> >> I’ve started doing this to try and mimic “Smart Constructors” in
>> >> Haskell
>> >> and I think it works quite well.
>> >>
>> >> struct Format {
>> >> enum FormatBacking {
>> >> case SMALL(Int, Int)
>> >> case MEDIUM(Int, Int)
>> >> case LARGE(Int, Int)
>> >> }
>> >
>> >
>> > _______________________________________________
>> > 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


(Mateusz Malczak) #17

Can't this problem most easily be solved by a raw value? Like so:

enum Format : Int {
    case small = 30
    case medium = 60
    case large = 120

    var width:Int { return self.rawValue }
    var height:Int { return self.rawValue }
}

This only solves a problem when width/height are the same. Im talking
here about more general use case when you can assign different values
of different types to an enum case. Please refer to the example code:
https://swiftlang.ng.bluemix.net/#/repl/57fb98074f9bcf25fdd415d8

···

--

Mateusz Malczak

2016-10-10 15:31 GMT+02:00 Haravikk <swift-evolution@haravikk.me>:

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

I think, I have used quite unfortunate naming, which is a root of an
misunderstanding here. By saying 'enums with stored properties' what I
was really thinking about, was enumeration type with stored constant,
immutable properties (constants). I don't want to duplicate 'struct'
type here, but instead I would like to make it possible to store a
const values in enumeration cases. So going back to my example once
again:

Lest define an enumeration type `Format` with 3 possible cases. Each
case will be able to carry over some additional information - in this
case a pair of numbers (but in fact Any? should be possible)

enum Format {
   case SMALL(30, 30)
   case MEDIUM(60, 60)
   case LARGE(120, 120)
   var width: Double
   var height: Double
   init(width: Double, height: Double) {
       self.width = width
       self.height = height
   }
}

I'm not sure about 'var' clause in that example as it causes all the
confusion.

I can access additional info stored in enum case, but it cannot be
modified. Format.SMALL doesn't change, as well as non of its
properties.

// allowed usage
let format = Format.SMALL
let width = format.width // this would be equal to 30 (const value
assigned to 'width' property on enum case .SMALL)

// not allowed usage
let format = Format.SMALL
format.width = 40 // error, stored values are immutable and can not be
modified

We get all advantages of enumeration type, and, assuming all cases are
describing the same possible state, we can store some extra
information in each case. This can be called a third enumeration type
feature, right next to associated values and rawType.

--
> Mateusz Malczak

Can't this problem most easily be solved by a raw value? Like so:

enum Format : Int {
    case small = 30
    case medium = 60
    case large = 120

    var width:Int { return self.rawValue }
    var height:Int { return self.rawValue }
}

Granted this becomes more complex if you want to specify widths and heights
that do not match, as you can't currently specify a tuple as the raw value,
but if you could then that seems like it would be a better solution to this
problem surely?


(Mateusz Malczak) #18

Maybe I am missing something, but is this what you want?

It a good illustration of what I would like to be able to define with
my proposed feature.
But instead to creating a class/struct to in switch case I would like
enumeration type to be able to carry that information within its cases
For example : https://swiftlang.ng.bluemix.net/#/repl/57fb99c54f9bcf25fdd415f3

···

class Size {
   let width: Double
   let height: Double
   init(width: Double, height: Double) { … }
}

enum Format {
        case SMALL
        case MEDIUM
        case LARGE
        var size: Size {
             switch self {
                   case SMALL: return Size(width: 100, height: 100)
                   case MEDIUM: …
                   ….
             }
        }
}

let format = Format.SMALL
let width = format.size.width

format.size.width = 50 // error, immutable

On 10 Oct 2016, at 14:35, Jay Abbott via swift-evolution <swift-evolution@swift.org> wrote:

Is this what you're trying to achieve, only using a nicer syntax to represent it?
http://swiftlang.ng.bluemix.net/#/repl/57fb8ac27365890cc848f831

On Mon, 10 Oct 2016 at 13:04 Mateusz Malczak <mateusz@malczak.info> wrote:
I think, I have used quite unfortunate naming, which is a root of an
misunderstanding here. By saying 'enums with stored properties' what I
was really thinking about, was enumeration type with stored constant,
immutable properties (constants). I don't want to duplicate 'struct'
type here, but instead I would like to make it possible to store a
const values in enumeration cases. So going back to my example once
again:

Lest define an enumeration type `Format` with 3 possible cases. Each
case will be able to carry over some additional information - in this
case a pair of numbers (but in fact Any? should be possible)

enum Format {
    case SMALL(30, 30)
    case MEDIUM(60, 60)
    case LARGE(120, 120)
    var width: Double
    var height: Double
    init(width: Double, height: Double) {
        self.width = width
        self.height = height
    }
}

I'm not sure about 'var' clause in that example as it causes all the confusion.

I can access additional info stored in enum case, but it cannot be
modified. Format.SMALL doesn't change, as well as non of its
properties.

// allowed usage
let format = Format.SMALL
let width = format.width // this would be equal to 30 (const value
assigned to 'width' property on enum case .SMALL)

// not allowed usage
let format = Format.SMALL
format.width = 40 // error, stored values are immutable and can not be modified

We get all advantages of enumeration type, and, assuming all cases are
describing the same possible state, we can store some extra
information in each case. This can be called a third enumeration type
feature, right next to associated values and rawType.

--
> Mateusz Malczak

2016-10-10 13:40 GMT+02:00 Jay Abbott <jay@abbott.me.uk>:
> Thanks for the explanation Mateusz, I think I understand. So the enum still
> only has 3 cases, SMALL, MEDIUM, and LARGE, but an instance also has some
> properties?
>
> So some code to use it might be:
> var aFormat = Format.LARGE
> aFormat.width = 150 // aFormat is still Format.LARGE - this doesn't change
>
> Is that right?
>
> On Mon, 10 Oct 2016 at 09:06 Mateusz Malczak via swift-evolution >> > <swift-evolution@swift.org> wrote:
>>
>> Hi,
>> > Perhaps it is a bit ugly, but I don’t know if allowing stored properties
>> > on
>> > enums is the solution: that looks very ugly to me too.
>>
>> That may look ugly, but can be very useful, if only you think
>> rawValue's are useful then you should also agree that stored
>> properties would be useful :slight_smile:
>>
>> --
>> > Mateusz Malczak
>>
>>
>> 2016-10-10 9:26 GMT+02:00 David Hart via swift-evolution
>> <swift-evolution@swift.org>:
>> > Perhaps it is a bit ugly, but I don’t know if allowing stored properties
>> > on
>> > enums is the solution: that looks very ugly to me too.
>> >
>> > On 10 Oct 2016, at 02:36, Erica Sadun via swift-evolution >> >> > <swift-evolution@swift.org> wrote:
>> >
>> > I would love to be able to have stored properties in addition to the
>> > varying
>> > elements.
>> >
>> > Now, I end up creating a secondary struct T and doing case a(T,
>> > whatever),
>> > b(T, whatever), c(T, whatever), etc. where the same associated structure
>> > is
>> > every case, *or* I end up putting the enum into a struct which means the
>> > guiding semantics are the struct and not the enumeration. Both
>> > approaches
>> > are ugly.
>> >
>> > -- E
>> >
>> > On Oct 9, 2016, at 6:03 PM, Jay Abbott via swift-evolution >> >> > <swift-evolution@swift.org> wrote:
>> >
>> > Mateusz,
>> >
>> > To me, "Enumeration defines a type with well defined set of possible
>> > values"
>> > seems to contradict the idea of having properties that can have
>> > different
>> > values. What could you do with this special enum - what would the code
>> > that
>> > uses it look like?
>> >
>> >
>> >
>> > On Sun, 9 Oct 2016 at 04:56 Robert Widmann via swift-evolution >> >> > <swift-evolution@swift.org> wrote:
>> >>
>> >> I’ve started doing this to try and mimic “Smart Constructors” in
>> >> Haskell
>> >> and I think it works quite well.
>> >>
>> >> struct Format {
>> >> enum FormatBacking {
>> >> case SMALL(Int, Int)
>> >> case MEDIUM(Int, Int)
>> >> case LARGE(Int, Int)
>> >> }
>> >
>> >
>> > _______________________________________________
>> > 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
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Kenny Leung) #19

This is the way Java enumerations work.

https://docs.oracle.com/javase/tutorial/java/javaOO/enum.html

I think it is a good model, and I think Swift enumerations should also work the same way.

An enumeration is a finite set of things. It’s really inconvenient to have to limit those things to have only a single attribute.

-Kenny


(Kevin Nattinger) #20

I agree wholeheartedly. An enum case should be a compile-time constant. IMO, “enums” with associated values should properly be a separate entity, called “union” as that’s essentially what they are.

···

On Oct 10, 2016, at 10:31 AM, Kenny Leung via swift-evolution <swift-evolution@swift.org> wrote:

This is the way Java enumerations work.

https://docs.oracle.com/javase/tutorial/java/javaOO/enum.html

I think it is a good model, and I think Swift enumerations should also work the same way.

An enumeration is a finite set of things. It’s really inconvenient to have to limit those things to have only a single attribute.

-Kenny

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