Re-pitch: Deriving collections of enum cases

Jacob Bandes-Storch

···

On Tue, Nov 14, 2017 at 9:06 PM, Brent Royal-Gordon <brent@architechies.com> wrote:

On Nov 14, 2017, at 5:21 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

1. It must be possible to easily access the count of values, and to access

any particular value using contiguous `Int` indices. This could be achieved
either by directly accessing elements in the list of values through an Int
subscript, or by constructing an Array from the list of values.

2. It must be possible to control the order of values in the list of
values, either by using source order or through some other simple,
straightforward mechanism.

OK, first of all, nowhere in the proposal text are these requirements
stated as part of the use case. You're free to put forward new use cases,
but here I am trying to design the most elegant way to fulfill a stated
need and you're telling me that it's something other than what's written.

Honestly, re-reading the proposal, it never cites a fully-formed use case.
Instead, it cites several blog posts, Stack Overflow questions, and small
code samples without digging in to the underlying reasons why developers
are doing what they're doing. Most of the people discussing it so far seem
to have had a tacit understanding that we wanted roughly Array-like access,
but we haven't explicitly dug into which properties of an Array are
important.

(If anyone involved feels like they had a different understanding of the
use case, please speak up.)

I think this is a place where the proposal can be improved, and I'm
willing to do some writing to improve it.

For the record, I would be happy to add co-authors (or even relinquish
authorship entirely—I don't really care whose name is on this, it just
needs to happen!) if you or anyone else has improved wording, motivation,
justification, etc. to contribute.

1. It must be possible to easily access the count of values, and to access

any particular value using contiguous `Int` indices. This could be achieved
either by directly accessing elements in the list of values through an Int
subscript, or by constructing an Array from the list of values.

2. It must be possible to control the order of values in the list of
values, either by using source order or through some other simple,
straightforward mechanism.

OK, first of all, nowhere in the proposal text are these requirements
stated as part of the use case. You're free to put forward new use cases,
but here I am trying to design the most elegant way to fulfill a stated
need and you're telling me that it's something other than what's written.

Honestly, re-reading the proposal, it never cites a fully-formed use case.
Instead, it cites several blog posts, Stack Overflow questions, and small
code samples without digging in to the underlying reasons why developers
are doing what they're doing. Most of the people discussing it so far seem
to have had a tacit understanding that we wanted roughly Array-like access,
but we haven't explicitly dug into which properties of an Array are
important.

(If anyone involved feels like they had a different understanding of the
use case, please speak up.)

I think this is a place where the proposal can be improved, and I'm
willing to do some writing to improve it.

You say that:

Essentially all other uses for enumeration of enum cases can be
trivially recreated based on just that.

But with this use case in mind, we can see that it is "trivial" in the
sense that the annoying boilerplate you need to bridge the significant
impedance mismatch is easy to come up with. Yes, you could construct an
array using the magic `for` loop, but that would be a serious pain. (And
there would be no ergonomic, mistake-resistant way to hide that pain behind
a function/initializer call, because there's no way to say that a parameter
must be a metatype for an enum.) What you really want is a way to access or
construct an `Array` or array-like type containing the type's values.

You cannot truly believe that

var cases = [BugStatus]()
for c in BugStatus.self { cases.append(c) }

is "serious pain." Yes, part of being an incomplete implementation is that
it lacks the ergonomics of a fleshed-out conformance to `Collection`. But
"serious pain"?

Yes, I'll stand by "serious pain".

If only all of life's challenges were such "serious pain."

This is fundamentally a convenience feature,

I greatly disagree with this characterization of the proposed feature. If
it were "fundamentally a convenience," then it would be best deferred from
Swift 5 entirely.

