[Idea] allValues for RawRepresentable enums


(Kevin Randrup) #1

# Summary
Add an allValues function to all enums that are RawRepresentable to access,
iterate over, and count all of the values of an enum. The usage is general
enough that I believe it would be a great addition to the language.

This can currently be "hacked" in a few different ways by using the
RawRepresentable initializer (SO link
<http://stackoverflow.com/questions/24007461/how-to-enumerate-an-enum-with-string-type/24137319#24137319>
).

I'm presenting this idea here for discussion and feedback before I write up
a formal proposal.

# Limits
Having an allValues method would only be logical for enums which do not
have associated values. This limits the enum to RawRepresentable enums and
basic enums (is there a name for an enum without associated values and no
raw value?).
I'm working with the assumption that this would only be done with
RawRepresentable enums but it may be the case that basic enums can be
included easily.

# Examples
All examples as source code are available as a gist
<https://gist.github.com/kevinrandrup/00448c37ae9c20fa4eab>.

enum CommandLineFlag : String {
    case Version = "--version"
    case Help = "--help"
    case Start = "--start"
}

func displayHelp() {
    print("Available flags\n")
    for flag in CommandLineFlag.allValues {
        print("\(flag): \(flag.rawValue)")
    }
}

Representing the structure and implementing UITableViewDataSource methods
enum RecipeTableViewSection : Int {
    case Header
    case Details
}

enum RecipeHeaderRow : Int {
    case Name
    case Image
}

enum RecipeDetailRow : Int {
    case Ingredients
    case Cost
    case PreparationTime
}

// UITableViewDataSource implementation
func tableView(tableView: UITableView, numberOfRowsInSection section: Int)
-> Int {
    switch RecipeTableViewSection(rawValue: section)! {
    case .Header:
        return RecipeHeaderRow.allValues().count
    case .Details:
        return RecipeDetailRow.allValues().count
    }
}

func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return RecipeTableViewSection.allValues().count
}

# Decisions/Questions

1. Function vs. computed property vs. stored static variable

static func allValues() -> [CommandLineFlag] {
  return [Version, Help, Start]
}

static var allValues: [CommandLineFlag] {
  return [Version, Help, Start]
}

static let allValues = [Version, Help, Start]

   - Currently leaning towards computed property
      - Computed property > function - allValues doesn't do anything
      besides return a value so it doesn't need to be a function
      - Computed property > stored static variable - Will not increase the
      memory usage of the program
      - A change between computed and stored static property would not be a
   source breaking change if it turns out one is better than the other.

2. Set vs. Array

   - Set - There are no duplicate values and RawRepresentable enums already
   conform to Hashable/Equatable.
   - Array - Preserves the cases' declaration order

3. Should allValues consist of the enum type or RawValue? (CommandLineFlag
vs. String)

   - Strongly learning towards enum type
   - However, either one could be converted to the other and one could
   simply be a computed property of the other.

If you have better examples and use cases, I would love to hear about them
before writing the proposal.

- Kevin Randrup


(Jacob Bandes-Storch) #2

Please see existing discussion at
https://github.com/apple/swift-evolution/pull/114.

As discussed on #199 <https://github.com/apple/swift-evolution/pull/199>, I
believe we should continue discussing this (preferably on the same thread
as the original, or a new one that references it), but I'm currently in the
middle of a move and multiple travel plans, so I can't spearhead this for
another week or two.

Jacob

···

On Thu, Mar 24, 2016 at 2:23 PM, Kevin Randrup via swift-evolution < swift-evolution@swift.org> wrote:

# Summary
Add an allValues function to all enums that are RawRepresentable to
access, iterate over, and count all of the values of an enum. The usage is
general enough that I believe it would be a great addition to the language.

This can currently be "hacked" in a few different ways by using the
RawRepresentable initializer (SO link
<http://stackoverflow.com/questions/24007461/how-to-enumerate-an-enum-with-string-type/24137319#24137319>
).

I'm presenting this idea here for discussion and feedback before I write
up a formal proposal.

# Limits
Having an allValues method would only be logical for enums which do not
have associated values. This limits the enum to RawRepresentable enums and
basic enums (is there a name for an enum without associated values and no
raw value?).
I'm working with the assumption that this would only be done with
RawRepresentable enums but it may be the case that basic enums can be
included easily.

# Examples
All examples as source code are available as a gist
<https://gist.github.com/kevinrandrup/00448c37ae9c20fa4eab>.

enum CommandLineFlag : String {
    case Version = "--version"
    case Help = "--help"
    case Start = "--start"
}

func displayHelp() {
    print("Available flags\n")
    for flag in CommandLineFlag.allValues {
        print("\(flag): \(flag.rawValue)")
    }
}

Representing the structure and implementing UITableViewDataSource methods
enum RecipeTableViewSection : Int {
    case Header
    case Details
}

enum RecipeHeaderRow : Int {
    case Name
    case Image
}

enum RecipeDetailRow : Int {
    case Ingredients
    case Cost
    case PreparationTime
}

