Re: [swift-evolution] [swift-dev] Re-pitch: Deriving collections of enum cases

2018-01-11 Thread Brent Royal-Gordon via swift-evolution
> On Jan 10, 2018, at 12:15 AM, Martin Waitz  wrote:
> 
> Hello Brent,
> 
>> Am 10.01.2018 um 06:15 schrieb Brent Royal-Gordon via 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.
> 
> 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.

-- 
Brent Royal-Gordon
Architechies

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


Re: [swift-evolution] [swift-dev] Re-pitch: Deriving collections of enum cases

2018-01-10 Thread Martin Waitz via swift-evolution
Hello Brent,

> Am 10.01.2018 um 06:15 schrieb Brent Royal-Gordon via 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.

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
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-dev] Re-pitch: Deriving collections of enum cases

2018-01-09 Thread Brent Royal-Gordon via swift-evolution
> On Jan 8, 2018, at 11:02 AM, Robert Widmann via swift-evolution 
>  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.


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.)

-- 
Brent Royal-Gordon
Architechies

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


Re: [swift-evolution] [swift-dev] Re-pitch: Deriving collections of enum cases

2018-01-08 Thread Karl Wagner via swift-evolution


> On 7. Jan 2018, at 18:47, Robert Widmann  wrote:
> 
> 
> 
> ~Robert Widmann 
> 
> 2017/12/31 11:02、Karl Wagner via swift-evolution  >のメール:
> 
>> 
>> 
>>> On 31. Dec 2017, at 00:12, Jacob Bandes-Storch via swift-evolution 
>>> > 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/-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
> 

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

- Karl

>> 
>> - Karl
>> 
>>> 
>>> On Fri, Dec 8, 2017 at 9:19 PM, Step Christopher 
>>> > 
>>> 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 
>>> > wrote:
>>> 
 
 
 Jacob Bandes-Storch
 
 On Tue, Nov 14, 2017 at 9:06 PM, Brent Royal-Gordon 
 > wrote:
> On Nov 14, 2017, at 5:21 PM, Xiaodi Wu  > 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 

Re: [swift-evolution] [swift-dev] Re-pitch: Deriving collections of enum cases

2018-01-08 Thread Robert Widmann via swift-evolution


~Robert Widmann 

2017/12/31 11:02、Karl Wagner via swift-evolution 
のメール:

> 
> 
>> On 31. Dec 2017, at 00:12, Jacob Bandes-Storch via swift-evolution 
>>  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/-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

> 
> - Karl
> 
>> 
>>> On Fri, Dec 8, 2017 at 9:19 PM, Step Christopher 
>>>  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 
  wrote:
 
 
 
 Jacob Bandes-Storch
 
 On Tue, Nov 14, 2017 at 9:06 PM, Brent Royal-Gordon 
  wrote:
>>> On Nov 14, 2017, at 5:21 PM, Xiaodi Wu  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
 

Re: [swift-evolution] [swift-dev] Re-pitch: Deriving collections of enum cases

2017-12-31 Thread Karl Wagner via swift-evolution


> On 31. Dec 2017, at 00:12, Jacob Bandes-Storch via swift-evolution 
>  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/-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]”?

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 Fri, Dec 8, 2017 at 9:19 PM, Step Christopher 
> > 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 
> > wrote:
> 
>> 
>> 
>> Jacob Bandes-Storch
>> 
>> On Tue, Nov 14, 2017 at 9:06 PM, Brent Royal-Gordon > > wrote:
>>> On Nov 14, 2017, at 5:21 PM, Xiaodi Wu >> > 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


Re: [swift-evolution] [swift-dev] Re-pitch: Deriving collections of enum cases

2017-12-31 Thread Félix Cloutier via 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 
>  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  > wrote:
> On Dec 30, 2017, at 3:12 PM, Jacob Bandes-Storch via swift-evolution 
> > 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/-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 马, 吗, 妈, 码, 骂, 麻, ,  }
> Ma.allValues   // error.
> 
> enum Ma : ValueEnumerable { case 马, 吗, 妈, 码, 骂, 麻, ,  }
> 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 
>>  
>> 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 
>> > 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 
>> > wrote:
>> 
>>> 
>>> 
>>> Jacob Bandes-Storch
>>> 
>>> On Tue, Nov 14, 2017 at 9:06 PM, Brent Royal-Gordon >> > wrote:
 On Nov 14, 2017, at 5:21 PM, Xiaodi Wu > 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 

Re: [swift-evolution] [swift-dev] Re-pitch: Deriving collections of enum cases

2017-12-30 Thread Matthew Johnson via 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 
>  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/-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 
>>  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 
>>>  wrote:
>>> 
>>> 
>>> 
>>> Jacob Bandes-Storch
>>> 
>>> On Tue, Nov 14, 2017 at 9:06 PM, Brent Royal-Gordon 
>>>  wrote:
>> On Nov 14, 2017, at 5:21 PM, Xiaodi Wu  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


Re: [swift-evolution] [swift-dev] Re-pitch: Deriving collections of enum cases

2017-12-30 Thread Jacob Bandes-Storch via 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  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/-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 马, 吗, 妈, 码, 骂, 麻, ,  }
> Ma.allValues   // error.
>
> enum Ma : ValueEnumerable { case 马, 吗, 妈, 码, 骂, 麻, ,  }
> 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
>  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 <
> schristop...@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 <
>> br...@architechies.com> wrote:
>>
>>> On Nov 14, 2017, at 5:21 PM, Xiaodi Wu  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


Re: [swift-evolution] [swift-dev] Re-pitch: Deriving collections of enum cases

2017-12-30 Thread Chris Lattner via swift-evolution
On Dec 30, 2017, at 3:12 PM, Jacob Bandes-Storch via swift-evolution 
 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/-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 马, 吗, 妈, 码, 骂, 麻, ,  }
Ma.allValues   // error.

enum Ma : ValueEnumerable { case 马, 吗, 妈, 码, 骂, 麻, ,  }
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 
>  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 
> > 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 
> > wrote:
> 
>> 
>> 
>> Jacob Bandes-Storch
>> 
>> On Tue, Nov 14, 2017 at 9:06 PM, Brent Royal-Gordon > > wrote:
>>> On Nov 14, 2017, at 5:21 PM, Xiaodi Wu >> > 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


Re: [swift-evolution] [swift-dev] Re-pitch: Deriving collections of enum cases

2017-12-30 Thread Jacob Bandes-Storch via 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/-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 <
schristop...@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 <
> br...@architechies.com> wrote:
>
>> On Nov 14, 2017, at 5:21 PM, Xiaodi Wu  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


Re: [swift-evolution] [swift-dev] Re-pitch: Deriving collections of enum cases

2017-12-09 Thread Step Christopher via 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 
>  wrote:
> 
> 
>>> On Nov 14, 2017, at 9:06 PM, Brent Royal-Gordon via swift-dev 
>>>  wrote:
>>> 
 On Nov 14, 2017, at 5:21 PM, Xiaodi Wu  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
>   }
> 
> …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 

Re: [swift-evolution] [swift-dev] Re-pitch: Deriving collections of enum cases

2017-12-09 Thread Jonathan Hull via swift-evolution

> On Nov 14, 2017, at 9:06 PM, Brent Royal-Gordon via swift-dev 
>  wrote:
> 
>> On Nov 14, 2017, at 5:21 PM, Xiaodi Wu > > 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
}

…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 

Re: [swift-evolution] [swift-dev] Re-pitch: Deriving collections of enum cases

2017-12-09 Thread Karl Wagner via swift-evolution
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 
>  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 
> > wrote:
> 
>> 
>> 
>> Jacob Bandes-Storch
>> 
>> On Tue, Nov 14, 2017 at 9:06 PM, Brent Royal-Gordon > > wrote:
>>> On Nov 14, 2017, at 5:21 PM, Xiaodi Wu >> > 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


Re: [swift-evolution] [swift-dev] Re-pitch: Deriving collections of enum cases

2017-12-08 Thread Step Christopher via swift-evolution
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 
>  wrote:
> 
> 
> 
> Jacob Bandes-Storch
> 
> On Tue, Nov 14, 2017 at 9:06 PM, Brent Royal-Gordon  
> wrote:
 On Nov 14, 2017, at 5:21 PM, Xiaodi Wu  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


Re: [swift-evolution] [swift-dev] Re-pitch: Deriving collections of enum cases

2017-11-14 Thread Xiaodi Wu via swift-evolution
On Tue, Nov 14, 2017 at 11:06 PM, Brent Royal-Gordon  wrote:

> On Nov 14, 2017, at 5:21 PM, Xiaodi Wu  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.
>
> 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
>> 

Re: [swift-evolution] [swift-dev] Re-pitch: Deriving collections of enum cases

2017-11-14 Thread Brent Royal-Gordon via swift-evolution
> On Nov 14, 2017, at 5:21 PM, Xiaodi Wu  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.

> 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". This is fundamentally a convenience feature, 
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.

> *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.

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.)