No, this feature is important to discuss--and hopefully implement--in the
Swift 5 timeframe because it is related to resilience. It is currently
_impossible_ to get all the cases of an enum. Even when you manually write
boilerplate, it can only cover the existing cases of an enum; if the enum
is vended by a library that later adds a case, your code may break. And if
you peer into the memory at runtime to do clever things, the runtime layout
of enums is not guaranteed at present. Put simply, you cannot retrieve all
the cases of an enum in today's Swift in a future-proof way. Making it
possible to do so is not about convenience--not at all. Convenience can
(and should, I'd argue) be deferred while more urgent solutions need to be
shipped first.

so it needs to actually *be* convenient—more convenient than writing out

the enum cases in an array literal. Forcing users to write imperative-style
code that can't be encapsulated is not convenient.

The point here is that even a minimal step towards what we agree is the
ideal design would make _possible_ what today is _impossible_: namely,
future-proof enumeration of all the cases of an enum type without
associated values.

We can take a minimal step towards having the feature…or we can just have
the feature.

The minimal step I propose makes _possible_ the core use case in its
entirety. Again, what makes this proposal so timely is that it's about
making _possible_ certain uses of resilient enums that are currently
_impossible_. The "feature" here to be achieved is the _possibility_ of
enumerating all the cases of an enum.

*Actually* conforming the metatype to `Sequence` or `Collection` would be a

different story. There, you could construct `Array`s or access elements
using ordinary APIs and type system features. And you could write generic
algorithms which used the set of all types: they would require conformance
to `Sequence` or `Collection`, and users would specify `Foo.Type` as the
generic parameter.

Indeed. The point here is that we don't need a name for this protocol.
You'd be able to write useful generic algorithms by using functions such as
`map` on `T.self` with intuitive constraints such as `T where T.Type :
Collection`. Isn't that a sublime way of expressing exactly what we mean?

It is! As I said, I love the idea of conforming the metatype to
`Collection`—it's very elegant. But the only advantage I can identify over
this proposal is a slight gain in elegance, while its
*disadvantages*—requiring several nontrivial enhancements to the language,
and therefore deferring large amounts of very desirable functionality to an
unspecified future release—are significant.

Here, I'd agree with you that what would be deferred _are_ purely
conveniences. You can call it very desirable functionality, but such
conveniences can wait. There are so many deep features in Swift 5 that will
also have the effect of making Swift more enjoyable and ergonomic to write.
Given two options to which we can devote time and effort going forward,
nontrivial long-term enhancements versus quick-fix pure conveniences, it is
an *advantage* and not a *disadvantage* when a design falls into the first
category.

In the meantime, we have an urgent issue here related to that very deep
feature of library resilience about how to retrieve all the cases of an
enum.

Basically, I don't think it's worth waiting for the "sublime way".

(There's also the disadvantage that the meaning of `Foo.self[i]` is not
immediately obvious in the way `Foo.allValues[i]` is. As it is, I'm not
totally convinced that `ValueEnumerable` is an obvious enough name;
`Foo.self` would be much more problematic in that sense.)

(And there's the opt-in question. Public types may not *want* to
participate in this feature, but you seem to suggest they should have to.)

That is orthogonally debatable. We could, of course (though I would not
advocate for it), require users always to explicitly conform their
metatypes (like so: `extension Foo.Type : Collection { }`) and then offer
synthesis of requirements. But yes, I do think it should be opt-out rather
than opt-in for enums.

But I suspect that would require deeper compiler changes than we can be

certain to get in Swift 5 or really at any specific point on the roadmap,
and I don't think we should delay this feature indefinitely to get a design
whose only real benefit is elegance.

We may (almost certainly) need more time to realize the full design. But
we don't need much to take the first steps towards it, which--as I write
above--would already make possible the currently impossible. It seems you'd
rather ship a complete but inelegant design forever than an incomplete but
useful part of an elegant design now. I wouldn't make that trade-off.

This is a feature people have wanted—asked for constantly—since Swift was
released. SR-30 is the oldest bug labeled "LanguageFeatureRequest" in the
Swift.org bug tracker. We've had several different threads, posted by
several different people, independently proposing it. Outside the evolution
process, questions and answers about how to do this (and related questions,
like "how do I get the number of cases?", which is usually a backdoor
version of it) are extremely common.

Apple deferred it beyond Swift 2, and Swift open source deferred it beyond
Swift 3 and 4, in part because we saw that future associated type features
and finalized type metadata formats would make the implementation
significantly better if we waited. The type features are now here, and the
metadata format will be frozen in the next release. We have everything we
need right now to make a very good version of this feature. You propose
deferring it again, not because the functionality would be appreciably
improved by the delay, but because it could be done more cleverly.

So let me turn the question around: Why *should* we wait?

We shouldn't wait. We should make it possible to enumerate all the cases of
an enum; this is important for resilient enums.

What appreciable advantages, *besides* elegance, do conforming the metatype

to `Collection` offer over a static constant?

It avoids the introduction of a protocol to the standard library that has
scant semantic significance. Recall that our bar for introducing a protocol
is to ask what semantic guarantees are made possible, and what useful
generic algorithms can be written that could not be written otherwise. What
do all `ValueEnumerable` types [as opposed to their corresponding
metatypes] have in common semantically? [Answer: What they have in common
is that we can retrieve the set of possible values of such a type; but
wait, one pretty darn good definition of a _type_ is the set of possible
values that a variable can have.] And what can you do in generic code with
`ValueEnumerable` other than access its one static property, after which
you end up relying on the semantics guaranteed by `Collection` and not that
of `ValueEnumerable`?

It results in a design that has a smaller API surface area, which is (all
other things being equal) superior to a design that has a larger API
surface area.

It permits each metatype to choose their own most suitable conformance in
the `Sequence : Collection : BidirectionalCollection :
RandomAccessCollection` hierarchy, should we choose to include non-enum
metatypes, and it permits users to use appropriate generic algorithms that
operate on sequences or collections with compatible metatypes. Suppose a
type has an infinite set of possible values, but they're well ordered and
there's a clear starting value (maybe an unsigned BigInt, say): the
corresponding metatype would be able to conform to Sequence instead of
Collection. Again, I don't really think of enabling such features on
integer types as a positive, but nonetheless it bears mentioning.

It correctly fits our mental model that enums themselves, not some static
property of enums, are enumerable--and, moreover, that the set of possible
values that a variable can have _is_ what a type represents, not what a
type's `allValues` property represents.

If someone buttonholes you at a conference and asks, "Why did you choose a

magic `for` loop, instead of just giving us an array of cases?", what is
your answer, and is it one that will satisfy them?

Firstly, it's not going to be an array of cases; we've already decided that
it's got to be some special collection.

Secondly, the reason that you should be able to use a `for` loop with the
metatype is that enum types are supposed to be, well, enumerable--not
merely some static property of enums. In the future, we'll permit
conformance to protocols that add more conveniences, just like we'll add
more conveniences for tuple equality, or for String-Substring conversion,
or any variety of APIs. In each case, we offer the best possible design
given the expressiveness of today's Swift, then wait for additional
language features rather than trying to design workaround hacks that become
permanent parts of the standard library.

Personally, I don't think I could give the answer "We thought of a design

that offered no additional functionality, but was much cooler" with a
straight face.

No, we thought of a superior design. It allows users to maximally reuse
their existing knowledge of standard library protocols and apply it to a
new context, and it adds impetus to expanding what metatypes can do, laying
the groundwork for a more expressive language.

···

On Tue, Nov 14, 2017 at 11:06 PM, Brent Royal-Gordon <brent@architechies.com > wrote:

On Nov 14, 2017, at 5:21 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

This is a feature I have been requesting since Swift 1. If the resulting ordering is not SOURCE ordering, this feature loses most of it’s usefulness for me. I would say around 80% of my uses for this require a predictable ordering (and I don’t consider something based on compiler internals predictable) which I can control. As Brent said, most of those cases involve something that shows to the user in some way. The weekday example was a good one (I actually have that in my code).

The most painful case of this being missing was where I needed an enum of all country codes (it is a beast to maintain). In that case, I am displaying them to the user in a tableView (along with icons named by the country codes), but I am also filtering them based on the user’s input in a search field. To do both, you need to be able to iterate/filter an array of cases. Awful to build. Just awful.

Also, I would greatly prefer an allValues/allCases method to having the type be a collection. It just reads clearer in code what is going on. I think what I basically want to see is:

  protocol ValueEnumerable {
    var allValues:Collection<Self>
  }

…where both the conformance and implementation are automatically inferred for enums when possible.

I would probably also end up using this protocol on Structs that I use as extensible enums. That is, I have a private/internal initializer and use static vars in place of the cases. This isn’t perfect, since part of the reason I use these structs is that they can be built in a distributed way… but I could find a way to build that array in a mostly distributed way as well (and if we ever get the Multi-function capability I have suggested elsewhere, then it could be truly distributed).

Semantically, the protocol should infer not only a finite number of cases, but a number that can be iterated over in a reasonable period of time. I would be fine with Bool conforming, but not with Int. With those semantics, I could easily see a follow-on proposal which says that associated cases where all of the values are ValueEnumerable are ValueEnumerable themselves. This would be super useful for cascading enums. I have a game that I am working on in my spare time right now, where effects of actions are represented as enums, with a single enum for all effects that references more specific enums for each type of thing that can be affected.

One other common need which I feel I should bring up even though it is a bit tangential, is that when I have enums with associated values, 90% of the time, I end up wanting a way to refer to the base of that without the value. For example, if the player has a case called ‘damage’ which has an associated Int, I end up wanting to ask (and sometimes store) if the case is a ‘damage’ case. Often, I am trying to match against patterns: Were there two damages followed by a block? What I end up doing is creating a second enum with the same cases (sans values) and then creating a mapping between the two. Busywork in the same way writing these allValues arrays are busywork. If we end up creating a way to reference just the base, maybe the allValues array should just contain those bases for non-enumerable associated values. Food for thought.

Thanks,
Jon

···

On Nov 14, 2017, at 9:06 PM, Brent Royal-Gordon via swift-dev <swift-dev@swift.org> wrote:

On Nov 14, 2017, at 5:21 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

1. It must be possible to easily access the count of values, and to access any particular value using contiguous `Int` indices. This could be achieved either by directly accessing elements in the list of values through an Int subscript, or by constructing an Array from the list of values.

2. It must be possible to control the order of values in the list of values, either by using source order or through some other simple, straightforward mechanism.

OK, first of all, nowhere in the proposal text are these requirements stated as part of the use case. You're free to put forward new use cases, but here I am trying to design the most elegant way to fulfill a stated need and you're telling me that it's something other than what's written.

Honestly, re-reading the proposal, it never cites a fully-formed use case. Instead, it cites several blog posts, Stack Overflow questions, and small code samples without digging in to the underlying reasons why developers are doing what they're doing. Most of the people discussing it so far seem to have had a tacit understanding that we wanted roughly Array-like access, but we haven't explicitly dug into which properties of an Array are important.

(If anyone involved feels like they had a different understanding of the use case, please speak up.)

I think this is a place where the proposal can be improved, and I'm willing to do some writing to improve it.

This is a feature I have been requesting since Swift 1. If the resulting ordering is not SOURCE ordering, this feature loses most of it’s usefulness for me. I would say around 80% of my uses for this require a predictable ordering (and I don’t consider something based on compiler internals predictable) which I can control. As Brent said, most of those cases involve something that shows to the user in some way. The weekday example was a good one (I actually have that in my code).

The most painful case of this being missing was where I needed an enum of all country codes (it is a beast to maintain). In that case, I am displaying them to the user in a tableView (along with icons named by the country codes), but I am also filtering them based on the user’s input in a search field. To do both, you need to be able to iterate/filter an array of cases. Awful to build. Just awful.

Also, I would greatly prefer an allValues/allCases method to having the type be a collection. It just reads clearer in code what is going on. I think what I basically want to see is:

  protocol ValueEnumerable {
    var allValues:Collection<Self>
  }

…where both the conformance and implementation are automatically inferred for enums when possible.

I would probably also end up using this protocol on Structs that I use as extensible enums. That is, I have a private/internal initializer and use static vars in place of the cases. This isn’t perfect, since part of the reason I use these structs is that they can be built in a distributed way… but I could find a way to build that array in a mostly distributed way as well (and if we ever get the Multi-function capability I have suggested elsewhere, then it could be truly distributed).

Semantically, the protocol should infer not only a finite number of cases, but a number that can be iterated over in a reasonable period of time. I would be fine with Bool conforming, but not with Int. With those semantics, I could easily see a follow-on proposal which says that associated cases where all of the values are ValueEnumerable are ValueEnumerable themselves. This would be super useful for cascading enums. I have a game that I am working on in my spare time right now, where effects of actions are represented as enums, with a single enum for all effects that references more specific enums for each type of thing that can be affected.

One other common need which I feel I should bring up even though it is a bit tangential, is that when I have enums with associated values, 90% of the time, I end up wanting a way to refer to the base of that without the value.. For example, if the player has a case called ‘damage’ which has an associated Int, I end up wanting to ask (and sometimes store) if the case is a ‘damage’ case. Often, I am trying to match against patterns: Were there two damages followed by a block? What I end up doing is creating a second enum with the same cases (sans values) and then creating a mapping between the two. Busywork in the same way writing these allValues arrays are busywork. If we end up creating a way to reference just the base, maybe the allValues array should just contain those bases for non-enumerable associated values. Food for thought.

Thanks,
Jon

···

On Nov 14, 2017, at 9:06 PM, Brent Royal-Gordon via swift-dev <swift-dev@swift.org> wrote:

On Nov 14, 2017, at 5:21 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

1. It must be possible to easily access the count of values, and to access any particular value using contiguous `Int` indices. This could be achieved either by directly accessing elements in the list of values through an Int subscript, or by constructing an Array from the list of values.

2. It must be possible to control the order of values in the list of values, either by using source order or through some other simple, straightforward mechanism.

OK, first of all, nowhere in the proposal text are these requirements stated as part of the use case. You're free to put forward new use cases, but here I am trying to design the most elegant way to fulfill a stated need and you're telling me that it's something other than what's written.

Honestly, re-reading the proposal, it never cites a fully-formed use case.. Instead, it cites several blog posts, Stack Overflow questions, and small code samples without digging in to the underlying reasons why developers are doing what they're doing. Most of the people discussing it so far seem to have had a tacit understanding that we wanted roughly Array-like access, but we haven't explicitly dug into which properties of an Array are important.

(If anyone involved feels like they had a different understanding of the use case, please speak up.)

I think this is a place where the proposal can be improved, and I'm willing to do some writing to improve it.

Has this stalled out again? I would like to help with the proposal and even attempt implementation.

I also need to catch up on the resilient discussion regarding enum case ordering.

···

On Nov 14, 2017, at 10:50 PM, Jacob Bandes-Storch via swift-evolution <swift-evolution@swift.org> wrote:

Jacob Bandes-Storch

On Tue, Nov 14, 2017 at 9:06 PM, Brent Royal-Gordon <brent@architechies.com> wrote:

On Nov 14, 2017, at 5:21 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

1. It must be possible to easily access the count of values, and to access any particular value using contiguous `Int` indices. This could be achieved either by directly accessing elements in the list of values through an Int subscript, or by constructing an Array from the list of values.

2. It must be possible to control the order of values in the list of values, either by using source order or through some other simple, straightforward mechanism.

OK, first of all, nowhere in the proposal text are these requirements stated as part of the use case. You're free to put forward new use cases, but here I am trying to design the most elegant way to fulfill a stated need and you're telling me that it's something other than what's written.

Honestly, re-reading the proposal, it never cites a fully-formed use case. Instead, it cites several blog posts, Stack Overflow questions, and small code samples without digging in to the underlying reasons why developers are doing what they're doing. Most of the people discussing it so far seem to have had a tacit understanding that we wanted roughly Array-like access, but we haven't explicitly dug into which properties of an Array are important.

(If anyone involved feels like they had a different understanding of the use case, please speak up.)

I think this is a place where the proposal can be improved, and I'm willing to do some writing to improve it.

For the record, I would be happy to add co-authors (or even relinquish authorship entirely—I don't really care whose name is on this, it just needs to happen!) if you or anyone else has improved wording, motivation, justification, etc. to contribute.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

The “base” case desire makes sense to me, but not as a part of this proposal. It might be a good follow-on.

If all associated values are enumerable, it is tempting to try to make the top level enum valueEnumerable too. I wonder if even that should be a follow-on feature.

As far as source-order, I want something like fragile enums to serve double-duty - but given where that discussion has gone I am not sure that is a possibility any more.

My planned next step is to write up some of these usage desires and constraints, and contribute those to the proposal.

If we can coalesce towards something (magic for loop, collection property...) I would like to investigate implementation and see how feasible it is for me. I don’t know expect to be particularly quick at it but hopefully I can help move things along.

···

On Dec 9, 2017, at 9:27 PM, Jonathan Hull via swift-evolution via swift-dev <swift-dev@swift.org> wrote:

On Nov 14, 2017, at 9:06 PM, Brent Royal-Gordon via swift-dev <swift-dev@swift.org> wrote:

On Nov 14, 2017, at 5:21 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

1. It must be possible to easily access the count of values, and to access any particular value using contiguous `Int` indices. This could be achieved either by directly accessing elements in the list of values through an Int subscript, or by constructing an Array from the list of values.

2. It must be possible to control the order of values in the list of values, either by using source order or through some other simple, straightforward mechanism.

OK, first of all, nowhere in the proposal text are these requirements stated as part of the use case. You're free to put forward new use cases, but here I am trying to design the most elegant way to fulfill a stated need and you're telling me that it's something other than what's written.

Honestly, re-reading the proposal, it never cites a fully-formed use case.. Instead, it cites several blog posts, Stack Overflow questions, and small code samples without digging in to the underlying reasons why developers are doing what they're doing. Most of the people discussing it so far seem to have had a tacit understanding that we wanted roughly Array-like access, but we haven't explicitly dug into which properties of an Array are important.

(If anyone involved feels like they had a different understanding of the use case, please speak up.)

I think this is a place where the proposal can be improved, and I'm willing to do some writing to improve it.

This is a feature I have been requesting since Swift 1. If the resulting ordering is not SOURCE ordering, this feature loses most of it’s usefulness for me. I would say around 80% of my uses for this require a predictable ordering (and I don’t consider something based on compiler internals predictable) which I can control. As Brent said, most of those cases involve something that shows to the user in some way. The weekday example was a good one (I actually have that in my code).

The most painful case of this being missing was where I needed an enum of all country codes (it is a beast to maintain). In that case, I am displaying them to the user in a tableView (along with icons named by the country codes), but I am also filtering them based on the user’s input in a search field. To do both, you need to be able to iterate/filter an array of cases. Awful to build. Just awful.

Also, I would greatly prefer an allValues/allCases method to having the type be a collection. It just reads clearer in code what is going on. I think what I basically want to see is:

  protocol ValueEnumerable {
    var allValues:Collection<Self>
  }

…where both the conformance and implementation are automatically inferred for enums when possible.

I would probably also end up using this protocol on Structs that I use as extensible enums. That is, I have a private/internal initializer and use static vars in place of the cases. This isn’t perfect, since part of the reason I use these structs is that they can be built in a distributed way… but I could find a way to build that array in a mostly distributed way as well (and if we ever get the Multi-function capability I have suggested elsewhere, then it could be truly distributed).

Semantically, the protocol should infer not only a finite number of cases, but a number that can be iterated over in a reasonable period of time.. I would be fine with Bool conforming, but not with Int. With those semantics, I could easily see a follow-on proposal which says that associated cases where all of the values are ValueEnumerable are ValueEnumerable themselves. This would be super useful for cascading enums. I have a game that I am working on in my spare time right now, where effects of actions are represented as enums, with a single enum for all effects that references more specific enums for each type of thing that can be affected.

One other common need which I feel I should bring up even though it is a bit tangential, is that when I have enums with associated values, 90% of the time, I end up wanting a way to refer to the base of that without the value. For example, if the player has a case called ‘damage’ which has an associated Int, I end up wanting to ask (and sometimes store) if the case is a ‘damage’ case. Often, I am trying to match against patterns: Were there two damages followed by a block? What I end up doing is creating a second enum with the same cases (sans values) and then creating a mapping between the two. Busywork in the same way writing these allValues arrays are busywork. If we end up creating a way to reference just the base, maybe the allValues array should just contain those bases for non-enumerable associated values. Food for thought.

Thanks,
Jon

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

The “base” case desire makes sense to me, but not as a part of this proposal. It might be a good follow-on.

If all associated values are enumerable, it is tempting to try to make the top level enum valueEnumerable too. I wonder if even that should be a follow-on feature.

As far as source-order, I want something like fragile enums to serve double-duty - but given where that discussion has gone I am not sure that is a possibility any more.

My planned next step is to write up some of these usage desires and constraints, and contribute those to the proposal.

If we can coalesce towards something (magic for loop, collection property...) I would like to investigate implementation and see how feasible it is for me. I don’t know expect to be particularly quick at it but hopefully I can help move things along.

···

On Dec 9, 2017, at 9:27 PM, Jonathan Hull via swift-evolution via swift-dev <swift-dev@swift.org> wrote:

On Nov 14, 2017, at 9:06 PM, Brent Royal-Gordon via swift-dev <swift-dev@swift.org> wrote:

On Nov 14, 2017, at 5:21 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

1. It must be possible to easily access the count of values, and to access any particular value using contiguous `Int` indices. This could be achieved either by directly accessing elements in the list of values through an Int subscript, or by constructing an Array from the list of values.

2. It must be possible to control the order of values in the list of values, either by using source order or through some other simple, straightforward mechanism.

OK, first of all, nowhere in the proposal text are these requirements stated as part of the use case. You're free to put forward new use cases, but here I am trying to design the most elegant way to fulfill a stated need and you're telling me that it's something other than what's written.

Honestly, re-reading the proposal, it never cites a fully-formed use case. Instead, it cites several blog posts, Stack Overflow questions, and small code samples without digging in to the underlying reasons why developers are doing what they're doing. Most of the people discussing it so far seem to have had a tacit understanding that we wanted roughly Array-like access, but we haven't explicitly dug into which properties of an Array are important.

(If anyone involved feels like they had a different understanding of the use case, please speak up.)

I think this is a place where the proposal can be improved, and I'm willing to do some writing to improve it.

This is a feature I have been requesting since Swift 1. If the resulting ordering is not SOURCE ordering, this feature loses most of it’s usefulness for me. I would say around 80% of my uses for this require a predictable ordering (and I don’t consider something based on compiler internals predictable) which I can control. As Brent said, most of those cases involve something that shows to the user in some way. The weekday example was a good one (I actually have that in my code).

The most painful case of this being missing was where I needed an enum of all country codes (it is a beast to maintain). In that case, I am displaying them to the user in a tableView (along with icons named by the country codes), but I am also filtering them based on the user’s input in a search field. To do both, you need to be able to iterate/filter an array of cases. Awful to build. Just awful.

Also, I would greatly prefer an allValues/allCases method to having the type be a collection. It just reads clearer in code what is going on. I think what I basically want to see is:

  protocol ValueEnumerable {
    var allValues:Collection<Self>
  }

…where both the conformance and implementation are automatically inferred for enums when possible.

I would probably also end up using this protocol on Structs that I use as extensible enums. That is, I have a private/internal initializer and use static vars in place of the cases. This isn’t perfect, since part of the reason I use these structs is that they can be built in a distributed way… but I could find a way to build that array in a mostly distributed way as well (and if we ever get the Multi-function capability I have suggested elsewhere, then it could be truly distributed).

Semantically, the protocol should infer not only a finite number of cases, but a number that can be iterated over in a reasonable period of time.. I would be fine with Bool conforming, but not with Int. With those semantics, I could easily see a follow-on proposal which says that associated cases where all of the values are ValueEnumerable are ValueEnumerable themselves. This would be super useful for cascading enums. I have a game that I am working on in my spare time right now, where effects of actions are represented as enums, with a single enum for all effects that references more specific enums for each type of thing that can be affected.

One other common need which I feel I should bring up even though it is a bit tangential, is that when I have enums with associated values, 90% of the time, I end up wanting a way to refer to the base of that without the value. For example, if the player has a case called ‘damage’ which has an associated Int, I end up wanting to ask (and sometimes store) if the case is a ‘damage’ case. Often, I am trying to match against patterns: Were there two damages followed by a block? What I end up doing is creating a second enum with the same cases (sans values) and then creating a mapping between the two. Busywork in the same way writing these allValues arrays are busywork. If we end up creating a way to reference just the base, maybe the allValues array should just contain those bases for non-enumerable associated values. Food for thought.

Thanks,
Jon

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

Personally, I think this dovetails quite nicely with the ‘random’ discussion. Enums are just one kind of type with a finite set of values; Int and Bool also fit that description, as may many structs and even classes.

Having a general way to express that would be quite nice, IMO.

- Karl

···

On 9. Dec 2017, at 06:19, Step Christopher via swift-evolution <swift-evolution@swift.org> wrote:

Has this stalled out again? I would like to help with the proposal and even attempt implementation.

I also need to catch up on the resilient discussion regarding enum case ordering.

On Nov 14, 2017, at 10:50 PM, Jacob Bandes-Storch via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Jacob Bandes-Storch

On Tue, Nov 14, 2017 at 9:06 PM, Brent Royal-Gordon <brent@architechies.com <mailto:brent@architechies.com>> wrote:

On Nov 14, 2017, at 5:21 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

1. It must be possible to easily access the count of values, and to access any particular value using contiguous `Int` indices. This could be achieved either by directly accessing elements in the list of values through an Int subscript, or by constructing an Array from the list of values.

2. It must be possible to control the order of values in the list of values, either by using source order or through some other simple, straightforward mechanism.

OK, first of all, nowhere in the proposal text are these requirements stated as part of the use case. You're free to put forward new use cases, but here I am trying to design the most elegant way to fulfill a stated need and you're telling me that it's something other than what's written.

Honestly, re-reading the proposal, it never cites a fully-formed use case. Instead, it cites several blog posts, Stack Overflow questions, and small code samples without digging in to the underlying reasons why developers are doing what they're doing. Most of the people discussing it so far seem to have had a tacit understanding that we wanted roughly Array-like access, but we haven't explicitly dug into which properties of an Array are important.

(If anyone involved feels like they had a different understanding of the use case, please speak up.)

I think this is a place where the proposal can be improved, and I'm willing to do some writing to improve it.

For the record, I would be happy to add co-authors (or even relinquish authorship entirely—I don't really care whose name is on this, it just needs to happen!) if you or anyone else has improved wording, motivation, justification, etc. to contribute.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto: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

Sorry for the delay. I've just updated the proposal text to incorporate
various changes, some contributed by others.

https://github.com/jtbandes/swift-evolution/blob/case-enumerable/proposals/0000-derived-collection-of-enum-cases.md

Robert's implementation
<Deriving collections of enum cases by jtbandes · Pull Request #114 · apple/swift-evolution · GitHub; is
a good start, but will need to be updated to match the naming choice in the
final proposal, and to use associatedtype.

···

On Fri, Dec 8, 2017 at 9:19 PM, Step Christopher < schristopher@bignerdranch.com> wrote:

Has this stalled out again? I would like to help with the proposal and
even attempt implementation.

I also need to catch up on the resilient discussion regarding enum case
ordering.

On Nov 14, 2017, at 10:50 PM, Jacob Bandes-Storch via swift-evolution < > swift-evolution@swift.org> wrote:

Jacob Bandes-Storch

On Tue, Nov 14, 2017 at 9:06 PM, Brent Royal-Gordon < > brent@architechies.com> wrote:

On Nov 14, 2017, at 5:21 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

1. It must be possible to easily access the count of values, and to

access any particular value using contiguous `Int` indices. This could be
achieved either by directly accessing elements in the list of values
through an Int subscript, or by constructing an Array from the list of
values.

2. It must be possible to control the order of values in the list of
values, either by using source order or through some other simple,
straightforward mechanism.

OK, first of all, nowhere in the proposal text are these requirements
stated as part of the use case. You're free to put forward new use cases,
but here I am trying to design the most elegant way to fulfill a stated
need and you're telling me that it's something other than what's written.

Honestly, re-reading the proposal, it never cites a fully-formed use
case. Instead, it cites several blog posts, Stack Overflow questions, and
small code samples without digging in to the underlying reasons why
developers are doing what they're doing. Most of the people discussing it
so far seem to have had a tacit understanding that we wanted roughly
Array-like access, but we haven't explicitly dug into which properties of
an Array are important.

(If anyone involved feels like they had a different understanding of the
use case, please speak up.)

I think this is a place where the proposal can be improved, and I'm
willing to do some writing to improve it.

For the record, I would be happy to add co-authors (or even relinquish
authorship entirely—I don't really care whose name is on this, it just
needs to happen!) if you or anyone else has improved wording, motivation,
justification, etc. to contribute.

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

Sorry for the delay. I've just updated the proposal text to incorporate various changes, some contributed by others.

https://github.com/jtbandes/swift-evolution/blob/case-enumerable/proposals/0000-derived-collection-of-enum-cases.md

I would really love to see this happen. I did a pass over the proposal, I strong suggest that you get Joe Groff’s input on this, because he has some opinions as well.

IMO, the proposal looks really great except for one thing: In "proposed solution”, I think it is very important that conformance to ValueEnumerable be explicitly requested in the code. Specifically:

enum Ma { case 马, 吗, 妈, 码, 骂, 麻, :racehorse:, :horse: }
Ma.allValues // error.

enum Ma : ValueEnumerable { case 马, 吗, 妈, 码, 骂, 麻, :racehorse:, :horse: }
Ma.allValues // works!

This is for two reasons:
1) Consistency with other similar features in Swift. Types are not hashable just because their members could be. This is because we want people to think about and explicitly opt into API features like this.
2) To align with our resilience design. An enum with no value-associated cases today could acquire them in the future, and doing so would implicitly remove this conformance. This would be surprising and bad.

Thanks for pushing this forward!

-Chris

···

On Dec 30, 2017, at 3:12 PM, Jacob Bandes-Storch via swift-evolution <swift-evolution@swift.org> wrote:

Robert's implementation <Deriving collections of enum cases by jtbandes · Pull Request #114 · apple/swift-evolution · GitHub; is a good start, but will need to be updated to match the naming choice in the final proposal, and to use associatedtype.

On Fri, Dec 8, 2017 at 9:19 PM, Step Christopher <schristopher@bignerdranch.com <mailto:schristopher@bignerdranch.com>> wrote:
Has this stalled out again? I would like to help with the proposal and even attempt implementation.

I also need to catch up on the resilient discussion regarding enum case ordering.

On Nov 14, 2017, at 10:50 PM, Jacob Bandes-Storch via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Jacob Bandes-Storch

On Tue, Nov 14, 2017 at 9:06 PM, Brent Royal-Gordon <brent@architechies.com <mailto:brent@architechies.com>> wrote:

On Nov 14, 2017, at 5:21 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

1. It must be possible to easily access the count of values, and to access any particular value using contiguous `Int` indices. This could be achieved either by directly accessing elements in the list of values through an Int subscript, or by constructing an Array from the list of values.

2. It must be possible to control the order of values in the list of values, either by using source order or through some other simple, straightforward mechanism.

OK, first of all, nowhere in the proposal text are these requirements stated as part of the use case. You're free to put forward new use cases, but here I am trying to design the most elegant way to fulfill a stated need and you're telling me that it's something other than what's written.

Honestly, re-reading the proposal, it never cites a fully-formed use case. Instead, it cites several blog posts, Stack Overflow questions, and small code samples without digging in to the underlying reasons why developers are doing what they're doing. Most of the people discussing it so far seem to have had a tacit understanding that we wanted roughly Array-like access, but we haven't explicitly dug into which properties of an Array are important.

(If anyone involved feels like they had a different understanding of the use case, please speak up.)

I think this is a place where the proposal can be improved, and I'm willing to do some writing to improve it.

For the record, I would be happy to add co-authors (or even relinquish authorship entirely—I don't really care whose name is on this, it just needs to happen!) if you or anyone else has improved wording, motivation, justification, etc. to contribute.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto: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

This looks really nice. Thank you for doing the legwork of researching previous discussions and writing up a detailed proposal!

The motivation discusses the common use case of using an enum in a data source implementation which requires 0-based Int indices. However, the proposed solution as-written does not specifically address this use case. Is the intent that the compiler-synthesized implementation always uses indices meeting 0-based Int requirement? If so it is probably worth stating this explicitly in the proposal.

···

Sent from my iPad

On Dec 30, 2017, at 5:12 PM, Jacob Bandes-Storch via swift-evolution <swift-evolution@swift.org> wrote:

Sorry for the delay. I've just updated the proposal text to incorporate various changes, some contributed by others.

https://github.com/jtbandes/swift-evolution/blob/case-enumerable/proposals/0000-derived-collection-of-enum-cases.md

Robert's implementation is a good start, but will need to be updated to match the naming choice in the final proposal, and to use associatedtype.

On Fri, Dec 8, 2017 at 9:19 PM, Step Christopher <schristopher@bignerdranch.com> wrote:
Has this stalled out again? I would like to help with the proposal and even attempt implementation.

I also need to catch up on the resilient discussion regarding enum case ordering.

On Nov 14, 2017, at 10:50 PM, Jacob Bandes-Storch via swift-evolution <swift-evolution@swift.org> wrote:

Jacob Bandes-Storch

On Tue, Nov 14, 2017 at 9:06 PM, Brent Royal-Gordon <brent@architechies.com> wrote:

On Nov 14, 2017, at 5:21 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

1. It must be possible to easily access the count of values, and to access any particular value using contiguous `Int` indices. This could be achieved either by directly accessing elements in the list of values through an Int subscript, or by constructing an Array from the list of values.

2. It must be possible to control the order of values in the list of values, either by using source order or through some other simple, straightforward mechanism.

OK, first of all, nowhere in the proposal text are these requirements stated as part of the use case. You're free to put forward new use cases, but here I am trying to design the most elegant way to fulfill a stated need and you're telling me that it's something other than what's written.

Honestly, re-reading the proposal, it never cites a fully-formed use case. Instead, it cites several blog posts, Stack Overflow questions, and small code samples without digging in to the underlying reasons why developers are doing what they're doing. Most of the people discussing it so far seem to have had a tacit understanding that we wanted roughly Array-like access, but we haven't explicitly dug into which properties of an Array are important.

(If anyone involved feels like they had a different understanding of the use case, please speak up.)

I think this is a place where the proposal can be improved, and I'm willing to do some writing to improve it.

For the record, I would be happy to add co-authors (or even relinquish authorship entirely—I don't really care whose name is on this, it just needs to happen!) if you or anyone else has improved wording, motivation, justification, etc. to contribute.
_______________________________________________
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

Sorry for the delay. I've just updated the proposal text to incorporate various changes, some contributed by others.

https://github.com/jtbandes/swift-evolution/blob/case-enumerable/proposals/0000-derived-collection-of-enum-cases.md

Robert's implementation <Deriving collections of enum cases by jtbandes · Pull Request #114 · apple/swift-evolution · GitHub; is a good start, but will need to be updated to match the naming choice in the final proposal, and to use associatedtype.

Looks good, but I have two questions:

1) What is the exact semantic meaning of ValueEnumerable? Does it somehow imply an enum? Or is it simply an abstraction for any type with a “fixed, finite set of [values]”?

I ask because the standard library includes some non-enum types which also fit that definition: namely Bool, Unicode characters, and the various integer types. Would it make sense for those types to also conform (regardless if its part of the proposal; I’m asking if you would consider that a “misuse” of the protocol)?.

2) Is the order of values in the Collection generally meaningful, or not? If not, would it be reasonable for types which conform to Comparable to always return a sorted Collection? Or should we manually sort it with “MyEnum.allValues.sorted()”?

- Karl

···

On 31. Dec 2017, at 00:12, Jacob Bandes-Storch via swift-evolution <swift-evolution@swift.org> wrote:

On Fri, Dec 8, 2017 at 9:19 PM, Step Christopher <schristopher@bignerdranch.com <mailto:schristopher@bignerdranch.com>> wrote:
Has this stalled out again? I would like to help with the proposal and even attempt implementation.

I also need to catch up on the resilient discussion regarding enum case ordering.

On Nov 14, 2017, at 10:50 PM, Jacob Bandes-Storch via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Jacob Bandes-Storch

On Tue, Nov 14, 2017 at 9:06 PM, Brent Royal-Gordon <brent@architechies.com <mailto:brent@architechies.com>> wrote:

On Nov 14, 2017, at 5:21 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

1. It must be possible to easily access the count of values, and to access any particular value using contiguous `Int` indices. This could be achieved either by directly accessing elements in the list of values through an Int subscript, or by constructing an Array from the list of values.

2. It must be possible to control the order of values in the list of values, either by using source order or through some other simple, straightforward mechanism.

OK, first of all, nowhere in the proposal text are these requirements stated as part of the use case. You're free to put forward new use cases, but here I am trying to design the most elegant way to fulfill a stated need and you're telling me that it's something other than what's written.

Honestly, re-reading the proposal, it never cites a fully-formed use case. Instead, it cites several blog posts, Stack Overflow questions, and small code samples without digging in to the underlying reasons why developers are doing what they're doing. Most of the people discussing it so far seem to have had a tacit understanding that we wanted roughly Array-like access, but we haven't explicitly dug into which properties of an Array are important.

(If anyone involved feels like they had a different understanding of the use case, please speak up.)

I think this is a place where the proposal can be improved, and I'm willing to do some writing to improve it.

For the record, I would be happy to add co-authors (or even relinquish authorship entirely—I don't really care whose name is on this, it just needs to happen!) if you or anyone else has improved wording, motivation, justification, etc. to contribute.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto: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

Re-reading this thread and thinking about it more, I think I agree :)
Updating again...

···

On Sat, Dec 30, 2017 at 3:44 PM, Chris Lattner <clattner@nondot.org> wrote:

On Dec 30, 2017, at 3:12 PM, Jacob Bandes-Storch via swift-evolution < > swift-evolution@swift.org> wrote:

Sorry for the delay. I've just updated the proposal text to incorporate
various changes, some contributed by others.

https://github.com/jtbandes/swift-evolution/blob/case-
enumerable/proposals/0000-derived-collection-of-enum-cases.md

I would really love to see this happen. I did a pass over the proposal, I
strong suggest that you get Joe Groff’s input on this, because he has some
opinions as well.

IMO, the proposal looks really great except for one thing: In "proposed
solution”, I think it is very important that conformance to ValueEnumerable
be explicitly requested in the code. Specifically:

enum Ma { case 马, 吗, 妈, 码, 骂, 麻, :racehorse:, :horse: }
Ma.allValues // error.

enum Ma : ValueEnumerable { case 马, 吗, 妈, 码, 骂, 麻, :racehorse:, :horse: }
Ma.allValues // works!

This is for two reasons:
1) Consistency with other similar features in Swift. Types are not
hashable just because their members could be. This is because we want
people to think about and explicitly opt into API features like this.
2) To align with our resilience design. An enum with no value-associated
cases today could acquire them in the future, and doing so would implicitly
remove this conformance. This would be surprising and bad.