// UITableViewDataSource implementation
func tableView(tableView: UITableView, numberOfRowsInSection section: Int)
-> Int {
    switch RecipeTableViewSection(rawValue: section)! {
    case .Header:
        return RecipeHeaderRow.allValues().count
    case .Details:
        return RecipeDetailRow.allValues().count
    }
}

func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return RecipeTableViewSection.allValues().count
}

# Decisions/Questions

1. Function vs. computed property vs. stored static variable

static func allValues() -> [CommandLineFlag] {
  return [Version, Help, Start]
}

static var allValues: [CommandLineFlag] {
  return [Version, Help, Start]
}

static let allValues = [Version, Help, Start]

   - Currently leaning towards computed property
      - Computed property > function - allValues doesn't do anything
      besides return a value so it doesn't need to be a function
      - Computed property > stored static variable - Will not increase
      the memory usage of the program
      - A change between computed and stored static property would not be
   a source breaking change if it turns out one is better than the other.

2. Set vs. Array

   - Set - There are no duplicate values and RawRepresentable enums
   already conform to Hashable/Equatable.
   - Array - Preserves the cases' declaration order

3. Should allValues consist of the enum type or RawValue? (CommandLineFlag
vs. String)

   - Strongly learning towards enum type
   - However, either one could be converted to the other and one could
   simply be a computed property of the other.

If you have better examples and use cases, I would love to hear about them
before writing the proposal.

- Kevin Randrup

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


(Kevin Randrup) #3

My bad, I didn't see the proposal listed in evolution and didn't think to
check the pull requests.

- Kevin Randrup

···

On Thu, Mar 24, 2016 at 5:28 PM, Jacob Bandes-Storch <jtbandes@gmail.com> wrote:

Please see existing discussion at
https://github.com/apple/swift-evolution/pull/114.

As discussed on #199 <https://github.com/apple/swift-evolution/pull/199>,
I believe we should continue discussing this (preferably on the same thread
as the original, or a new one that references it), but I'm currently in the
middle of a move and multiple travel plans, so I can't spearhead this for
another week or two.

Jacob

On Thu, Mar 24, 2016 at 2:23 PM, Kevin Randrup via swift-evolution < > swift-evolution@swift.org> wrote:

# Summary
Add an allValues function to all enums that are RawRepresentable to
access, iterate over, and count all of the values of an enum. The usage is
general enough that I believe it would be a great addition to the language.

This can currently be "hacked" in a few different ways by using the
RawRepresentable initializer (SO link
<http://stackoverflow.com/questions/24007461/how-to-enumerate-an-enum-with-string-type/24137319#24137319>
).

I'm presenting this idea here for discussion and feedback before I write
up a formal proposal.

# Limits
Having an allValues method would only be logical for enums which do not
have associated values. This limits the enum to RawRepresentable enums and
basic enums (is there a name for an enum without associated values and no
raw value?).
I'm working with the assumption that this would only be done with
RawRepresentable enums but it may be the case that basic enums can be
included easily.

# Examples
All examples as source code are available as a gist
<https://gist.github.com/kevinrandrup/00448c37ae9c20fa4eab>.

enum CommandLineFlag : String {
    case Version = "--version"
    case Help = "--help"
    case Start = "--start"
}

func displayHelp() {
    print("Available flags\n")
    for flag in CommandLineFlag.allValues {
        print("\(flag): \(flag.rawValue)")
    }
}

Representing the structure and implementing UITableViewDataSource methods
enum RecipeTableViewSection : Int {
    case Header
    case Details
}

enum RecipeHeaderRow : Int {
    case Name
    case Image
}

enum RecipeDetailRow : Int {
    case Ingredients
    case Cost
    case PreparationTime
}

// UITableViewDataSource implementation
func tableView(tableView: UITableView, numberOfRowsInSection section:
Int) -> Int {
    switch RecipeTableViewSection(rawValue: section)! {
    case .Header:
        return RecipeHeaderRow.allValues().count
    case .Details:
        return RecipeDetailRow.allValues().count
    }
}

func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return RecipeTableViewSection.allValues().count
}

# Decisions/Questions

1. Function vs. computed property vs. stored static variable

static func allValues() -> [CommandLineFlag] {
  return [Version, Help, Start]
}

static var allValues: [CommandLineFlag] {
  return [Version, Help, Start]
}

static let allValues = [Version, Help, Start]

   - Currently leaning towards computed property
      - Computed property > function - allValues doesn't do anything
      besides return a value so it doesn't need to be a function
      - Computed property > stored static variable - Will not increase
      the memory usage of the program
      - A change between computed and stored static property would not
   be a source breaking change if it turns out one is better than the other.

2. Set vs. Array

   - Set - There are no duplicate values and RawRepresentable enums
   already conform to Hashable/Equatable.
   - Array - Preserves the cases' declaration order

3. Should allValues consist of the enum type or RawValue?
(CommandLineFlag vs. String)

   - Strongly learning towards enum type
   - However, either one could be converted to the other and one could
   simply be a computed property of the other.

If you have better examples and use cases, I would love to hear about
them before writing the proposal.

- Kevin Randrup

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