> 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 

Re: [swift-evolution] [swift-dev] Re-pitch: Deriving collections of enum cases

2017-11-14 Thread Xiaodi Wu via swift-evolution
On Tue, Nov 14, 2017 at 5:49 AM, Brent Royal-Gordon 
wrote:

> On Nov 13, 2017, at 9:21 PM, Xiaodi Wu  wrote:
>
> ...I should add, if full conformance to `Collection` is still too much to
> ask, enabling "for `case` in Foo.self" by magic would itself address the
> entirety of the proposal's use case, adding no API surface area.
>
>
> No, Xiaodi. No, it would not.
>
> Okay, thus far we've talked vaguely about "accessing the cases of an
> enum", but let's talk a little more concretely about what that means. I
> think that, especially on Apple platforms, this is the most important
> concrete use case:
>
> PROBLEM:
>
> You have an enum like:
>
> enum BugStatus {
> case open, inProgress, resolved, closed, reopened
> var localizedName: String { … }
> }
>
> You wish to present these options in a user interface so a user can select
> one of them. For instance, if you're on iOS and using UITableView, you
> might want to present the enum's values through `UITableViewDataSource` and
> allow selection through `UITableViewDelegate`.
>
> REQUIREMENTS:
>
> 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.
But sure, let's proceed on this basis.

PROPOSED SOLUTION:
>
> You conform `BugStatus` to `ValueEnumerable`:
>
> enum BugStatus: ValueEnumerable {
> case open, inProgress, resolved, closed, reopened
> var localizedName: String { … }
> }
>
> And then write the table view data source to present the elements of
> `BugStatus.allValues`:
>
> class BugStatusDataSource: NSObject, UITableViewDataSource,
> UITableViewDelegate {
> @IBOutlet var tableView: UITableView?
> @objc dynamic var selected: BugStatus? { // Observable via KVO
> didSet { tableView.reloadData() }
> }
> func status(at indexPath: IndexPath) -> Status {
> BugStatus.allValues[indexPath.row]
> }
> func tableView(_: UITableView, numberOfRowsInSection section: Int) -> Int {
> return BugStatus.allValues.count
> }
> func tableView(_: UITableView, cellForRowAt indexPath: IndexPath) ->
> UITableViewCell {
> let status = self.status(at: indexPath)
> let identifier = (status == selected) ? "SelectedCell" : "RegularCell"
> let cell = tableView.dequeueReusableCell(withIdentifier: identifier, for:
> indexPath)
> cell.titleLabel.text = status.localizedName
> return cell
> }
> func tableView(_: UITableView, didSelectRowAt indexPath: IndexPath) {
> selected = status(at: indexPath)
> }
> }
>
> This is the most direct solution; a more sophisticated version might
> inject the list as an Array so that you can show a subset of the full set
> of values.
>
> EXTENSIONS:
>
> Now, let's quickly talk about a couple extensions of this use case:
>
> * The values, and the table view cells, are grouped into sections. This
> suggests some sort of two-level, nested structure, which may not use `Int`
> indices.
>
> * You want to write a *generic* data source which can present all the
> values of *any* ValueEnumerable type (or at least any conforming to a
> protocol that allows us to fill in their cells). For that purpose, it's
> helpful to have the type conform to *some* sort of protocol and expose the
> value list through that protocol.
>
> 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"?

The point here is that even a minimal step towards what we agree is the
ideal design would make _possible_ what today is 

Re: [swift-evolution] [swift-dev] Re-pitch: Deriving collections of enum cases

2017-11-13 Thread Xiaodi Wu via swift-evolution
On Mon, Nov 13, 2017 at 11:15 PM, Xiaodi Wu  wrote:

> On Mon, Nov 13, 2017 at 8:16 PM, Brent Royal-Gordon <
> br...@architechies.com> wrote:
>
>> On Nov 12, 2017, at 10:16 AM, Xiaodi Wu  wrote:
>>
>> On Sun, Nov 12, 2017 at 4:54 AM, Brent Royal-Gordon <
>> br...@architechies.com> wrote:
>>
>>> On Nov 10, 2017, at 11:01 PM, Xiaodi Wu  wrote:
>>>
>>> Nit: if you want to call it `ValueEnumerable`, then this should be
>>> `DefaultValueCollection`.
>>>
>>>
>>> I used `DefaultCaseCollection` because, although the protocol can work
>>> with any type to return its values, this type can only work with enums and
>>> only returns their cases. `ValueEnumerable` could be sensibly applied to
>>> `Int`; `DefaultCaseCollection` could not.
>>>
>>
>>  Because of how you've chosen to implement `DefaultCaseCollection`, or do
>> you mean to say that you deliberately want a design where types other than
>> enums do not share the default return type?
>>
>>
>> Because the way `DefaultCaseCollection` works is that it queries runtime
>> metadata that can only exist for enums.
>>
>> In theory, we might be able to write a `DefaultValueCollection` which
>> would work for structs with `ValueEnumerable` properties by generating all
>> possible permutations of those fields. In practice, I suspect that this
>> would only rarely be useful. Structs' types are rarely specified so tightly
>> that all permutations are valid; for instance, a `struct PlayingCard` with
>> an integer `rank` property would only be *valid* with a rank between 1 and
>> 13, even though `Int`'s range is much wider. So I don't think we'll ever
>> want this type to support structs, and it would therefore be clearer to
>> bake its enum-only nature into its name.
>>
>> (If your response is that "your argument against permuting all possible
>> struct values is just as true with an integer associated value"…well,
>> you're not wrong, and that might be an argument against making integer
>> types `ValueEnumerable`.
>>
>
> Not only is it an argument against making integer types `ValueEnumerable`,
> it's a pretty darn good argument against any design that makes such an
> eventuality possible--in the absence of a compelling use case that would
> make that design desirable for other reasons.
>
>
>> But we don't propose conforming `Int` to `ValueEnumerable` immediately,
>> just adopting a design flexible enough to permit it.)
>>
>> Tony's "no more specific than they need to" language applies here. The
>>> way I see it is this:
>>>
>>> * `Bool` is not an enum, but it could be usefully conformed to
>>> `ValueEnumerable`. Why should we prevent that?
>>> * A type with two independently-switchable `Bool`s—say, `isMirrored` and
>>> `isFlipped`—could be usefully conformed to `ValueEnumerable`. Why should we
>>> prevent that?
>>> * Having integer types conform to `ValueEnumerable` with `static let
>>> allValues = Self.min...Self.max` could be useful. Why should we prevent
>>> that?
>>>
>>
>> I'd say you're looking at it the wrong way. We're not *preventing*
>> anything. We're adding a feature, and the question is, why should we *add*
>> more than is justified by the use case?
>>
>>
>> Okay, here's the positive justification: The choice of an enum vs. a
>> struct ought, to some degree, to be an implementation detail. As a general
>> example of this, `__attribute__((swift_wrapper(enum)) ` types in
>> Objective-C are actually imported into Swift as structs, but this detail
>> rarely matters to users. A little closer to home, `Bool` could be an enum,
>> but is implemented as a struct instead. `EncodingError` and `DecodingError`
>> could be structs, but are implemented as enums instead.
>>
>
> This is not a terrible argument from a practical standpoint, but I'd turn
> it around: based on your examples, it's a convincing argument for improving
> Objective-C import so that all types that users would want to be enums can
> actually be bridged as enums, and for making `Bool` into an enum. I don't
> see what the problem is with `EncodingError` or `DecodingError` being
> enums, so I can't comment on that.
>
>
>> To allow this flexibility, Swift rarely creates features for enums which
>> are completely closed off to the structs (or vice versa), though they may
>> have convenience features on only one of them. For example, both can have
>> initializers, but only structs have them created implicitly; both can be
>> RawRepresentable, but only enums get the sugar syntax. (The big exceptions
>> are enum's pattern matching and struct's ability to encapsulate
>> implementation details, but we've talked about bringing both of these
>> features to the other side in some fashion.)
>>
>> Therefore, I think this feature should follow the general Swift pattern
>> and not be completely closed off to structs. It may not be as convenient to
>> use there, but it should be possible. This preserves flexibility for type
>> designers so they aren't forced to 

Re: [swift-evolution] [swift-dev] Re-pitch: Deriving collections of enum cases

2017-11-13 Thread Xiaodi Wu via swift-evolution
On Mon, Nov 13, 2017 at 8:16 PM, Brent Royal-Gordon 
wrote:

> On Nov 12, 2017, at 10:16 AM, Xiaodi Wu  wrote:
>
> On Sun, Nov 12, 2017 at 4:54 AM, Brent Royal-Gordon <
> br...@architechies.com> wrote:
>
>> On Nov 10, 2017, at 11:01 PM, Xiaodi Wu  wrote:
>>
>> Nit: if you want to call it `ValueEnumerable`, then this should be
>> `DefaultValueCollection`.
>>
>>
>> I used `DefaultCaseCollection` because, although the protocol can work
>> with any type to return its values, this type can only work with enums and
>> only returns their cases. `ValueEnumerable` could be sensibly applied to
>> `Int`; `DefaultCaseCollection` could not.
>>
>
>  Because of how you've chosen to implement `DefaultCaseCollection`, or do
> you mean to say that you deliberately want a design where types other than
> enums do not share the default return type?
>
>
> Because the way `DefaultCaseCollection` works is that it queries runtime
> metadata that can only exist for enums.
>
> In theory, we might be able to write a `DefaultValueCollection` which
> would work for structs with `ValueEnumerable` properties by generating all
> possible permutations of those fields. In practice, I suspect that this
> would only rarely be useful. Structs' types are rarely specified so tightly
> that all permutations are valid; for instance, a `struct PlayingCard` with
> an integer `rank` property would only be *valid* with a rank between 1 and
> 13, even though `Int`'s range is much wider. So I don't think we'll ever
> want this type to support structs, and it would therefore be clearer to
> bake its enum-only nature into its name.
>
> (If your response is that "your argument against permuting all possible
> struct values is just as true with an integer associated value"…well,
> you're not wrong, and that might be an argument against making integer
> types `ValueEnumerable`.
>

Not only is it an argument against making integer types `ValueEnumerable`,
it's a pretty darn good argument against any design that makes such an
eventuality possible--in the absence of a compelling use case that would
make that design desirable for other reasons.


> But we don't propose conforming `Int` to `ValueEnumerable` immediately,
> just adopting a design flexible enough to permit it.)
>
> Tony's "no more specific than they need to" language applies here. The way
>> I see it is this:
>>
>> * `Bool` is not an enum, but it could be usefully conformed to
>> `ValueEnumerable`. Why should we prevent that?
>> * A type with two independently-switchable `Bool`s—say, `isMirrored` and
>> `isFlipped`—could be usefully conformed to `ValueEnumerable`. Why should we
>> prevent that?
>> * Having integer types conform to `ValueEnumerable` with `static let
>> allValues = Self.min...Self.max` could be useful. Why should we prevent
>> that?
>>
>
> I'd say you're looking at it the wrong way. We're not *preventing*
> anything. We're adding a feature, and the question is, why should we *add*
> more than is justified by the use case?
>
>
> Okay, here's the positive justification: The choice of an enum vs. a
> struct ought, to some degree, to be an implementation detail. As a general
> example of this, `__attribute__((swift_wrapper(enum)) ` types in
> Objective-C are actually imported into Swift as structs, but this detail
> rarely matters to users. A little closer to home, `Bool` could be an enum,
> but is implemented as a struct instead. `EncodingError` and `DecodingError`
> could be structs, but are implemented as enums instead.
>

This is not a terrible argument from a practical standpoint, but I'd turn
it around: based on your examples, it's a convincing argument for improving
Objective-C import so that all types that users would want to be enums can
actually be bridged as enums, and for making `Bool` into an enum. I don't
see what the problem is with `EncodingError` or `DecodingError` being
enums, so I can't comment on that.


> To allow this flexibility, Swift rarely creates features for enums which
> are completely closed off to the structs (or vice versa), though they may
> have convenience features on only one of them. For example, both can have
> initializers, but only structs have them created implicitly; both can be
> RawRepresentable, but only enums get the sugar syntax. (The big exceptions
> are enum's pattern matching and struct's ability to encapsulate
> implementation details, but we've talked about bringing both of these
> features to the other side in some fashion.)
>
> Therefore, I think this feature should follow the general Swift pattern
> and not be completely closed off to structs. It may not be as convenient to
> use there, but it should be possible. This preserves flexibility for type
> designers so they aren't forced to use enums merely because they want to
> use the standard mechanism for publishing the possible values of a type.
>

Or, we could fix the edge cases so that no user needs to use a `struct`

Re: [swift-evolution] [swift-dev] Re-pitch: Deriving collections of enum cases

2017-11-13 Thread Brent Royal-Gordon via swift-evolution
> On Nov 12, 2017, at 10:16 AM, Xiaodi Wu  wrote:
> 
> On Sun, Nov 12, 2017 at 4:54 AM, Brent Royal-Gordon  > wrote:
>> On Nov 10, 2017, at 11:01 PM, Xiaodi Wu > > wrote:
>> 
>> Nit: if you want to call it `ValueEnumerable`, then this should be 
>> `DefaultValueCollection`.
> 
> I used `DefaultCaseCollection` because, although the protocol can work with 
> any type to return its values, this type can only work with enums and only 
> returns their cases. `ValueEnumerable` could be sensibly applied to `Int`; 
> `DefaultCaseCollection` could not.
> 
>  Because of how you've chosen to implement `DefaultCaseCollection`, or do you 
> mean to say that you deliberately want a design where types other than enums 
> do not share the default return type?

Because the way `DefaultCaseCollection` works is that it queries runtime 
metadata that can only exist for enums.

In theory, we might be able to write a `DefaultValueCollection` which would 
work for structs with `ValueEnumerable` properties by generating all possible 
permutations of those fields. In practice, I suspect that this would only 
rarely be useful. Structs' types are rarely specified so tightly that all 
permutations are valid; for instance, a `struct PlayingCard` with an integer 
`rank` property would only be *valid* with a rank between 1 and 13, even though 
`Int`'s range is much wider. So I don't think we'll ever want this type to 
support structs, and it would therefore be clearer to bake its enum-only nature 
into its name.

(If your response is that "your argument against permuting all possible struct 
values is just as true with an integer associated value"…well, you're not 
wrong, and that might be an argument against making integer types 
`ValueEnumerable`. But we don't propose conforming `Int` to `ValueEnumerable` 
immediately, just adopting a design flexible enough to permit it.)

> Tony's "no more specific than they need to" language applies here. The way I 
> see it is this:
> 
> * `Bool` is not an enum, but it could be usefully conformed to 
> `ValueEnumerable`. Why should we prevent that?
> * A type with two independently-switchable `Bool`s—say, `isMirrored` and 
> `isFlipped`—could be usefully conformed to `ValueEnumerable`. Why should we 
> prevent that?
> * Having integer types conform to `ValueEnumerable` with `static let 
> allValues = Self.min...Self.max` could be useful. Why should we prevent that?
> 
> I'd say you're looking at it the wrong way. We're not *preventing* anything. 
> We're adding a feature, and the question is, why should we *add* more than is 
> justified by the use case?

Okay, here's the positive justification: The choice of an enum vs. a struct 
ought, to some degree, to be an implementation detail. As a general example of 
this, `__attribute__((swift_wrapper(enum)) ` types in Objective-C are actually 
imported into Swift as structs, but this detail rarely matters to users. A 
little closer to home, `Bool` could be an enum, but is implemented as a struct 
instead. `EncodingError` and `DecodingError` could be structs, but are 
implemented as enums instead.

To allow this flexibility, Swift rarely creates features for enums which are 
completely closed off to the structs (or vice versa), though they may have 
convenience features on only one of them. For example, both can have 
initializers, but only structs have them created implicitly; both can be 
RawRepresentable, but only enums get the sugar syntax. (The big exceptions are 
enum's pattern matching and struct's ability to encapsulate implementation 
details, but we've talked about bringing both of these features to the other 
side in some fashion.)

Therefore, I think this feature should follow the general Swift pattern and not 
be completely closed off to structs. It may not be as convenient to use there, 
but it should be possible. This preserves flexibility for type designers so 
they aren't forced to use enums merely because they want to use the standard 
mechanism for publishing the possible values of a type.

> Is there a clamor for enumerating the possible values of a type with two 
> independently switchable `Bool`s? If so, is that not an argument to make 
> `Bool` a valid raw value type? (There is already a bug report to make tuples 
> of raw value types valid raw value types themselves.)

FWIW, I'm surprised Swift thinks "raw type 'Bool' is not expressible by any 
literal" when Bool is `ExpressibleByBooleanLiteral`. I'm not sure whether this 
is an oversight or if there's a specific reason for it.

> Why is it useful for (fixed-width) integer types to conform to 
> `ValueEnumerable`? What use cases, exactly, would that enable that are not 
> possible now?

It might permit advanced `ValueEnumerable` synthesis, for one thing. (But 
again, see my misgivings above about the usefulness of generating all possible 
permutations.)


Re: [swift-evolution] [swift-dev] Re-pitch: Deriving collections of enum cases

2017-11-12 Thread Xiaodi Wu via swift-evolution
On Sun, Nov 12, 2017 at 1:37 PM, Tony Allevato 
wrote:

>
>
> On Sat, Nov 11, 2017 at 1:53 PM Xiaodi Wu  wrote:
>
>> On Sat, Nov 11, 2017 at 3:15 PM, Tony Allevato 
>> wrote:
>>
>>>
>>>
>>> On Sat, Nov 11, 2017 at 10:28 AM Xiaodi Wu  wrote:
>>>
 On Sat, Nov 11, 2017 at 11:23 AM, Tony Allevato <
 tony.allev...@gmail.com> wrote:

>
>
> On Fri, Nov 10, 2017 at 11:01 PM Xiaodi Wu via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>> Nit: if you want to call it `ValueEnumerable`, then this should be
>> `DefaultValueCollection`.
>>
>> More generally though, I can see the appeal of allowing `Int` to
>> conform to `ValueEnumerable`, but I've got a feeling that this is headed
>> rapidly in the direction of overengineering a feature without a good
>> rationale for the additional complexity. The stated use case is to
>> enumerate the cases of an enum, and any additional complexity above that
>> should stand on its own merit. I disagree quite vehemently that protocols
>> should be "as general as possible"; rather, they exist to enable useful
>> generic algorithms and should be as _useful_ as possible. There is a 
>> happy
>> medium beyond which overengineering the design makes a protocol markedly
>> less usable/approachable for the sake of enabling rare functionality.
>>
>
> Perhaps "no more specific than they need to be" would have been a
> better choice of words on my part than "as general as possible".
>
> I'm not sure why you think this decision makes the protocol "markedly
> less usable/approachable". and I think you're seeing a lot of complexity
> that isn't there. Regarding good rationale, I've given that in this thread
> above and in the previous discussion thread, but I'll summarize it again
> here:
>
> 1) "The stated use case is to enumerate the cases of an enum" isn't
> sufficient for designing a protocol because Swift does not have protocols
> that are restricted only to enums. Just as anyone can conform their own
> types to RawRepresentable, anyone should be able to conform their own 
> types
> to ValueEnumerable.
>

 This is the part of the argument that I am questioning. If the desired
 use case is to enumerate the cases of an enum, is it much of a gain to
 allow anyone to be able to conform their own non-enum types to this
 protocol? Yes, if you buy that, then much of the rest follows. But make no
 mistake that it is not necessary to serve the desired use case and
 dramatically increases the complexity of the design (see below for just
 some considerations).

>>>
>>> Some increase in complexity is certainly going to be introduced by
>>> generalizing a design to make it useful to more than just a single use
>>> case, but I hope you understand that using unquantifiable and subjective
>>> qualifiers like "markedly less usable" or "dramatically increases the
>>> complexity" is a bit unhelpful when trying to debate specifics. You clearly
>>> put a great deal of thought into design problems like this and I always
>>> appreciate your points of view, so I want to focus on the objective parts.
>>>
>>> In prior threads on this topic, I believe I recall you saying that a
>>> static property that returns an array is fine. (I don't remember your exact
>>> words, so please correct me if I'm wrong. I don't want to misstate your
>>> position.) Given the concerns I've pointed out about why that is both a
>>> time and memory performance problem, and given your focus on the common use
>>> case above, I'd appreciate your opinion on these points:
>>>
>>> * Are you advocating for a magic protocol that *only* enums can conform
>>> to? (This is a different issue than whether the protocol is just a
>>> compiler-known protocol that it can synthesize.)
>>> * If yes, why intentionally restrict it others from implementing the
>>> protocol? That's actually *more* complexity than allowing it, like we do
>>> with RawRepresentable. There's also no precedent for "a protocol that can
>>> only be applied to enums" in the Swift language. The ramifications of that
>>> decision introduce their own design complexity—you're just shifting it
>>> around, not avoiding it.
>>> * If no, then I don't think we differ on this point.
>>>
>>
>> No magic. Consider: Does the compiler stop me from conforming `UIButton`
>> to `Error`? No. Can `UIButton` conform to `Error`? Semantically, no.
>>
>> I am arguing that the use case justifies a protocol called
>> "CaseEnumerable" with documented semantics such that only types with cases
>> (i.e., enums with one or more cases) would fulfill those semantics. Any
>> more generalization and we are designing without a justification. I'm
>> unsure what design complexity you anticipate with such a definition of
>> 

Re: [swift-evolution] [swift-dev] Re-pitch: Deriving collections of enum cases

2017-11-12 Thread Tony Allevato via swift-evolution
On Sat, Nov 11, 2017 at 1:53 PM Xiaodi Wu  wrote:

> On Sat, Nov 11, 2017 at 3:15 PM, Tony Allevato 
> wrote:
>
>>
>>
>> On Sat, Nov 11, 2017 at 10:28 AM Xiaodi Wu  wrote:
>>
>>> On Sat, Nov 11, 2017 at 11:23 AM, Tony Allevato >> > wrote:
>>>


 On Fri, Nov 10, 2017 at 11:01 PM Xiaodi Wu via swift-evolution <
 swift-evolution@swift.org> wrote:

> Nit: if you want to call it `ValueEnumerable`, then this should be
> `DefaultValueCollection`.
>
> More generally though, I can see the appeal of allowing `Int` to
> conform to `ValueEnumerable`, but I've got a feeling that this is headed
> rapidly in the direction of overengineering a feature without a good
> rationale for the additional complexity. The stated use case is to
> enumerate the cases of an enum, and any additional complexity above that
> should stand on its own merit. I disagree quite vehemently that protocols
> should be "as general as possible"; rather, they exist to enable useful
> generic algorithms and should be as _useful_ as possible. There is a happy
> medium beyond which overengineering the design makes a protocol markedly
> less usable/approachable for the sake of enabling rare functionality.
>

 Perhaps "no more specific than they need to be" would have been a
 better choice of words on my part than "as general as possible".

 I'm not sure why you think this decision makes the protocol "markedly
 less usable/approachable". and I think you're seeing a lot of complexity
 that isn't there. Regarding good rationale, I've given that in this thread
 above and in the previous discussion thread, but I'll summarize it again
 here:

 1) "The stated use case is to enumerate the cases of an enum" isn't
 sufficient for designing a protocol because Swift does not have protocols
 that are restricted only to enums. Just as anyone can conform their own
 types to RawRepresentable, anyone should be able to conform their own types
 to ValueEnumerable.

>>>
>>> This is the part of the argument that I am questioning. If the desired
>>> use case is to enumerate the cases of an enum, is it much of a gain to
>>> allow anyone to be able to conform their own non-enum types to this
>>> protocol? Yes, if you buy that, then much of the rest follows. But make no
>>> mistake that it is not necessary to serve the desired use case and
>>> dramatically increases the complexity of the design (see below for just
>>> some considerations).
>>>
>>
>> Some increase in complexity is certainly going to be introduced by
>> generalizing a design to make it useful to more than just a single use
>> case, but I hope you understand that using unquantifiable and subjective
>> qualifiers like "markedly less usable" or "dramatically increases the
>> complexity" is a bit unhelpful when trying to debate specifics. You clearly
>> put a great deal of thought into design problems like this and I always
>> appreciate your points of view, so I want to focus on the objective parts.
>>
>> In prior threads on this topic, I believe I recall you saying that a
>> static property that returns an array is fine. (I don't remember your exact
>> words, so please correct me if I'm wrong. I don't want to misstate your
>> position.) Given the concerns I've pointed out about why that is both a
>> time and memory performance problem, and given your focus on the common use
>> case above, I'd appreciate your opinion on these points:
>>
>> * Are you advocating for a magic protocol that *only* enums can conform
>> to? (This is a different issue than whether the protocol is just a
>> compiler-known protocol that it can synthesize.)
>> * If yes, why intentionally restrict it others from implementing the
>> protocol? That's actually *more* complexity than allowing it, like we do
>> with RawRepresentable. There's also no precedent for "a protocol that can
>> only be applied to enums" in the Swift language. The ramifications of that
>> decision introduce their own design complexity—you're just shifting it
>> around, not avoiding it.
>> * If no, then I don't think we differ on this point.
>>
>
> No magic. Consider: Does the compiler stop me from conforming `UIButton`
> to `Error`? No. Can `UIButton` conform to `Error`? Semantically, no.
>
> I am arguing that the use case justifies a protocol called
> "CaseEnumerable" with documented semantics such that only types with cases
> (i.e., enums with one or more cases) would fulfill those semantics. Any
> more generalization and we are designing without a justification. I'm
> unsure what design complexity you anticipate with such a definition of
> "CaseEnumerable."
>

I don't anticipate any design complexity with that definition. I also don't
see where the design complexity allegedly exists with the more general
version—you've claimed that it 

Re: [swift-evolution] [swift-dev] Re-pitch: Deriving collections of enum cases

2017-11-12 Thread Xiaodi Wu via swift-evolution
On Sun, Nov 12, 2017 at 4:54 AM, Brent Royal-Gordon 
wrote:

> On Nov 10, 2017, at 11:01 PM, Xiaodi Wu  wrote:
>
> Nit: if you want to call it `ValueEnumerable`, then this should be
> `DefaultValueCollection`.
>
>
> I used `DefaultCaseCollection` because, although the protocol can work
> with any type to return its values, this type can only work with enums and
> only returns their cases. `ValueEnumerable` could be sensibly applied to
> `Int`; `DefaultCaseCollection` could not.
>

 Because of how you've chosen to implement `DefaultCaseCollection`, or do
you mean to say that you deliberately want a design where types other than
enums do not share the default return type?