Thanks for pushing this forward!

-Chris

Robert's implementation
<Deriving collections of enum cases by jtbandes · Pull Request #114 · apple/swift-evolution · GitHub; is
a good start, but will need to be updated to match the naming choice in the
final proposal, and to use associatedtype.

On Fri, Dec 8, 2017 at 9:19 PM, Step Christopher < > schristopher@bignerdranch.com> wrote:

Has this stalled out again? I would like to help with the proposal and
even attempt implementation.

I also need to catch up on the resilient discussion regarding enum case
ordering.

On Nov 14, 2017, at 10:50 PM, Jacob Bandes-Storch via swift-evolution < >> swift-evolution@swift.org> wrote:

Jacob Bandes-Storch

On Tue, Nov 14, 2017 at 9:06 PM, Brent Royal-Gordon < >> brent@architechies.com> wrote:

On Nov 14, 2017, at 5:21 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

1. It must be possible to easily access the count of values, and to

access any particular value using contiguous `Int` indices. This could be
achieved either by directly accessing elements in the list of values
through an Int subscript, or by constructing an Array from the list of
values.

2. It must be possible to control the order of values in the list of
values, either by using source order or through some other simple,
straightforward mechanism.

OK, first of all, nowhere in the proposal text are these requirements
stated as part of the use case. You're free to put forward new use cases,
but here I am trying to design the most elegant way to fulfill a stated
need and you're telling me that it's something other than what's written.

Honestly, re-reading the proposal, it never cites a fully-formed use
case. Instead, it cites several blog posts, Stack Overflow questions, and
small code samples without digging in to the underlying reasons why
developers are doing what they're doing. Most of the people discussing it
so far seem to have had a tacit understanding that we wanted roughly
Array-like access, but we haven't explicitly dug into which properties of
an Array are important.

(If anyone involved feels like they had a different understanding of the
use case, please speak up.)

I think this is a place where the proposal can be improved, and I'm
willing to do some writing to improve it.

For the record, I would be happy to add co-authors (or even relinquish
authorship entirely—I don't really care whose name is on this, it just
needs to happen!) if you or anyone else has improved wording, motivation,
justification, etc. to contribute.

_______________________________________________
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

~Robert Widmann

2017/12/31 11:02、Karl Wagner via swift-evolution <swift-evolution@swift.org>のメール:

Sorry for the delay. I've just updated the proposal text to incorporate various changes, some contributed by others.

https://github.com/jtbandes/swift-evolution/blob/case-enumerable/proposals/0000-derived-collection-of-enum-cases.md

Robert's implementation is a good start, but will need to be updated to match the naming choice in the final proposal, and to use associatedtype.

Looks good, but I have two questions:

1) What is the exact semantic meaning of ValueEnumerable? Does it somehow imply an enum? Or is it simply an abstraction for any type with a “fixed, finite set of [values]”?