> More generally though, I can see the appeal of allowing `Int` to conform
> to `ValueEnumerable`, but I've got a feeling that this is headed rapidly in
> the direction of overengineering a feature without a good rationale for the
> additional complexity. The stated use case is to enumerate the cases of an
> enum, and any additional complexity above that should stand on its own
> merit. I disagree quite vehemently that protocols should be "as general as
> possible"; rather, they exist to enable useful generic algorithms and
> should be as _useful_ as possible. There is a happy medium beyond which
> overengineering the design makes a protocol markedly less
> usable/approachable for the sake of enabling rare functionality.
>
>
> Tony's "no more specific than they need to" language applies here. The way
> I see it is this:
>
> * `Bool` is not an enum, but it could be usefully conformed to
> `ValueEnumerable`. Why should we prevent that?
> * A type with two independently-switchable `Bool`s—say, `isMirrored` and
> `isFlipped`—could be usefully conformed to `ValueEnumerable`. Why should we
> prevent that?
> * Having integer types conform to `ValueEnumerable` with `static let
> allValues = Self.min...Self.max` could be useful. Why should we prevent
> that?
>

I'd say you're looking at it the wrong way. We're not *preventing*
anything. We're adding a feature, and the question is, why should we *add*
more than is justified by the use case?

Is there a clamor for enumerating the two possible values of `Bool`? If so,
is that not an argument instead to make `Bool` an enum and not a struct
under the hood?
Is there a clamor for enumerating the possible values of a type with two
independently switchable `Bool`s? If so, is that not an argument to make
`Bool` a valid raw value type? (There is already a bug report to make
tuples of raw value types valid raw value types themselves.)
Why is it useful for (fixed-width) integer types to conform to
`ValueEnumerable`? What use cases, exactly, would that enable that are not
possible now?


> And at the same time, a small, specialized collection type _also_ helps
> with our intended use case in some ways (while admittedly making things
> more difficult in others). So I think the more general design, which also
> works better for our intended use case, is the superior option.
>
> Along the lines of user ergonomics, I would advocate for as many enums as
> possible to conform without explicit opt-in. It's true that we are moving
> away from such magical designs, and for good reason, but the gain here of
> enums Just Working(TM) for such a long-demanded feature has, I would argue,
> more benefits than drawbacks. To my mind, the feature is a lot like
> `RawRepresentable` in several ways, and it would be defensible for an equal
> amount of magic to be enabled for it.
>
>
> But `RawRepresentable` *doesn't* get automatically added to all enums—you
> explicitly opt in, albeit using a special sugar syntax. No, I think opt-in
> is the right answer here. We might be able to justify adding sugar to
> opt-in, but I can't actually think of a way to make opting in easier than
> conforming to a protocol and letting the complier synthesize the
> requirements.
>

Yes, you're right that `RawRepresentable` conformance *doesn't* get
automatically added in, but there exists special sugar which makes the end
result indistinguishable. By this I mean that the user gets
`RawRepresentable` conformance without ever writing `Foo :
RawRepresentable` anywhere (and neither do they write `Foo : Bar` where
`Bar` is in turn `RawRepresentable`).

(This is also important for library evolution. A public enum may not want
> to promise that its values will always be enumerable—for instance, it might
> add a case with a non-enumerable associated type in the future. Since
> conformances are always as public as the type itself, we can't have this
> feature be opt-out without moving away from using a protocol.)
>

This is, in fact, a perfect opportunity to bring up a question I've been
leaving implicit. Why not explore moving away from using a protocol? The
proposed protocol has no syntactic requirements, and when constrained only
the use case of enums, it has essentially no semantic requirements either.
It seems 

Re: [swift-evolution] [swift-dev] Re-pitch: Deriving collections of enum cases

2017-11-12 Thread Brent Royal-Gordon via swift-evolution
> On Nov 10, 2017, at 11:01 PM, Xiaodi Wu  wrote:
> 
> Nit: if you want to call it `ValueEnumerable`, then this should be 
> `DefaultValueCollection`.

I used `DefaultCaseCollection` because, although the protocol can work with any 
type to return its values, this type can only work with enums and only returns 
their cases. `ValueEnumerable` could be sensibly applied to `Int`; 
`DefaultCaseCollection` could not.

> More generally though, I can see the appeal of allowing `Int` to conform to 
> `ValueEnumerable`, but I've got a feeling that this is headed rapidly in the 
> direction of overengineering a feature without a good rationale for the 
> additional complexity. The stated use case is to enumerate the cases of an 
> enum, and any additional complexity above that should stand on its own merit. 
> I disagree quite vehemently that protocols should be "as general as 
> possible"; rather, they exist to enable useful generic algorithms and should 
> be as _useful_ as possible. There is a happy medium beyond which 
> overengineering the design makes a protocol markedly less usable/approachable 
> for the sake of enabling rare functionality.

Tony's "no more specific than they need to" language applies here. The way I 
see it is this:

* `Bool` is not an enum, but it could be usefully conformed to 
`ValueEnumerable`. Why should we prevent that?
* A type with two independently-switchable `Bool`s—say, `isMirrored` and 
`isFlipped`—could be usefully conformed to `ValueEnumerable`. Why should we 
prevent that?
* Having integer types conform to `ValueEnumerable` with `static let allValues 
= Self.min...Self.max` could be useful. Why should we prevent that?

And at the same time, a small, specialized collection type _also_ helps with 
our intended use case in some ways (while admittedly making things more 
difficult in others). So I think the more general design, which also works 
better for our intended use case, is the superior option.

> Along the lines of user ergonomics, I would advocate for as many enums as 
> possible to conform without explicit opt-in. It's true that we are moving 
> away from such magical designs, and for good reason, but the gain here of 
> enums Just Working(TM) for such a long-demanded feature has, I would argue, 
> more benefits than drawbacks. To my mind, the feature is a lot like 
> `RawRepresentable` in several ways, and it would be defensible for an equal 
> amount of magic to be enabled for it.


But `RawRepresentable` *doesn't* get automatically added to all enums—you 
explicitly opt in, albeit using a special sugar syntax. No, I think opt-in is 
the right answer here. We might be able to justify adding sugar to opt-in, but 
I can't actually think of a way to make opting in easier than conforming to a 
protocol and letting the complier synthesize the requirements.

(This is also important for library evolution. A public enum may not want to 
promise that its values will always be enumerable—for instance, it might add a 
case with a non-enumerable associated type in the future. Since conformances 
are always as public as the type itself, we can't have this feature be opt-out 
without moving away from using a protocol.)

-- 
Brent Royal-Gordon
Architechies

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


Re: [swift-evolution] [swift-dev] Re-pitch: Deriving collections of enum cases

2017-11-11 Thread Xiaodi Wu via swift-evolution
On Sat, Nov 11, 2017 at 3:15 PM, Tony Allevato 
wrote:

>
>
> On Sat, Nov 11, 2017 at 10:28 AM Xiaodi Wu  wrote:
>
>> On Sat, Nov 11, 2017 at 11:23 AM, Tony Allevato 
>> wrote:
>>
>>>
>>>
>>> On Fri, Nov 10, 2017 at 11:01 PM Xiaodi Wu via swift-evolution <
>>> swift-evolution@swift.org> wrote:
>>>
 Nit: if you want to call it `ValueEnumerable`, then this should be
 `DefaultValueCollection`.

 More generally though, I can see the appeal of allowing `Int` to
 conform to `ValueEnumerable`, but I've got a feeling that this is headed
 rapidly in the direction of overengineering a feature without a good
 rationale for the additional complexity. The stated use case is to
 enumerate the cases of an enum, and any additional complexity above that
 should stand on its own merit. I disagree quite vehemently that protocols
 should be "as general as possible"; rather, they exist to enable useful
 generic algorithms and should be as _useful_ as possible. There is a happy
 medium beyond which overengineering the design makes a protocol markedly
 less usable/approachable for the sake of enabling rare functionality.