The exact meaning of a synthesized conformance to ValueEnumerable is

- The type is an enum
- That enum is not @objc
- That enum is composed entirely of cases that have no associated values
- That enum is defined in the module declaring the synthesized conformance (ie no extensions - same as Equatable and Hashable)

The exact meaning of a general conformance is

- The type has a finite number of possible values inhabiting it

As you note, integral types and Bool and some enums that fall outside the scope of the synthesis requirements fit this mold quite nicely. We do not include them in the proposal partially to keep things simple, partially because we’d be stepping on Range’s toes, and partially because synthesis for structs is tricky in the general case. If deemed particularly useful in the future, these conformance can be added.

2) Is the order of values in the Collection generally meaningful, or not? If not, would it be reasonable for types which conform to Comparable to always return a sorted Collection? Or should we manually sort it with “MyEnum.allValues.sorted()”?

The interface for the protocol makes no ordering guarantees, but the synthesized conformance uses source-order because that’s currently the way the runtime metadata (which will become ABI) is implemented. It is up to authors to document the ordering stability of the value collection or to let the compiler handle it for them.

~Robert Widmann

···

On 31. Dec 2017, at 00:12, Jacob Bandes-Storch via swift-evolution <swift-evolution@swift.org> wrote:

- Karl

On Fri, Dec 8, 2017 at 9:19 PM, Step Christopher <schristopher@bignerdranch.com> wrote:
Has this stalled out again? I would like to help with the proposal and even attempt implementation.

I also need to catch up on the resilient discussion regarding enum case ordering.

On Nov 14, 2017, at 10:50 PM, Jacob Bandes-Storch via swift-evolution <swift-evolution@swift.org> wrote:

Jacob Bandes-Storch

On Tue, Nov 14, 2017 at 9:06 PM, Brent Royal-Gordon <brent@architechies.com> wrote:

On Nov 14, 2017, at 5:21 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

1. It must be possible to easily access the count of values, and to access any particular value using contiguous `Int` indices. This could be achieved either by directly accessing elements in the list of values through an Int subscript, or by constructing an Array from the list of values.

2. It must be possible to control the order of values in the list of values, either by using source order or through some other simple, straightforward mechanism.

OK, first of all, nowhere in the proposal text are these requirements stated as part of the use case. You're free to put forward new use cases, but here I am trying to design the most elegant way to fulfill a stated need and you're telling me that it's something other than what's written.

Honestly, re-reading the proposal, it never cites a fully-formed use case. Instead, it cites several blog posts, Stack Overflow questions, and small code samples without digging in to the underlying reasons why developers are doing what they're doing. Most of the people discussing it so far seem to have had a tacit understanding that we wanted roughly Array-like access, but we haven't explicitly dug into which properties of an Array are important.

(If anyone involved feels like they had a different understanding of the use case, please speak up.)