>>>
>>> Perhaps "no more specific than they need to be" would have been a better
>>> choice of words on my part than "as general as possible".
>>>
>>> I'm not sure why you think this decision makes the protocol "markedly
>>> less usable/approachable". and I think you're seeing a lot of complexity
>>> that isn't there. Regarding good rationale, I've given that in this thread
>>> above and in the previous discussion thread, but I'll summarize it again
>>> here:
>>>
>>> 1) "The stated use case is to enumerate the cases of an enum" isn't
>>> sufficient for designing a protocol because Swift does not have protocols
>>> that are restricted only to enums. Just as anyone can conform their own
>>> types to RawRepresentable, anyone should be able to conform their own types
>>> to ValueEnumerable.
>>>
>>
>> This is the part of the argument that I am questioning. If the desired
>> use case is to enumerate the cases of an enum, is it much of a gain to
>> allow anyone to be able to conform their own non-enum types to this
>> protocol? Yes, if you buy that, then much of the rest follows. But make no
>> mistake that it is not necessary to serve the desired use case and
>> dramatically increases the complexity of the design (see below for just
>> some considerations).
>>
>
> Some increase in complexity is certainly going to be introduced by
> generalizing a design to make it useful to more than just a single use
> case, but I hope you understand that using unquantifiable and subjective
> qualifiers like "markedly less usable" or "dramatically increases the
> complexity" is a bit unhelpful when trying to debate specifics. You clearly
> put a great deal of thought into design problems like this and I always
> appreciate your points of view, so I want to focus on the objective parts.
>
> In prior threads on this topic, I believe I recall you saying that a
> static property that returns an array is fine. (I don't remember your exact
> words, so please correct me if I'm wrong. I don't want to misstate your
> position.) Given the concerns I've pointed out about why that is both a
> time and memory performance problem, and given your focus on the common use
> case above, I'd appreciate your opinion on these points:
>
> * Are you advocating for a magic protocol that *only* enums can conform
> to? (This is a different issue than whether the protocol is just a
> compiler-known protocol that it can synthesize.)
> * If yes, why intentionally restrict it others from implementing the
> protocol? That's actually *more* complexity than allowing it, like we do
> with RawRepresentable. There's also no precedent for "a protocol that can
> only be applied to enums" in the Swift language. The ramifications of that
> decision introduce their own design complexity—you're just shifting it
> around, not avoiding it.
> * If no, then I don't think we differ on this point.
>

No magic. Consider: Does the compiler stop me from conforming `UIButton` to
`Error`? No. Can `UIButton` conform to `Error`? Semantically, no.

I am arguing that the use case justifies a protocol called "CaseEnumerable"
with documented semantics such that only types with cases (i.e., enums with
one or more cases) would fulfill those semantics. Any more generalization
and we are designing without a justification. I'm unsure what design
complexity you anticipate with such a definition of "CaseEnumerable."

* Do you think that the type of this property should still be an array,
> with all of the performance problems that it brings, or would you find a
> sufficiently array-like but more performant type to be fine?
>

I have no problem with any suitable type if it can be justified, say, on
the grounds of performance or memory efficiency. I do have a 

Re: [swift-evolution] [swift-dev] Re-pitch: Deriving collections of enum cases

2017-11-11 Thread Tony Allevato via swift-evolution
On Sat, Nov 11, 2017 at 10:28 AM Xiaodi Wu  wrote:

> On Sat, Nov 11, 2017 at 11:23 AM, Tony Allevato 
> wrote:
>
>>
>>
>> On Fri, Nov 10, 2017 at 11:01 PM Xiaodi Wu via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>>> Nit: if you want to call it `ValueEnumerable`, then this should be
>>> `DefaultValueCollection`.
>>>
>>> More generally though, I can see the appeal of allowing `Int` to conform
>>> to `ValueEnumerable`, but I've got a feeling that this is headed rapidly in
>>> the direction of overengineering a feature without a good rationale for the
>>> additional complexity. The stated use case is to enumerate the cases of an
>>> enum, and any additional complexity above that should stand on its own
>>> merit. I disagree quite vehemently that protocols should be "as general as
>>> possible"; rather, they exist to enable useful generic algorithms and
>>> should be as _useful_ as possible. There is a happy medium beyond which
>>> overengineering the design makes a protocol markedly less
>>> usable/approachable for the sake of enabling rare functionality.
>>>
>>
>> Perhaps "no more specific than they need to be" would have been a better
>> choice of words on my part than "as general as possible".
>>
>> I'm not sure why you think this decision makes the protocol "markedly
>> less usable/approachable". and I think you're seeing a lot of complexity
>> that isn't there. Regarding good rationale, I've given that in this thread
>> above and in the previous discussion thread, but I'll summarize it again
>> here:
>>
>> 1) "The stated use case is to enumerate the cases of an enum" isn't
>> sufficient for designing a protocol because Swift does not have protocols
>> that are restricted only to enums. Just as anyone can conform their own
>> types to RawRepresentable, anyone should be able to conform their own types
>> to ValueEnumerable.
>>
>
> This is the part of the argument that I am questioning. If the desired use
> case is to enumerate the cases of an enum, is it much of a gain to allow
> anyone to be able to conform their own non-enum types to this protocol?
> Yes, if you buy that, then much of the rest follows. But make no mistake
> that it is not necessary to serve the desired use case and dramatically
> increases the complexity of the design (see below for just some
> considerations).
>

Some increase in complexity is certainly going to be introduced by
generalizing a design to make it useful to more than just a single use
case, but I hope you understand that using unquantifiable and subjective
qualifiers like "markedly less usable" or "dramatically increases the
complexity" is a bit unhelpful when trying to debate specifics. You clearly
put a great deal of thought into design problems like this and I always
appreciate your points of view, so I want to focus on the objective parts.

In prior threads on this topic, I believe I recall you saying that a static
property that returns an array is fine. (I don't remember your exact words,
so please correct me if I'm wrong. I don't want to misstate your position.)
Given the concerns I've pointed out about why that is both a time and
memory performance problem, and given your focus on the common use case
above, I'd appreciate your opinion on these points:

* Are you advocating for a magic protocol that *only* enums can conform to?
(This is a different issue than whether the protocol is just a
compiler-known protocol that it can synthesize.)
* If yes, why intentionally restrict it others from implementing the
protocol? That's actually *more* complexity than allowing it, like we do
with RawRepresentable. There's also no precedent for "a protocol that can
only be applied to enums" in the Swift language. The ramifications of that
decision introduce their own design complexity—you're just shifting it
around, not avoiding it.
* If no, then I don't think we differ on this point.

* Do you think that the type of this property should still be an array,
with all of the performance problems that it brings, or would you find a
sufficiently array-like but more performant type to be fine?


>
>> And once that's allowed, they should be able to do so without imposing an
>> overly restrictive API. What if a custom type has thousands of elements
>> that are easily computed sequentially or from an index? Forcing an Array on
>> the implementor is an unnecessary restriction and a burden. (More on this
>> below.)
>>
>> 2) There is *no decrease in usability for the common use case *by
>> choosing to make the protocol associated type a Sequence instead of a
>> Collection or Array because the concrete type synthesized by the compiler 
>> *would
>> be a more refined concrete type anyway.* In other words, anyone who
>> writes "MyEnum.allValues" would get back an integer-indexable random access
>> collection. I can imagine useful algorithms (more of an
>> algebraic/set-theoretical nature) that could be written for types with
>> 

Re: [swift-evolution] [swift-dev] Re-pitch: Deriving collections of enum cases

2017-11-11 Thread Xiaodi Wu via swift-evolution
On Sat, Nov 11, 2017 at 11:23 AM, Tony Allevato 
wrote:

>
>
> On Fri, Nov 10, 2017 at 11:01 PM Xiaodi Wu via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>> On Sat, Nov 11, 2017 at 12:15 AM, Brent Royal-Gordon via swift-evolution
>>  wrote:
>>
>>> > Personally I like the flexibility provided by the associatedtype, but
>>> I also recognize it won't be incredibly useful for enums — more so if we
>>> wanted to provide e.g. UInt8.allValues, whose ideal implementation might be
>>> "return 0...UInt8.max". So I could see allowing allValues to be any
>>> sequence or collection, but flexibility for allCases might be less
>>> important. Others should weigh in here.
>>>
>>>
>>> I think we should allow any `Collection` (option 3), and I think we
>>> should have a `DefaultCaseCollection` type in the standard library
>>> which encapsulates the interaction with the runtime.
>>>
>>> A `Collection` is good because `Sequence` doesn't provide all of the
>>> guarantees we want—`allValues` should never be single-pass and it should
>>> always be possible to resume iteration at an earlier point, which
>>> `Sequence` doesn't guarantee. (It probably makes sense to use
>>> `BidirectionalCollection`, actually; I'm less sure about
>>> `RandomAccessCollection`.) At the same time, an `Array` ties us to all
>>> sorts of things that are unnecessary at best and harmful at worst, like a
>>> heap allocation. It also forces us into integer indices, which may be
>>> suboptimal for certain use cases (particularly if we later want to support
>>> associated values). And it prevents us from making types like integers
>>> conform, which I think would be a good idea.
>>>
>>> Meanwhile, encapsulating the runtime machinery in
>>> `DefaultCaseCollection` gives users an escape hatch: If the enum you want
>>> to use doesn't conform to `ValueEnumerable`, but you're certain it's
>>> compatible, you can construct a `DefaultCaseCollection` for it.
>>> `DefaultCaseCollection` can be a `RandomAccessCollection` with `Int`
>>> indices, making it convenient to use, but at the same time, it's *not* an
>>> array, so it doesn't have to allocate storage or think about `NSArray`
>>> bridging. And it minimizes the complexity of what the compiler needs to
>>> synthesize.
>>>
>>> public protocol ValueEnumerable {
>>> associatedtype AllValues: BidirectionalCollection where
>>> AllValues.Element == Self
>>> static var allValues: AllValues { get }
>>> }
>>>
>>> // The compiler automatically does `typealias AllValues =
>>> DefaultCaseCollection` if the
>>> // conformance is on the original declaration, the type is
>>> compatible (e.g. no associated values),
>>> // and a different type is neither explicitly specified nor
>>> inferred. That will cause this default
>>> // implementation to be used:
>>> extension ValueEnumerable where AllValues ==
>>> DefaultCaseCollection {
>>> public static var allValues: DefaultCaseCollection
>>> {
>>> return DefaultCaseCollection(unsafeForEnum:
>>> Self.self)
>>> }
>>> }
>>>
>>> public struct DefaultCaseCollection:
>>> RandomAccessCollection {
>>> public var startIndex: Int { return 0 }
>>> public let endIndex: Int
>>>
>>> public init(unsafeForEnum _: Enum.Type) {
>>> endIndex = _countCaseValues(Enum.self)
>>> }
>>>
>>> public subscript(i: Int) -> Enum {
>>> precondition(indices.contains(i), "Case index
>>> out of range")
>>> return Builtin.reinterpretCast(i) as Enum
>>> }
>>> }
>>>
>>
>> Nit: if you want to call it `ValueEnumerable`, then this should be
>> `DefaultValueCollection`.
>>
>> More generally though, I can see the appeal of allowing `Int` to conform
>> to `ValueEnumerable`, but I've got a feeling that this is headed rapidly in
>> the direction of overengineering a feature without a good rationale for the
>> additional complexity. The stated use case is to enumerate the cases of an
>> enum, and any additional complexity above that should stand on its own
>> merit. I disagree quite vehemently that protocols should be "as general as
>> possible"; rather, they exist to enable useful generic algorithms and
>> should be as _useful_ as possible. There is a happy medium beyond which
>> overengineering the design makes a protocol markedly less
>> usable/approachable for the sake of enabling rare functionality.
>>
>
> Perhaps "no more specific than they need to be" would have been a better
> choice of words on my part than "as general as possible".
>
> I'm not sure why you think this decision makes the protocol "markedly less
> usable/approachable". and I think you're seeing a lot of complexity that
> isn't there. Regarding good rationale, I've 

Re: [swift-evolution] [swift-dev] Re-pitch: Deriving collections of enum cases

2017-11-11 Thread Tony Allevato via swift-evolution
On Fri, Nov 10, 2017 at 11:01 PM Xiaodi Wu via swift-evolution <
swift-evolution@swift.org> wrote:

> On Sat, Nov 11, 2017 at 12:15 AM, Brent Royal-Gordon via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>> > Personally I like the flexibility provided by the associatedtype, but I
>> also recognize it won't be incredibly useful for enums — more so if we
>> wanted to provide e.g. UInt8.allValues, whose ideal implementation might be
>> "return 0...UInt8.max". So I could see allowing allValues to be any
>> sequence or collection, but flexibility for allCases might be less
>> important. Others should weigh in here.
>>
>>
>> I think we should allow any `Collection` (option 3), and I think we
>> should have a `DefaultCaseCollection` type in the standard library
>> which encapsulates the interaction with the runtime.
>>
>> A `Collection` is good because `Sequence` doesn't provide all of the
>> guarantees we want—`allValues` should never be single-pass and it should
>> always be possible to resume iteration at an earlier point, which
>> `Sequence` doesn't guarantee. (It probably makes sense to use
>> `BidirectionalCollection`, actually; I'm less sure about
>> `RandomAccessCollection`.) At the same time, an `Array` ties us to all
>> sorts of things that are unnecessary at best and harmful at worst, like a
>> heap allocation. It also forces us into integer indices, which may be
>> suboptimal for certain use cases (particularly if we later want to support
>> associated values). And it prevents us from making types like integers
>> conform, which I think would be a good idea.
>>
>> Meanwhile, encapsulating the runtime machinery in `DefaultCaseCollection`
>> gives users an escape hatch: If the enum you want to use doesn't conform to
>> `ValueEnumerable`, but you're certain it's compatible, you can construct a
>> `DefaultCaseCollection` for it. `DefaultCaseCollection` can be a
>> `RandomAccessCollection` with `Int` indices, making it convenient to use,
>> but at the same time, it's *not* an array, so it doesn't have to allocate
>> storage or think about `NSArray` bridging. And it minimizes the complexity
>> of what the compiler needs to synthesize.
>>
>> public protocol ValueEnumerable {
>> associatedtype AllValues: BidirectionalCollection where
>> AllValues.Element == Self
>> static var allValues: AllValues { get }
>> }
>>
>> // The compiler automatically does `typealias AllValues =
>> DefaultCaseCollection` if the
>> // conformance is on the original declaration, the type is
>> compatible (e.g. no associated values),
>> // and a different type is neither explicitly specified nor
>> inferred. That will cause this default
>> // implementation to be used:
>> extension ValueEnumerable where AllValues ==
>> DefaultCaseCollection {
>> public static var allValues: DefaultCaseCollection {
>> return DefaultCaseCollection(unsafeForEnum:
>> Self.self)
>> }
>> }
>>
>> public struct DefaultCaseCollection: RandomAccessCollection
>> {
>> public var startIndex: Int { return 0 }
>> public let endIndex: Int
>>
>> public init(unsafeForEnum _: Enum.Type) {
>> endIndex = _countCaseValues(Enum.self)
>> }
>>
>> public subscript(i: Int) -> Enum {
>> precondition(indices.contains(i), "Case index out
>> of range")
>> return Builtin.reinterpretCast(i) as Enum
>> }
>> }
>>
>
> Nit: if you want to call it `ValueEnumerable`, then this should be
> `DefaultValueCollection`.
>
> More generally though, I can see the appeal of allowing `Int` to conform
> to `ValueEnumerable`, but I've got a feeling that this is headed rapidly in
> the direction of overengineering a feature without a good rationale for the
> additional complexity. The stated use case is to enumerate the cases of an
> enum, and any additional complexity above that should stand on its own
> merit. I disagree quite vehemently that protocols should be "as general as
> possible"; rather, they exist to enable useful generic algorithms and
> should be as _useful_ as possible. There is a happy medium beyond which
> overengineering the design makes a protocol markedly less
> usable/approachable for the sake of enabling rare functionality.
>

Perhaps "no more specific than they need to be" would have been a better
choice of words on my part than "as general as possible".

I'm not sure why you think this decision makes the protocol "markedly less
usable/approachable". and I think you're seeing a lot of complexity that
isn't there. Regarding good rationale, I've given that in this thread above
and in the previous discussion thread, but I'll summarize it again here:

1) "The stated use case is to enumerate the cases of an enum" isn't
sufficient for designing 

Re: [swift-evolution] [swift-dev] Re-pitch: Deriving collections of enum cases

2017-11-10 Thread Xiaodi Wu via swift-evolution
On Sat, Nov 11, 2017 at 12:15 AM, Brent Royal-Gordon via swift-evolution <
swift-evolution@swift.org> wrote:

> > Personally I like the flexibility provided by the associatedtype, but I
> also recognize it won't be incredibly useful for enums — more so if we
> wanted to provide e.g. UInt8.allValues, whose ideal implementation might be
> "return 0...UInt8.max". So I could see allowing allValues to be any
> sequence or collection, but flexibility for allCases might be less
> important. Others should weigh in here.
>
>
> I think we should allow any `Collection` (option 3), and I think we should
> have a `DefaultCaseCollection` type in the standard library which
> encapsulates the interaction with the runtime.
>
> A `Collection` is good because `Sequence` doesn't provide all of the
> guarantees we want—`allValues` should never be single-pass and it should
> always be possible to resume iteration at an earlier point, which
> `Sequence` doesn't guarantee. (It probably makes sense to use
> `BidirectionalCollection`, actually; I'm less sure about
> `RandomAccessCollection`.) At the same time, an `Array` ties us to all
> sorts of things that are unnecessary at best and harmful at worst, like a
> heap allocation. It also forces us into integer indices, which may be
> suboptimal for certain use cases (particularly if we later want to support
> associated values). And it prevents us from making types like integers
> conform, which I think would be a good idea.
>
> Meanwhile, encapsulating the runtime machinery in `DefaultCaseCollection`
> gives users an escape hatch: If the enum you want to use doesn't conform to
> `ValueEnumerable`, but you're certain it's compatible, you can construct a
> `DefaultCaseCollection` for it. `DefaultCaseCollection` can be a
> `RandomAccessCollection` with `Int` indices, making it convenient to use,
> but at the same time, it's *not* an array, so it doesn't have to allocate
> storage or think about `NSArray` bridging. And it minimizes the complexity
> of what the compiler needs to synthesize.
>
> public protocol ValueEnumerable {
> associatedtype AllValues: BidirectionalCollection where
> AllValues.Element == Self
> static var allValues: AllValues { get }
> }
>
> // The compiler automatically does `typealias AllValues =
> DefaultCaseCollection` if the
> // conformance is on the original declaration, the type is
> compatible (e.g. no associated values),
> // and a different type is neither explicitly specified nor
> inferred. That will cause this default
> // implementation to be used:
> extension ValueEnumerable where AllValues ==
> DefaultCaseCollection {
> public static var allValues: DefaultCaseCollection {
> return DefaultCaseCollection(unsafeForEnum:
> Self.self)
> }
> }
>
> public struct DefaultCaseCollection: RandomAccessCollection {
> public var startIndex: Int { return 0 }
> public let endIndex: Int
>
> public init(unsafeForEnum _: Enum.Type) {
> endIndex = _countCaseValues(Enum.self)
> }
>
> public subscript(i: Int) -> Enum {
> precondition(indices.contains(i), "Case index out
> of range")
> return Builtin.reinterpretCast(i) as Enum
> }
> }
>

Nit: if you want to call it `ValueEnumerable`, then this should be
`DefaultValueCollection`.

More generally though, I can see the appeal of allowing `Int` to conform to
`ValueEnumerable`, but I've got a feeling that this is headed rapidly in
the direction of overengineering a feature without a good rationale for the
additional complexity. The stated use case is to enumerate the cases of an
enum, and any additional complexity above that should stand on its own
merit. I disagree quite vehemently that protocols should be "as general as
possible"; rather, they exist to enable useful generic algorithms and
should be as _useful_ as possible. There is a happy medium beyond which
overengineering the design makes a protocol markedly less
usable/approachable for the sake of enabling rare functionality.

Along the lines of user ergonomics, I would advocate for as many enums as
possible to conform without explicit opt-in. It's true that we are moving
away from such magical designs, and for good reason, but the gain here of
enums Just Working(TM) for such a long-demanded feature has, I would argue,
more benefits than drawbacks. To my mind, the feature is a lot like
`RawRepresentable` in several ways, and it would be defensible for an equal
amount of magic to be enabled for it.
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-dev] Re-pitch: Deriving collections of enum cases

2017-11-10 Thread Brent Royal-Gordon via swift-evolution
> Personally I like the flexibility provided by the associatedtype, but I also 
> recognize it won't be incredibly useful for enums — more so if we wanted to 
> provide e.g. UInt8.allValues, whose ideal implementation might be "return 
> 0...UInt8.max". So I could see allowing allValues to be any sequence or 
> collection, but flexibility for allCases might be less important. Others 
> should weigh in here.


I think we should allow any `Collection` (option 3), and I think we should have 
a `DefaultCaseCollection` type in the standard library which encapsulates 
the interaction with the runtime.

A `Collection` is good because `Sequence` doesn't provide all of the guarantees 
we want—`allValues` should never be single-pass and it should always be 
possible to resume iteration at an earlier point, which `Sequence` doesn't 
guarantee. (It probably makes sense to use `BidirectionalCollection`, actually; 
I'm less sure about `RandomAccessCollection`.) At the same time, an `Array` 
ties us to all sorts of things that are unnecessary at best and harmful at 
worst, like a heap allocation. It also forces us into integer indices, which 
may be suboptimal for certain use cases (particularly if we later want to 
support associated values). And it prevents us from making types like integers 
conform, which I think would be a good idea.

Meanwhile, encapsulating the runtime machinery in `DefaultCaseCollection` gives 
users an escape hatch: If the enum you want to use doesn't conform to 
`ValueEnumerable`, but you're certain it's compatible, you can construct a 
`DefaultCaseCollection` for it. `DefaultCaseCollection` can be a 
`RandomAccessCollection` with `Int` indices, making it convenient to use, but 
at the same time, it's *not* an array, so it doesn't have to allocate storage 
or think about `NSArray` bridging. And it minimizes the complexity of what the 
compiler needs to synthesize.

public protocol ValueEnumerable {
associatedtype AllValues: BidirectionalCollection where 
AllValues.Element == Self
static var allValues: AllValues { get }
}

// The compiler automatically does `typealias AllValues = 
DefaultCaseCollection` if the 
// conformance is on the original declaration, the type is compatible 
(e.g. no associated values), 
// and a different type is neither explicitly specified nor inferred. 
That will cause this default 
// implementation to be used:
extension ValueEnumerable where AllValues == 
DefaultCaseCollection {
public static var allValues: DefaultCaseCollection {
return DefaultCaseCollection(unsafeForEnum: Self.self)
}
}

public struct DefaultCaseCollection: RandomAccessCollection {
public var startIndex: Int { return 0 }
public let endIndex: Int

public init(unsafeForEnum _: Enum.Type) {
endIndex = _countCaseValues(Enum.self)
}

public subscript(i: Int) -> Enum {
precondition(indices.contains(i), "Case index out of 
range")
return Builtin.reinterpretCast(i) as Enum
}
}

-- 
Brent Royal-Gordon
Architechies

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


Re: [swift-evolution] [swift-dev] Re-pitch: Deriving collections of enum cases

2017-11-10 Thread Robert Widmann via swift-evolution

> On Nov 6, 2017, at 2:54 AM, Jacob Bandes-Storch via swift-dev 
>  wrote:
> 
> Over a year ago, we discussed adding a magic "allValues"/"allCases" static 
> property on enums with a compiler-derived implementation. The original 
> proposal PR  has been 
> reopened for Swift 5 after languishing for a while, and I'd like to revisit 
> it and make some changes before it goes up for formal review.
> 
> Prior discussion: 
> https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160411/015098.html
>  
> 
>  (good luck finding the rest of the thread if you weren't on the list at the 
> time...)
> 
> [cc'd swift-dev for importer/availability-related topics below.]
> 
> **Naming**
> 
> Given the complexity gap between a simple enumeration of cases and full 
> support for non-enum types and associated values (which we don't intend to 
> support with this proposal), I think it might be a good idea to adopt the 
> names CaseEnumerable/allCases instead of ValueEnumerable/allValues.
> 
> The original proposal didn't expose allValues as a requirement, for fear of 
> unduly restricting its type. However, if the protocol's scope is more 
> limited, static var allCases can be exposed as a requirement since the 
> implementations are not likely to be complex. Furthermore...
> 
> 
> **Generics**
> 
> Since SE-0142 
> 
>  was implemented in Swift 4, we now have more expressive options for the 
> protocol requirements:
> 
>   // 1 - array only
>   protocol CaseEnumerable {
> static var allCases: [Self] { get }
>   }
> 
>   // 2 - any sequence
>   protocol CaseEnumerable {
> associatedtype CaseSequence: Sequence where CaseSequence.Element == Self
> static var allCases: CaseSequence { get }
>   }
> 
>   // 3 - any collection
>   protocol CaseEnumerable {
> associatedtype CaseCollection: Collection where CaseCollection.Element == 
> Self
> static var allCases: CaseCollection { get }
>   }
> 
> This restricts the CaseEnumerable protocol to be used as a generic 
> constraint, but that'd be true even with a plain array because of the Self 
> type.
> 
> Personally I like the flexibility provided by the associatedtype, but I also 
> recognize it won't be incredibly useful for enums — more so if we wanted to 
> provide e.g. UInt8.allValues, whose ideal implementation might be "return 
> 0...UInt8.max". So I could see allowing allValues to be any sequence or 
> collection, but flexibility for allCases might be less important. Others 
> should weigh in here.

Generalizing the result type is probably a good thing to do before we finalize 
the user-facing component of this.  I wrote the interface with an Array at the 
time because it was easy and because the first implementation of this tried to 
directly synthesize an array literal expression.

> 
> 
> **Implementation strategy and edge cases**
> 
> Last year , Robert 
> Widmann put together an implementation of CaseEnumerable: 
> https://github.com/apple/swift/compare/master...CodaFi:ace-attorney 
>  
> I'd love to hear from anyone more familiar with the code whether there's 
> anything we'd want to change about this approach.
> 
> A few tricky situations have been brought to my attention:
> 
> - Enums imported from C/Obj-C headers. Doug Gregor writes: "The autogenerated 
> allValues would only be able to list the enum cases it knows about from the 
> header it was compiled with. If the library changes to add cases in the 
> future (which, for example, Apple frameworks tend to do), those wouldn’t be 
> captured in allValues."
> 
> My understanding of the runtime/importer is very shallow, but with the 
> current metadata-based strategy, I suspect imported enums couldn't be 
> supported at all, or if they could, the metadata would be generated at import 
> time rather than loaded dynamically from the library, which naturally 
> wouldn't behave the same way when you drop in an upgraded version of the 
> library. Is that correct?

Exactly.  Today, we don’t write out metadata for foreign enumerations and it 
would be interesting to see how that would look if we decide to do so in the 
future.  Either way, leaving it up to the authors of Objective-C/C to create a 
Swift wrapper to get access to this protocol is a little unfortunate, but not 
that big a deal ultimately.

> 
> - Enums with availability annotations on some cases. Doug Gregor writes: "if 
> I have a case that’s only available on macOS 10.12 and newer, it probably 
> shouldn’t show up if I use allValues when running on macOS 10.11."
> 
> If we fetch cases from the enum metadata, does this "just work" since the 
> metadata will