I think this is a place where the proposal can be improved, and I'm willing to do some writing to improve it.

For the record, I would be happy to add co-authors (or even relinquish authorship entirely—I don't really care whose name is on this, it just needs to happen!) if you or anyone else has improved wording, motivation, justification, etc. to contribute.
_______________________________________________
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

In addition to what Chris said: enums imported from C and @objc enums can both have extensions and conform to protocols, so IMO it should be legal to write something like `extension Foundation.ComparisonResult: ValueEnumerable {}`.

Félix

···

Le 30 déc. 2017 à 19:00, Jacob Bandes-Storch via swift-evolution <swift-evolution@swift.org> a écrit :

Re-reading this thread and thinking about it more, I think I agree :) Updating again...

On Sat, Dec 30, 2017 at 3:44 PM, Chris Lattner <clattner@nondot.org <mailto:clattner@nondot.org>> wrote:
On Dec 30, 2017, at 3:12 PM, Jacob Bandes-Storch via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Sorry for the delay. I've just updated the proposal text to incorporate various changes, some contributed by others.

https://github.com/jtbandes/swift-evolution/blob/case-enumerable/proposals/0000-derived-collection-of-enum-cases.md

I would really love to see this happen. I did a pass over the proposal, I strong suggest that you get Joe Groff’s input on this, because he has some opinions as well.

IMO, the proposal looks really great except for one thing: In "proposed solution”, I think it is very important that conformance to ValueEnumerable be explicitly requested in the code. Specifically:

enum Ma { case 马, 吗, 妈, 码, 骂, 麻, :racehorse:, :horse: }
Ma.allValues // error.

enum Ma : ValueEnumerable { case 马, 吗, 妈, 码, 骂, 麻, :racehorse:, :horse: }
Ma.allValues // works!

This is for two reasons:
1) Consistency with other similar features in Swift. Types are not hashable just because their members could be. This is because we want people to think about and explicitly opt into API features like this.
2) To align with our resilience design. An enum with no value-associated cases today could acquire them in the future, and doing so would implicitly remove this conformance. This would be surprising and bad.

Thanks for pushing this forward!

-Chris

Robert's implementation <Deriving collections of enum cases by jtbandes · Pull Request #114 · apple/swift-evolution · GitHub; is a good start, but will need to be updated to match the naming choice in the final proposal, and to use associatedtype.

On Fri, Dec 8, 2017 at 9:19 PM, Step Christopher <schristopher@bignerdranch.com <mailto:schristopher@bignerdranch.com>> wrote:
Has this stalled out again? I would like to help with the proposal and even attempt implementation.

I also need to catch up on the resilient discussion regarding enum case ordering.

On Nov 14, 2017, at 10:50 PM, Jacob Bandes-Storch via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Jacob Bandes-Storch

On Tue, Nov 14, 2017 at 9:06 PM, Brent Royal-Gordon <brent@architechies.com <mailto:brent@architechies.com>> wrote:

On Nov 14, 2017, at 5:21 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

1. It must be possible to easily access the count of values, and to access any particular value using contiguous `Int` indices. This could be achieved either by directly accessing elements in the list of values through an Int subscript, or by constructing an Array from the list of values.

2. It must be possible to control the order of values in the list of values, either by using source order or through some other simple, straightforward mechanism.

OK, first of all, nowhere in the proposal text are these requirements stated as part of the use case. You're free to put forward new use cases, but here I am trying to design the most elegant way to fulfill a stated need and you're telling me that it's something other than what's written.

Honestly, re-reading the proposal, it never cites a fully-formed use case. Instead, it cites several blog posts, Stack Overflow questions, and small code samples without digging in to the underlying reasons why developers are doing what they're doing. Most of the people discussing it so far seem to have had a tacit understanding that we wanted roughly Array-like access, but we haven't explicitly dug into which properties of an Array are important.

(If anyone involved feels like they had a different understanding of the use case, please speak up.)

I think this is a place where the proposal can be improved, and I'm willing to do some writing to improve it.

For the record, I would be happy to add co-authors (or even relinquish authorship entirely—I don't really care whose name is on this, it just needs to happen!) if you or anyone else has improved wording, motivation, justification, etc. to contribute.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto: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

~Robert Widmann

2017/12/31 11:02、Karl Wagner via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>>のメール:

Sorry for the delay. I've just updated the proposal text to incorporate various changes, some contributed by others.

https://github.com/jtbandes/swift-evolution/blob/case-enumerable/proposals/0000-derived-collection-of-enum-cases.md

Robert's implementation <Deriving collections of enum cases by jtbandes · Pull Request #114 · apple/swift-evolution · GitHub; is a good start, but will need to be updated to match the naming choice in the final proposal, and to use associatedtype.

Looks good, but I have two questions:

1) What is the exact semantic meaning of ValueEnumerable? Does it somehow imply an enum? Or is it simply an abstraction for any type with a “fixed, finite set of [values]”?

The exact meaning of a synthesized conformance to ValueEnumerable is

- The type is an enum
- That enum is not @objc
- That enum is composed entirely of cases that have no associated values
- That enum is defined in the module declaring the synthesized conformance (ie no extensions - same as Equatable and Hashable)

The exact meaning of a general conformance is

- The type has a finite number of possible values inhabiting it

As you note, integral types and Bool and some enums that fall outside the scope of the synthesis requirements fit this mold quite nicely. We do not include them in the proposal partially to keep things simple, partially because we’d be stepping on Range’s toes, and partially because synthesis for structs is tricky in the general case. If deemed particularly useful in the future, these conformance can be added.

2) Is the order of values in the Collection generally meaningful, or not? If not, would it be reasonable for types which conform to Comparable to always return a sorted Collection? Or should we manually sort it with “MyEnum.allValues.sorted()”?

The interface for the protocol makes no ordering guarantees, but the synthesized conformance uses source-order because that’s currently the way the runtime metadata (which will become ABI) is implemented. It is up to authors to document the ordering stability of the value collection or to let the compiler handle it for them.

~Robert Widmann

Cool. I definitely think it’s worth having this protocol in the standard library.

- Karl

···

On 7. Jan 2018, at 18:47, Robert Widmann <devteam.codafi@gmail.com> wrote:

On 31. Dec 2017, at 00:12, Jacob Bandes-Storch via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

- Karl

On Fri, Dec 8, 2017 at 9:19 PM, Step Christopher <schristopher@bignerdranch.com <mailto:schristopher@bignerdranch.com>> wrote:
Has this stalled out again? I would like to help with the proposal and even attempt implementation.

I also need to catch up on the resilient discussion regarding enum case ordering.

On Nov 14, 2017, at 10:50 PM, Jacob Bandes-Storch via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Jacob Bandes-Storch

On Tue, Nov 14, 2017 at 9:06 PM, Brent Royal-Gordon <brent@architechies.com <mailto:brent@architechies.com>> wrote:

On Nov 14, 2017, at 5:21 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

1. It must be possible to easily access the count of values, and to access any particular value using contiguous `Int` indices. This could be achieved either by directly accessing elements in the list of values through an Int subscript, or by constructing an Array from the list of values.

2. It must be possible to control the order of values in the list of values, either by using source order or through some other simple, straightforward mechanism.

OK, first of all, nowhere in the proposal text are these requirements stated as part of the use case. You're free to put forward new use cases, but here I am trying to design the most elegant way to fulfill a stated need and you're telling me that it's something other than what's written.

Honestly, re-reading the proposal, it never cites a fully-formed use case. Instead, it cites several blog posts, Stack Overflow questions, and small code samples without digging in to the underlying reasons why developers are doing what they're doing. Most of the people discussing it so far seem to have had a tacit understanding that we wanted roughly Array-like access, but we haven't explicitly dug into which properties of an Array are important.

(If anyone involved feels like they had a different understanding of the use case, please speak up.)

I think this is a place where the proposal can be improved, and I'm willing to do some writing to improve it.

For the record, I would be happy to add co-authors (or even relinquish authorship entirely—I don't really care whose name is on this, it just needs to happen!) if you or anyone else has improved wording, motivation, justification, etc. to contribute.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

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

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

For what it's worth, I *might* introduce a follow-up proposal with conformances for Bool and Optional. Their straightforwardness and utility make them very tempting.

(The only questions are whether `false` and `nil` should be first or last. But if the default isn't right for your use case, you can always make your own static property instead of using the standard library's.)

···

On Jan 8, 2018, at 11:02 AM, Robert Widmann via swift-evolution <swift-evolution@swift.org> wrote:

As you note, integral types and Bool and some enums that fall outside the scope of the synthesis requirements fit this mold quite nicely. We do not include them in the proposal partially to keep things simple, partially because we’d be stepping on Range’s toes, and partially because synthesis for structs is tricky in the general case. If deemed particularly useful in the future, these conformance can be added.

--
Brent Royal-Gordon
Architechies

Hello Brent,

For what it's worth, I *might* introduce a follow-up proposal with conformances for Bool and Optional. Their straightforwardness and utility make them very tempting.

A conditional conformance for Optional could in fact be useful, but what’s the use-case for Bool?
If somebody needs a Bool conformance for generic code, it’s extremely simple to just define conformance herself.
If we see that people really do need Bool conformance, we can still add it at any time.

(The only questions are whether `false` and `nil` should be first or last. But if the default isn't right for your use case, you can always make your own static property instead of using the standard library's.)

I would start with the default initialiser.

— Martin

···

Am 10.01.2018 um 06:15 schrieb Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org>:

Hello Brent,

For what it's worth, I *might* introduce a follow-up proposal with conformances for Bool and Optional. Their straightforwardness and utility make them very tempting.

A conditional conformance for Optional could in fact be useful, but what’s the use-case for Bool?
If somebody needs a Bool conformance for generic code, it’s extremely simple to just define conformance herself.
If we see that people really do need Bool conformance, we can still add it at any time.

Retroactive conformance is always a little dangerous, because you never know when a library will want to do the same thing. This is especially true when you own neither the type nor the protocol, and doubly so for standard library types and protocols. My feeling is that we might as well just do it.

(The only questions are whether `false` and `nil` should be first or last. But if the default isn't right for your use case, you can always make your own static property instead of using the standard library's.)

I would start with the default initialiser.

That's one thing I was thinking about, but we can discuss that if and when the topic comes up for real. My point was simply that even the standard library includes types which cannot have automatically-generated conformances, but which we might want to give manual conformances to. The `ValueEnumerable` protocol formalizes a useful semantic; the synthesized conformance to it is just a convenience.

···

On Jan 10, 2018, at 12:15 AM, Martin Waitz <tali@admingilde.org> wrote:

Am 10.01.2018 um 06:15 schrieb Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org>:

--
Brent Royal-Gordon
Architechies