Re: [swift-evolution] final + lazy + fileprivate modifiers

2017-02-15 Thread Matthew Johnson via swift-evolution

> On Feb 15, 2017, at 4:16 PM, David Hart  wrote:
> 
> 
>> On 15 Feb 2017, at 23:15, Matthew Johnson > > wrote:
>> 
>>> 
>>> On Feb 15, 2017, at 4:12 PM, David Hart >> > wrote:
>>> 
 
 On 15 Feb 2017, at 16:31, Matthew Johnson >>> > wrote:
 
 
> On Feb 14, 2017, at 11:31 PM, Chris Lattner via swift-evolution 
> mailto:swift-evolution@swift.org>> wrote:
> 
> 
>> On Feb 14, 2017, at 3:20 AM, David Hart > > wrote:
>> 
>> 
>> On 14 Feb 2017, at 09:25, Goffredo Marocchi > > wrote:
>> 
>>> I disagree with that as well as I still think we are damaging the 
>>> language each time we take a known concept (like access levels) and 
>>> give new meanings to the same keywords. I still look baffled at the 
>>> redefinition of do and the addition of repeat for example...
>>> 
>>> Private, the way it was before, was an admittedly curious take on how 
>>> most languages mean by private and we have jumped through a lot of 
>>> hoops to justify why we did not start with Java/C++/C# like access 
>>> control and augmented it instead of redefining things, omitting others, 
>>> and then constantly pulling the language left and right with not a lot 
>>> of permanent consensus either way as this discussion and others before 
>>> show.
>> 
>> It's a curious take, but it is a curious take is perfectly coherent with 
>> Swift extensions. How else would you access private implementation 
>> details from an extension? But putting it in the same file, instead of 
>> having to resort to an internal access level.
> 
> Right.  Swift is its own language distinct from Java/C++/etc.  While it 
> is intentionally designed to remain familiar (and thus reuses many 
> keywords across the language family), it often does so with slightly 
> different meaning / behavior.  Consider ‘throw’ for example.
> 
> Keeping with the spirit of Swift and staying consistent with its design, 
> I see two plausible meanings for private:
> 
> Private could mean either:
> 1) private to the file (Swift 2 semantics)
> 2) accessible only to the current type/scope and to extensions to that 
> type that are in the current file.
> 
> I don’t think we’ve ever evaluated and debated approach #2 systematically.
 
 I think #2 is an interesting meaning for `private`.  It would have a 
 little bit more similarity to type-scoped `private` in other languages.  
 It would also be applicable in the vast majority of cases where 
 `fileprivate` is currently required.
 
 That said, we very much need a file-scoped access modifier.  This is by 
 far the most important as it allows us to encapsulate access to state that 
 needs to be accessed by more than one type.  I think most people could 
 probably live with `fileprivate` for these use cases if they were allowed 
 to use `private` for the majority of use cases where access is both within 
 a file *and* within the same type.
 
 However, as Brent points out, the SE-0025 meaning of `private` has 
 important use cases.  I would be sad to see these go.  
 
 The big lesson I have taken away from our experience with SE-0025 is that 
 `private` should have remained relevant as the “soft default” file-scoped 
 access modifier but it does not play well with extensions.  It is very 
 common to implement a type using several extensions in the same file and 
 despite having important use cases, SE-0025 `private` does not allow for 
 this.  This means we should not have taken the `private` keyword and 
 instead should have persisted in finding it a name that we can all live 
 with.
 
 If we could come up with a good name for this (not at all a sure thing) I 
 think the best way forward would be:
 
 * retain `fileprivate` - its slight awkwardness will be more acceptable if 
 it indicates a more rare / unusual use case
 * make `private` have the semantics of #2 - it will without question be 
 the right choice in the majority of use cases
 * give scoped access control a new keyword - we still have the ability for 
 tighter encapsulation when necessary and a less common keyword will better 
 highlight that intent 
>>> 
>>> I’d be very strongly against adding yet another private accessor. I brought 
>>> this all up to simplify the access-story, and this goes completely against 
>>> that goal.
>> 
>> Yes, I understand that a lot of people feel strongly that way.  I don’t 
>> expect this to be adopted, I just wanted to offer my opinion.
> 
> Sorry if I came across as violent in my response, I was just being passionate 
> :) Your opinion is of great value to me!

No problem at all, thanks David! 

Re: [swift-evolution] final + lazy + fileprivate modifiers

2017-02-15 Thread Matthew Johnson via swift-evolution

> On Feb 15, 2017, at 4:12 PM, David Hart  wrote:
> 
>> 
>> On 15 Feb 2017, at 16:31, Matthew Johnson > > wrote:
>> 
>> 
>>> On Feb 14, 2017, at 11:31 PM, Chris Lattner via swift-evolution 
>>> mailto:swift-evolution@swift.org>> wrote:
>>> 
>>> 
 On Feb 14, 2017, at 3:20 AM, David Hart >>> > wrote:
 
 
 On 14 Feb 2017, at 09:25, Goffredo Marocchi >>> > wrote:
 
> I disagree with that as well as I still think we are damaging the 
> language each time we take a known concept (like access levels) and give 
> new meanings to the same keywords. I still look baffled at the 
> redefinition of do and the addition of repeat for example...
> 
> Private, the way it was before, was an admittedly curious take on how 
> most languages mean by private and we have jumped through a lot of hoops 
> to justify why we did not start with Java/C++/C# like access control and 
> augmented it instead of redefining things, omitting others, and then 
> constantly pulling the language left and right with not a lot of 
> permanent consensus either way as this discussion and others before show.
 
 It's a curious take, but it is a curious take is perfectly coherent with 
 Swift extensions. How else would you access private implementation details 
 from an extension? But putting it in the same file, instead of having to 
 resort to an internal access level.
>>> 
>>> Right.  Swift is its own language distinct from Java/C++/etc.  While it is 
>>> intentionally designed to remain familiar (and thus reuses many keywords 
>>> across the language family), it often does so with slightly different 
>>> meaning / behavior.  Consider ‘throw’ for example.
>>> 
>>> Keeping with the spirit of Swift and staying consistent with its design, I 
>>> see two plausible meanings for private:
>>> 
>>> Private could mean either:
>>> 1) private to the file (Swift 2 semantics)
>>> 2) accessible only to the current type/scope and to extensions to that type 
>>> that are in the current file.
>>> 
>>> I don’t think we’ve ever evaluated and debated approach #2 systematically.
>> 
>> I think #2 is an interesting meaning for `private`.  It would have a little 
>> bit more similarity to type-scoped `private` in other languages.  It would 
>> also be applicable in the vast majority of cases where `fileprivate` is 
>> currently required.
>> 
>> That said, we very much need a file-scoped access modifier.  This is by far 
>> the most important as it allows us to encapsulate access to state that needs 
>> to be accessed by more than one type.  I think most people could probably 
>> live with `fileprivate` for these use cases if they were allowed to use 
>> `private` for the majority of use cases where access is both within a file 
>> *and* within the same type.
>> 
>> However, as Brent points out, the SE-0025 meaning of `private` has important 
>> use cases.  I would be sad to see these go.  
>> 
>> The big lesson I have taken away from our experience with SE-0025 is that 
>> `private` should have remained relevant as the “soft default” file-scoped 
>> access modifier but it does not play well with extensions.  It is very 
>> common to implement a type using several extensions in the same file and 
>> despite having important use cases, SE-0025 `private` does not allow for 
>> this.  This means we should not have taken the `private` keyword and instead 
>> should have persisted in finding it a name that we can all live with.
>> 
>> If we could come up with a good name for this (not at all a sure thing) I 
>> think the best way forward would be:
>> 
>> * retain `fileprivate` - its slight awkwardness will be more acceptable if 
>> it indicates a more rare / unusual use case
>> * make `private` have the semantics of #2 - it will without question be the 
>> right choice in the majority of use cases
>> * give scoped access control a new keyword - we still have the ability for 
>> tighter encapsulation when necessary and a less common keyword will better 
>> highlight that intent 
> 
> I’d be very strongly against adding yet another private accessor. I brought 
> this all up to simplify the access-story, and this goes completely against 
> that goal.

Yes, I understand that a lot of people feel strongly that way.  I don’t expect 
this to be adopted, I just wanted to offer my opinion.

> 
>> I understand that there probably aren’t too many people in the community 
>> willing to see this level of churn in access modifiers, and probably many 
>> who would view this introduction of "yet another” private access modifier to 
>> be excessive and complex so I don’t plan to push this.  But that is my two 
>> cents about what I think would be ideal.  `private` would be used most of 
>> the time and we would still have the ability to widen or narrow visibility 
>> where necessary, with a more esoteric keyword that draws a rea

Re: [swift-evolution] [Pitch] consistent public access modifiers

2017-02-15 Thread Matthew Johnson via swift-evolution

> On Feb 14, 2017, at 3:43 AM, Brent Royal-Gordon  
> wrote:
> 
>> On Feb 13, 2017, at 7:45 AM, Matthew Johnson  wrote:
>> 
>> If you look closely, when most people say “closed enum” they mean a fixed, 
>> complete set of cases that are all public.  But when people say “closed 
>> protocol” they don’t actually mean a fixed, complete set of conformances 
>> that are all public.  They simply mean clients cannot add conformances.  
>> This is the semantic contract of resilient enums, not closed enums.
> 
> Yes, our traditional terminology here has been a little bit confused.
> 
>>> What I instead suggest is that we think of a closed enum as being like a 
>>> fragile (non-resilient) struct. In both cases, you are committing to a 
>>> particular design for the type. So I think we should give them both the 
>>> same keyword—something like:
>>> 
>>> @fixed struct Person {
>>> var name: String
>>> var birthDate: Date
>>> }
>>> @fixed enum Edge {
>>> case start
>>> case end
>>> }
>>> 
>> 
>> You omitted public here.  Does that mean you intend for `@fixed` to imply 
>> public visibility?  If so, I could get behind this.  But I am curious why 
>> you made it an attribute rather than a keyword.
> 
> No, I'm sorry, I meant to say `@fixed public struct` and `@fixed public 
> enum`. I don't think `@fixed` implies public-ness, either, so it would need 
> to be paired with a `public` keyword. There *may* be keywords we could use 
> that would, like `exposed`, but I'm not sure we want to make this feature so 
> prominent, and I'm not sure how that would work with classes you want to both 
> expose and permit subclassing of. (Would that be `exposed open class Foo`?)

I thought of a couple of other possible keywords.  I had previously mentioned 
`complete` as an alternative to `closed`.  Another option that goes in this 
direction is `total` - it borrows from the mathematical notion of a total 
function.  I’m not sure how I feel about this option and it still doesn’t 
necessarily imply “more public than public” very strongly (only in the sense 
that its totality is known to all which is a rather weak sense).

Another possibility is `transparent`.  This does imply “more public than 
public” a some sense that is similar to `open`.  I know `@transparent` (or 
something like that) has been used as an unsupported(?) attribute hinting to 
the compiler that a function should be made available for inlining (what is the 
current status of this?).  The meaning of this attribute is in some ways 
similar to the meaning you ascribe to `fixed`.  In all cases, this is only 
meaningful for `public` entities so it feels like a promising direction.  

The one thing that makes me somewhat uncomfortable with this approach is that 
in the context of structs and functions it has no semantic impact on user code 
- it is only an optimization, while for enums it wold make a important semantic 
difference to user code.  I’m not sure we should use the same syntax for 
something that is sometimes an optimization and sometimes is semantically 
meaningful.  This concern is relevant regardless of what the keyword is called.

> 
>>> I don't see it mentioned here (maybe I just missed it), but even though we 
>>> *could* do exhaustiveness checking on non-open protocols, I'm not convinced 
>>> that's a good idea. Usually when you have several types conforming to a 
>>> protocol, you should access type-specific behavior through polymorphism, 
>>> not by switching on the protocol. A protocol is supposed to represent a 
>>> behavior, not just mark a type in some arbitrary way.
>> 
>> I agree that you should usually be adding polymorphism, but preventing 
>> exhaustive switch on what is effectively a style argument seems like an 
>> unnecessary restriction to me.  There will be times when it could be used to 
>> good effect.  I think the community has done a pretty good job of figuring 
>> out how to use Swift’s many features well and don’t believe it would be 
>> frequently abused.
> 
> I agree we shouldn't change the language to *prevent* bad style. But this 
> would go beyond that—we'd be putting specific engineering effort solely into 
> *enabling* bad style. At minimum, this should fall so far down our to-do list 
> that we'll probably never get to it.
> 
>>> I still support this general approach. One spelling could simply be 
>>> `@nonopen`. Although if we don't use `closed`, we could simply use 
>>> `@closed` like I suggested—here it really *would* be an antonym to `open`.
>> 
>> I like the idea of using `@nonopen` for the transitional attribute.  Both 
>> because it “removes the openness” that `public protocol` currently implies.  
>> In that sense it is probably the most accurate term we could find and it’s 
>> also pretty concise.
> 
> It also sounds a little bit awkward, which is normally a reason not to use 
> it, but perhaps that's actually a good thing in a temporary, transitional 
> ke

Re: [swift-evolution] [Pitch] consistent public access modifiers

2017-02-15 Thread Matthew Johnson via swift-evolution

> On Feb 15, 2017, at 10:35 AM, Rien  wrote:
> 
>> 
>> On 15 Feb 2017, at 17:02, Matthew Johnson  wrote:
>> 
>>> 
>>> On Feb 15, 2017, at 9:59 AM, Rien  wrote:
>>> 
>>>> 
>>>> On 15 Feb 2017, at 16:45, Matthew Johnson  wrote:
>>>> 
>>>>> 
>>>>> On Feb 15, 2017, at 9:35 AM, Rien  wrote:
>>>>> 
>>>>> 
>>>>>> On 15 Feb 2017, at 16:11, Matthew Johnson via swift-evolution 
>>>>>>  wrote:
>>>>>> 
>>>>>> 
>>>>>>> On Feb 15, 2017, at 5:59 AM, Jeremy Pereira via swift-evolution 
>>>>>>>  wrote:
>>>>>>> 
>>>>>>> 
>>>>>>>> On 15 Feb 2017, at 11:11, Brent Royal-Gordon via swift-evolution 
>>>>>>>>  wrote:
>>>>>>>> 
>>>>>>>> 
>>>>>>>> Our philosophy in general, however, is to default to the behavior 
>>>>>>>> which preserves the most flexibility for the library designer.
>>>>>>> 
>>>>>>> Actually, I thought the philosophy was to preserver type safety. When 
>>>>>>> did that change?
>>>>>>> 
>>>>>>> Also, when was the library designer prioritised ahead of the 
>>>>>>> application developer?
>>>>>>> 
>>>>>>> 
>>>>>>>> Both open and non-open classes are common, but we chose to give 
>>>>>>>> non-open classes the `public` keyword because that's the 
>>>>>>>> flexibility-preserving option.
>>>>>>> 
>>>>>>> No it isn’t, it’s the flexibility restricting option. The consumer of 
>>>>>>> an open class can subclass it. The consumer of a public class cannot 
>>>>>>> subclass it. How is the second more flexible than the first?
>>>>>> 
>>>>>> It reduces complexity for the library author by allowing them to opt-out 
>>>>>> of the complexity involved in supporting unknown, user-defined 
>>>>>> subclasses.  It is important to allow libraries to have this 
>>>>>> flexibility. They are free to declare a class `open` if they want to 
>>>>>> allow subclassing. It’s even possibly for a library to declare all 
>>>>>> classes `open` if it wishes to do so.  But *requiring* that would reduce 
>>>>>> the design space libraries are allowed to explore and / or introduce 
>>>>>> fragility by moving the subclass restriction to a comment.
>>>>>> 
>>>>> 
>>>>> Why would a library author want to prohibit subclasses?
>>>>> A library user can always wrap the class and subclass the wrapper.
>>>> 
>>>> This is composition, not inheritance.  The most important difference is 
>>>> that a wrapper cannot override methods, it can only wrap and / or forward 
>>>> them.  This means that when the superclass calls a method on `self` that 
>>>> method *always* invokes its version of that method rather than a subclass 
>>>> override.  This is a very important difference.
>>>> 
>>> 
>>> Agreed, however that does not answer the question why would a library 
>>> developer want to disallow subclassing?
>>> I do not see a use case for that. I.e. a feature that cannot be implemented 
>>> without it. (without “open”)
>> 
>> The feature it enables is more robust libraries and the ability for library 
>> authors to better reason about their code.  You may not find this benefit 
>> enough to be worth a language feature, but many of us do.
> 
> You start of with a claim “more robust libraries”.
> I would really like to know the “how” of that. How does it make a library 
> more robust?
> 
> I do write libraries myself, and if there is something I am missing, I very 
> much would like to know.

This topic was well explored during the discussion and review of the proposal 
that introduced `open`.  If you would really like to know I suggest you take 
some time to read through that discussion.

> 
> Regards,
> Rien.
> 
>> 
>>> 
>>> Rien.
>>> 
>>>>> 
>>>>> There are cases where subclassing does not make sense. And thus 
>>>>> preventing subclasses adds information for those users that don’t RTFM. 
>>>>> But that imo is not worth the impact extra complexity places on all other 
>>>>> users.
>>>>> 
>>>>> Rien.
>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>>> ___
>>>>>>> swift-evolution mailing list
>>>>>>> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
>>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>>>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>>>>> 
>>>>>> ___
>>>>>> swift-evolution mailing list
>>>>>> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>>>>> <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] [Pitch] consistent public access modifiers

2017-02-15 Thread Matthew Johnson via swift-evolution

> On Feb 15, 2017, at 9:59 AM, Rien  wrote:
> 
>> 
>> On 15 Feb 2017, at 16:45, Matthew Johnson  wrote:
>> 
>>> 
>>> On Feb 15, 2017, at 9:35 AM, Rien  wrote:
>>> 
>>> 
>>>> On 15 Feb 2017, at 16:11, Matthew Johnson via swift-evolution 
>>>>  wrote:
>>>> 
>>>> 
>>>>> On Feb 15, 2017, at 5:59 AM, Jeremy Pereira via swift-evolution 
>>>>>  wrote:
>>>>> 
>>>>> 
>>>>>> On 15 Feb 2017, at 11:11, Brent Royal-Gordon via swift-evolution 
>>>>>>  wrote:
>>>>>> 
>>>>>> 
>>>>>> Our philosophy in general, however, is to default to the behavior which 
>>>>>> preserves the most flexibility for the library designer.
>>>>> 
>>>>> Actually, I thought the philosophy was to preserver type safety. When did 
>>>>> that change?
>>>>> 
>>>>> Also, when was the library designer prioritised ahead of the application 
>>>>> developer?
>>>>> 
>>>>> 
>>>>>> Both open and non-open classes are common, but we chose to give non-open 
>>>>>> classes the `public` keyword because that's the flexibility-preserving 
>>>>>> option.
>>>>> 
>>>>> No it isn’t, it’s the flexibility restricting option. The consumer of an 
>>>>> open class can subclass it. The consumer of a public class cannot 
>>>>> subclass it. How is the second more flexible than the first?
>>>> 
>>>> It reduces complexity for the library author by allowing them to opt-out 
>>>> of the complexity involved in supporting unknown, user-defined subclasses. 
>>>>  It is important to allow libraries to have this flexibility. They are 
>>>> free to declare a class `open` if they want to allow subclassing. It’s 
>>>> even possibly for a library to declare all classes `open` if it wishes to 
>>>> do so.  But *requiring* that would reduce the design space libraries are 
>>>> allowed to explore and / or introduce fragility by moving the subclass 
>>>> restriction to a comment.
>>>> 
>>> 
>>> Why would a library author want to prohibit subclasses?
>>> A library user can always wrap the class and subclass the wrapper.
>> 
>> This is composition, not inheritance.  The most important difference is that 
>> a wrapper cannot override methods, it can only wrap and / or forward them.  
>> This means that when the superclass calls a method on `self` that method 
>> *always* invokes its version of that method rather than a subclass override. 
>>  This is a very important difference.
>> 
> 
> Agreed, however that does not answer the question why would a library 
> developer want to disallow subclassing?
> I do not see a use case for that. I.e. a feature that cannot be implemented 
> without it. (without “open”)

The feature it enables is more robust libraries and the ability for library 
authors to better reason about their code.  You may not find this benefit 
enough to be worth a language feature, but many of us do.

> 
> Rien.
> 
>>> 
>>> There are cases where subclassing does not make sense. And thus preventing 
>>> subclasses adds information for those users that don’t RTFM. But that imo 
>>> is not worth the impact extra complexity places on all other users.
>>> 
>>> Rien.
>>> 
>>>>> 
>>>>> 
>>>>> ___
>>>>> 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] Rules for structs default/memberwise initializers

2017-02-15 Thread Matthew Johnson via swift-evolution
Hi Dimitri,

You may be interested in taking a look at a proposal I introduced about a year 
ago which was deferred.  Memberwise initialization is a topic we intend to 
revisit eventually.  This may happen in phase 2 of the Swift 4 effort, or may 
not happen until Swift 5.

https://github.com/apple/swift-evolution/blob/master/proposals/0018-flexible-memberwise-initialization.md

Matthew

> On Feb 15, 2017, at 9:38 AM, Dimitri Racordon via swift-evolution 
>  wrote:
> 
> Hello community!
> 
> While writing a Swift introduction tutorial for students, I’ve been stumbling 
> upon the rules for struct default and memberwise initializers.
> I failed to find explanations in Apple’s language guide, but as far as I 
> could observe, I think the rules don’t fit interesting use-cases.
> 
> Here are the cases that I was able to identify (I hope you don’t mind 
> millennials and their obligatory Pokemon references):
> 
> First, as documented in Apple’s guide, structs that doesn’t define any 
> initializer and have no default values receive a memberwise initializer:
> 
> typealias Species = (number: Int, name: String)
> 
> struct Pokemon {
> let species: Species
> var level: Int
> var nickname: String
> }
> 
> let bulby = Pokemon(species: (001, "Bulbasaur"), level: 1, nickname: "bulby")
> 
> Structs that define a default value for all their properties receive a 
> default initializer:
> 
> struct Pokemon {
> let species: Species = (001, "Bulbasaur")
> var level: Int = 1
> var nickname: String = "bulby"
> }
> 
> let bulby = Pokemon()
> 
> Now digging a bit deeper, I noticed that they also seem to receive an 
> initializer for their non-constant properties:
> 
> let bulby = Pokemon(level: 1, nickname: "bulby")
> 
> If no value is provided for one (or several) of its variable properties, they 
> receives an initializer for all their variable properties:
> 
> struct Pokemon {
> let species: Species = (001, "Bulbasaur")
> var level: Int = 1
> var nickname: String
> }
> 
> let bulby = Pokemon(level: 1, nickname: "bulby")
> 
> Finally, if they're given a default value for their variable properties but 
> not for their constant properties, they receive the full memberwise 
> initializer only:
> 
> struct Pokemon {
> let species: Species
> var level: Int = 1
> var nickname: String = "bulby"
> }
> 
> let bulby = Pokemon(species: (001, "Bulbasaur"), level: 1, nickname: "bulby")
> 
> If the two extreme cases sounds perfectly valid to me (no default value vs 
> all default values), the mixed situations do not.
> In particular, it seems strange that a struct without a default value for its 
> constant property, but one for all its variable properties receives the 
> memberwise initializer only. I guess that would be a common “mixed situation” 
> case, yet the provided initializer is actually useless.
> 
> Receiving the full memberwise initializer is fine, but I would also expect to 
> receive some kind of "partial memberwise” initializer for all properties 
> (constants or variables) that are not defined:
> 
> struct Pokemon {
> let species: Species
> var level: Int = 1
> var nickname: String = "bulby"
> }
> 
> let bulby = Pokemon(species: (001, "Bulbasaur”))
> print(bulby)
> // Prints "Pokemon(species: (1, "Bulbasaur"), level: 1, nickname: "bulby")"
> 
> Besides, that would avoid some tedious initializer definitions. Indeed, If I 
> want to get the desired result, I have to write this kind of initializer:
> 
> struct Pokemon {
> let species: Species
> var level: Int = 1
> var nickname: String = "bulby"
> 
> init(species: Species, level: Int? = nil, nickname: String? = nil) {
> self.species = species
> 
> if level != nil {
> self.level = level!
> }
> 
> if nickname != nil {
> self.nickname = nickname!
> }
> }
> }
> 
> In addition to be rather wordy, it arguably destroys the purpose of defining 
> a default value for variable properties in the first place, since imho this 
> approach is clearer (unless maybe for some more complicated structs with 
> multiple layers of initializer delegation):
> 
> struct Pokemon {
> let species: Species
> var level: Int
> var nickname: String
> 
> init(species: Species, level: Int = 1, nickname: String = "bulby") {
> self.species = species
> self.level = level
> self.nickname = nickname
> }
> }
> 
> Thanks.
> 
> Dimitri Racordon
> 
> ___
> 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] Simplifying Access Using 'Hidden'

2017-02-15 Thread Matthew Johnson via swift-evolution

> On Feb 15, 2017, at 9:37 AM, Michel Fortin via swift-evolution 
>  wrote:
> 
> 
>> Le 15 févr. 2017 à 9:28, Vladimir.S via swift-evolution 
>>  a écrit :
>> 
>> On 15.02.2017 14:29, Joanna Carter via swift-evolution wrote:
 The beauty of Swift 2's access modifiers was that they were based
 around files and modules, explicitly rejecting types and scopes as
 units for determining visibility. It seems at base there's a group of
 people who reject that decision altogether. Hence, new `private`,
 proposals around `protected`, `friend`, `hidden`, `extensible`, etc.
>>> 
>>> I suppose, for those coming from an Objective-C only background, any
>>> extra visibilities are seen as a bonus.
>>> 
>>> For those coming from a Pascal background, file-based visibility seems
>>> more natural.
>>> 
>>> But for those of us who have used languages like C++ and C#, losing the
>>> visibilities that we have been used to can seriously affect how we think
>>> and design stuff.
>>> 
>> 
>> Was surprised that you expressed exactly what I'm thinking about this 
>> subject.
>> 
>> I do believe even in Swift we need a way to say "only code that *knows* what 
>> it does should see this" and to not force us to write(and manage) the the 
>> code in same file.
>> Yes, some implementation details that shouldn't be used by "users" of the 
>> type, but can be used by "extenders" of our type. At least in the same 
>> module.
>> 
>> While reading, the question was raised(if was discussed, let me know pls): 
>> what if we extend the meaning of 'private' to 'visible to current type/scope 
>> and subtypes and extensions in the *same module*' ?
>> This will help us to split types by files, help to better model access 
>> policy for fields/methods(i.e. only scope that can know about details can 
>> see them) while 'private' still will be hidden outside of the module even 
>> for subclasses/extensions.
>> 
>> So, we'll have such situation:
>> 
>> "modifier" -> "can be accessed from"
>> ---
>> public -> outside of the mondule
>> internal -> inside the module only
>> fileprivate -> the same file only
>> private -> the same type/scope, or subtype, or extension in the same module. 
>> I.e. some kind of 'internal' but scope-oriented.
>> 
>> Actually I still believe we need current 'private' and additionally some 
>> 'protected' with meaning "access from subtype, or extension" probably with 
>> this limitation: "only in the same module". But suggested extended 'private' 
>> will be also OK for me.
>> 
>> Thoughts?
> 
> Here's an idea in three points:
> 
> 1. Return to the Swift 2 definition of `private`.
> 2. Introduce `scoped` to limit the visibility to within the same type, 
> subtype, or extension.
> 3. Allow mixing the two.
> 
> So you have:
> 
>   private // current file
>   private scoped  // current file, in the same type, subtype, or ext.
>   internal// current module
>   internal scoped // current module, in the same type, subtype, or ext.
>   public  // external modules
>   public scoped   // maybe we want that one?
> 
> Since `internal` is implied, using `scoped` alone would be equivalent to 
> `internal scoped`.
> 
> Swift 3's private could be mapped to `private scoped` to achieve (almost) the 
> same results and thus preserve source compatibility.

This definition of `scoped` is actually much different than the current 
`private` which restricts visibility to the *current* scope.  Your definition 
allows visibility in an unlimited number of scopes that just happen to be of 
the same type.  I don’t think `scoped` is a good name for this.  

`private(type)` would be a better name if we were going to make this a 
modification of the existing access modifiers.  However, I don’t think this is 
the right direction.  If we’re going to have an access modifier that means “in 
the same file *and* the same type” I think that should simply be called 
`private` (a “soft default”).  If we’re going to have something between 
`internal` and `fileprivate` I think it would be better to explore submodules 
than introduce something like `internal(type)`.

> 
> -- 
> Michel Fortin
> https://michelf.ca
> 
> ___
> 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] [Pitch] consistent public access modifiers

2017-02-15 Thread Matthew Johnson via swift-evolution

> On Feb 15, 2017, at 9:35 AM, Rien  wrote:
> 
> 
>> On 15 Feb 2017, at 16:11, Matthew Johnson via swift-evolution 
>>  wrote:
>> 
>> 
>>> On Feb 15, 2017, at 5:59 AM, Jeremy Pereira via swift-evolution 
>>>  wrote:
>>> 
>>> 
>>>> On 15 Feb 2017, at 11:11, Brent Royal-Gordon via swift-evolution 
>>>>  wrote:
>>>> 
>>>> 
>>>> Our philosophy in general, however, is to default to the behavior which 
>>>> preserves the most flexibility for the library designer.
>>> 
>>> Actually, I thought the philosophy was to preserver type safety. When did 
>>> that change?
>>> 
>>> Also, when was the library designer prioritised ahead of the application 
>>> developer?
>>> 
>>> 
>>>> Both open and non-open classes are common, but we chose to give non-open 
>>>> classes the `public` keyword because that's the flexibility-preserving 
>>>> option.
>>> 
>>> No it isn’t, it’s the flexibility restricting option. The consumer of an 
>>> open class can subclass it. The consumer of a public class cannot subclass 
>>> it. How is the second more flexible than the first?
>> 
>> It reduces complexity for the library author by allowing them to opt-out of 
>> the complexity involved in supporting unknown, user-defined subclasses.  It 
>> is important to allow libraries to have this flexibility.  They are free to 
>> declare a class `open` if they want to allow subclassing.  It’s even 
>> possibly for a library to declare all classes `open` if it wishes to do so.  
>> But *requiring* that would reduce the design space libraries are allowed to 
>> explore and / or introduce fragility by moving the subclass restriction to a 
>> comment.
>> 
> 
> Why would a library author want to prohibit subclasses?
> A library user can always wrap the class and subclass the wrapper.

This is composition, not inheritance.  The most important difference is that a 
wrapper cannot override methods, it can only wrap and / or forward them.  This 
means that when the superclass calls a method on `self` that method *always* 
invokes its version of that method rather than a subclass override.  This is a 
very important difference.

> 
> There are cases where subclassing does not make sense. And thus preventing 
> subclasses adds information for those users that don’t RTFM. But that imo is 
> not worth the impact extra complexity places on all other users.
> 
> Rien.
> 
>>> 
>>> 
>>> ___
>>> 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] final + lazy + fileprivate modifiers

2017-02-15 Thread Matthew Johnson via swift-evolution

> On Feb 14, 2017, at 11:31 PM, Chris Lattner via swift-evolution 
>  wrote:
> 
> 
>> On Feb 14, 2017, at 3:20 AM, David Hart > > wrote:
>> 
>> 
>> On 14 Feb 2017, at 09:25, Goffredo Marocchi > > wrote:
>> 
>>> I disagree with that as well as I still think we are damaging the language 
>>> each time we take a known concept (like access levels) and give new 
>>> meanings to the same keywords. I still look baffled at the redefinition of 
>>> do and the addition of repeat for example...
>>> 
>>> Private, the way it was before, was an admittedly curious take on how most 
>>> languages mean by private and we have jumped through a lot of hoops to 
>>> justify why we did not start with Java/C++/C# like access control and 
>>> augmented it instead of redefining things, omitting others, and then 
>>> constantly pulling the language left and right with not a lot of permanent 
>>> consensus either way as this discussion and others before show.
>> 
>> It's a curious take, but it is a curious take is perfectly coherent with 
>> Swift extensions. How else would you access private implementation details 
>> from an extension? But putting it in the same file, instead of having to 
>> resort to an internal access level.
> 
> Right.  Swift is its own language distinct from Java/C++/etc.  While it is 
> intentionally designed to remain familiar (and thus reuses many keywords 
> across the language family), it often does so with slightly different meaning 
> / behavior.  Consider ‘throw’ for example.
> 
> Keeping with the spirit of Swift and staying consistent with its design, I 
> see two plausible meanings for private:
> 
> Private could mean either:
> 1) private to the file (Swift 2 semantics)
> 2) accessible only to the current type/scope and to extensions to that type 
> that are in the current file.
> 
> I don’t think we’ve ever evaluated and debated approach #2 systematically.

I think #2 is an interesting meaning for `private`.  It would have a little bit 
more similarity to type-scoped `private` in other languages.  It would also be 
applicable in the vast majority of cases where `fileprivate` is currently 
required.

That said, we very much need a file-scoped access modifier.  This is by far the 
most important as it allows us to encapsulate access to state that needs to be 
accessed by more than one type.  I think most people could probably live with 
`fileprivate` for these use cases if they were allowed to use `private` for the 
majority of use cases where access is both within a file *and* within the same 
type.

However, as Brent points out, the SE-0025 meaning of `private` has important 
use cases.  I would be sad to see these go.  

The big lesson I have taken away from our experience with SE-0025 is that 
`private` should have remained relevant as the “soft default” file-scoped 
access modifier but it does not play well with extensions.  It is very common 
to implement a type using several extensions in the same file and despite 
having important use cases, SE-0025 `private` does not allow for this.  This 
means we should not have taken the `private` keyword and instead should have 
persisted in finding it a name that we can all live with.

If we could come up with a good name for this (not at all a sure thing) I think 
the best way forward would be:

* retain `fileprivate` - its slight awkwardness will be more acceptable if it 
indicates a more rare / unusual use case
* make `private` have the semantics of #2 - it will without question be the 
right choice in the majority of use cases
* give scoped access control a new keyword - we still have the ability for 
tighter encapsulation when necessary and a less common keyword will better 
highlight that intent 

I understand that there probably aren’t too many people in the community 
willing to see this level of churn in access modifiers, and probably many who 
would view this introduction of "yet another” private access modifier to be 
excessive and complex so I don’t plan to push this.  But that is my two cents 
about what I think would be ideal.  `private` would be used most of the time 
and we would still have the ability to widen or narrow visibility where 
necessary, with a more esoteric keyword that draws a reader’s attention.


> 
> -Chris
> 
> ___
> 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] [Pitch] consistent public access modifiers

2017-02-15 Thread Matthew Johnson via swift-evolution

> On Feb 15, 2017, at 5:59 AM, Jeremy Pereira via swift-evolution 
>  wrote:
> 
> 
>> On 15 Feb 2017, at 11:11, Brent Royal-Gordon via swift-evolution 
>>  wrote:
>> 
>> 
>> Our philosophy in general, however, is to default to the behavior which 
>> preserves the most flexibility for the library designer.
> 
> Actually, I thought the philosophy was to preserver type safety. When did 
> that change?
> 
> Also, when was the library designer prioritised ahead of the application 
> developer?
> 
> 
>> Both open and non-open classes are common, but we chose to give non-open 
>> classes the `public` keyword because that's the flexibility-preserving 
>> option.
> 
> No it isn’t, it’s the flexibility restricting option. The consumer of an open 
> class can subclass it. The consumer of a public class cannot subclass it. How 
> is the second more flexible than the first?

It reduces complexity for the library author by allowing them to opt-out of the 
complexity involved in supporting unknown, user-defined subclasses.  It is 
important to allow libraries to have this flexibility.  They are free to 
declare a class `open` if they want to allow subclassing.  It’s even possibly 
for a library to declare all classes `open` if it wishes to do so.  But 
*requiring* that would reduce the design space libraries are allowed to explore 
and / or introduce fragility by moving the subclass restriction to a comment.

> 
> 
> ___
> 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] [Pitch] consistent public access modifiers

2017-02-15 Thread Matthew Johnson via swift-evolution

> On Feb 15, 2017, at 5:52 AM, Jeremy Pereira  
> wrote:
> 
> 
>> On 15 Feb 2017, at 02:16, Xiaodi Wu via swift-evolution 
>>  wrote:
>> 
>> So, perhaps I'm being simplistic here, but--
>> 
>> At the end of the day, aren't we simply trying to enable a resiliency 
>> feature? Could it not be said that an enum where future added cases aren't 
>> source-breaking is a more resilient enum?
>> 
>> Since there is consensus that the status quo is desirable for a lot of use 
>> cases, couldn't we keep spelling it "public enum" and just spell this 
>> proposed more resilient enum "@resilient public enum”?
> 
> If it’s got to be done, this is the best solution, but to my mind, it 
> shouldn’t be done at all. 
> 
> There is no way that a library designer can possibly determine what 
> constitutes “resilient” behaviour on the part of the client software. Maybe 
> adding a default clause is the right thing, but maybe the default clause does 
> something that it shouldn’t for some new enumeration cases. As the client 
> software designer, my only defence is an exhaustive switch statement that 
> relies on the compiler to tell me the it is no longer exhaustive. Yes, it 
> means software in the field will crash until I distribute a new version but 
> that is often preferable to other silent consequences. I really do not want 
> to be forced to add a default to a switch that might reduce the safety of my 
> software.
> 
> Adding new cases to any enumeration where the client software is meant to 
> take different actions based on the different cases is source breaking. End 
> of story. No point in trying to mark them as resilient.
> 
> Adding cases to enumerations that are meant to be passed in to the library 
> e.g. an enumeration that specifies a compositing operation or a string 
> encoding may well not be source breaking (how can you tell in every case?) 
> but it’s unlikely that the client is going to be testing those enumerations 
> in a switch statement anyway.

In order to support adding cases to enums meant to be passed in to a library we 
have to introduce some kind of syntax to distinguish these enums from enums 
that are not resilient.  We’ve been discussing options for how to do this.

> 
> 
> 
>> On Tue, Feb 14, 2017 at 10:09 Matthew Johnson via swift-evolution 
>>  wrote:
>> 
>>> On Feb 14, 2017, at 3:43 AM, Brent Royal-Gordon  
>>> wrote:
>>> 
>>>> On Feb 13, 2017, at 7:45 AM, Matthew Johnson  
>>>> wrote:
>>>> 
>>>> If you look closely, when most people say “closed enum” they mean a fixed, 
>>>> complete set of cases that are all public.  But when people say “closed 
>>>> protocol” they don’t actually mean a fixed, complete set of conformances 
>>>> that are all public.  They simply mean clients cannot add conformances.  
>>>> This is the semantic contract of resilient enums, not closed enums.
>>> 
>>> Yes, our traditional terminology here has been a little bit confused.
>>> 
>>>>> What I instead suggest is that we think of a closed enum as being like a 
>>>>> fragile (non-resilient) struct. In both cases, you are committing to a 
>>>>> particular design for the type. So I think we should give them both the 
>>>>> same keyword—something like:
>>>>> 
>>>>>@fixed struct Person {
>>>>>var name: String
>>>>>var birthDate: Date
>>>>>}
>>>>>@fixed enum Edge {
>>>>>case start
>>>>>case end
>>>>>}
>>>>> 
>>>> 
>>>> You omitted public here.  Does that mean you intend for `@fixed` to imply 
>>>> public visibility?  If so, I could get behind this.  But I am curious why 
>>>> you made it an attribute rather than a keyword.
>>> 
>>> No, I'm sorry, I meant to say `@fixed public struct` and `@fixed public 
>>> enum`. I don't think `@fixed` implies public-ness, either, so it would need 
>>> to be paired with a `public` keyword. There *may* be keywords we could use 
>>> that would, like `exposed`
>> 
>> I agree that `fixed` (and `closed`) don’t imply `public` in terms of the 
>> colloquial meaning of the words and there is a reasonable case that `open` 
>> does.  I’m not sure I like `exposed`, but maybe it’s possible to find a 
>> keyword that would more directly imply `public`.
>> 
>>> , but I'm not sure we want to make this feature so pr

Re: [swift-evolution] [Pitch] consistent public access modifiers

2017-02-15 Thread Matthew Johnson via swift-evolution

> On Feb 15, 2017, at 5:11 AM, Brent Royal-Gordon  
> wrote:
> 
>> On Feb 14, 2017, at 6:16 PM, Xiaodi Wu  wrote:
>> 
>> So, perhaps I'm being simplistic here, but--
>> 
>> At the end of the day, aren't we simply trying to enable a resiliency 
>> feature? Could it not be said that an enum where future added cases aren't 
>> source-breaking is a more resilient enum?
>> 
>> Since there is consensus that the status quo is desirable for a lot of use 
>> cases, couldn't we keep spelling it "public enum" and just spell this 
>> proposed more resilient enum "@resilient public enum"?
> 
> Our philosophy in general, however, is to default to the behavior which 
> preserves the most flexibility for the library designer. Both open and 
> non-open classes are common, but we chose to give non-open classes the 
> `public` keyword because that's the flexibility-preserving option. Resilient 
> enums are definitely the more flexible option, so by that rule, they should 
> have plain `public`.
> 
> I think that, if enums were a brand-new feature being introduced for the 
> first time in Swift 4, there would be no question that `public enum` ought to 
> give you a resilient enum. The only good reason not to do that is source 
> compatibility. So we need to decide: Which of these principles is more 
> important to us?
> 
> 1. "Defaults for public symbols should preserve as much flexibility for 
> designers as possible."
> 
> 2. "Swift 3 code should compile in Swift 4 without deprecation warnings, 
> unmodified and without a version compatibility flag, whenever possible.”

It’s also worth re-iterating the point I have made about inconsistent semantics 
for `public`, and that this problem as well as your first point also impacts 
protocols.  That means we have two reasons to make a change and both impact 
protocols and enums.  We also have a very reasonable way to introduce the 
changes necessary to solve these problems.

I think the changes are worth making, and certainly worthy of at least bringing 
a proposal to review.

> 
> -- 
> Brent Royal-Gordon
> Architechies
> 

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


Re: [swift-evolution] [Pitch] consistent public access modifiers

2017-02-14 Thread Matthew Johnson via swift-evolution

> On Feb 14, 2017, at 3:43 AM, Brent Royal-Gordon  
> wrote:
> 
>> On Feb 13, 2017, at 7:45 AM, Matthew Johnson  wrote:
>> 
>> If you look closely, when most people say “closed enum” they mean a fixed, 
>> complete set of cases that are all public.  But when people say “closed 
>> protocol” they don’t actually mean a fixed, complete set of conformances 
>> that are all public.  They simply mean clients cannot add conformances.  
>> This is the semantic contract of resilient enums, not closed enums.
> 
> Yes, our traditional terminology here has been a little bit confused.
> 
>>> What I instead suggest is that we think of a closed enum as being like a 
>>> fragile (non-resilient) struct. In both cases, you are committing to a 
>>> particular design for the type. So I think we should give them both the 
>>> same keyword—something like:
>>> 
>>> @fixed struct Person {
>>> var name: String
>>> var birthDate: Date
>>> }
>>> @fixed enum Edge {
>>> case start
>>> case end
>>> }
>>> 
>> 
>> You omitted public here.  Does that mean you intend for `@fixed` to imply 
>> public visibility?  If so, I could get behind this.  But I am curious why 
>> you made it an attribute rather than a keyword.
> 
> No, I'm sorry, I meant to say `@fixed public struct` and `@fixed public 
> enum`. I don't think `@fixed` implies public-ness, either, so it would need 
> to be paired with a `public` keyword. There *may* be keywords we could use 
> that would, like `exposed`

I agree that `fixed` (and `closed`) don’t imply `public` in terms of the 
colloquial meaning of the words and there is a reasonable case that `open` 
does.  I’m not sure I like `exposed`, but maybe it’s possible to find a keyword 
that would more directly imply `public`.

> , but I'm not sure we want to make this feature so prominent, 

I have some trouble getting on board with requiring an annotation *in addition* 
to `public` for the reasons I have already stated, and which led to `open` 
becoming an access modifier rather than an annotation.  It’s possible I could 
be convinced otherwise, but I think it would require data showing that this 
really is a rare edge case.  If the relatively frequency of closed vs resilient 
enums is reasonably similar to the relative frequency of public vs open enums I 
think there is a strong case to make them carry the same syntactic weight, as 
we did with `open`.

> and I'm not sure how that would work with classes you want to both expose and 
> permit subclassing of. (Would that be `exposed open class Foo`?)


Can you elaborate on what you mean by "classes you want to both expose and 
permit subclassing of”?  Do you mean commit to the set of fields being fixed 
like you indicated with a struct?  If so, I’m not sure that is a valuable 
combination and my instinct is to ban it.  

If we did want to support something like that it points to keeping `closed` (as 
in cases, subclasses and conformances) orthogonal to `fixed` (as in the set of 
stored properties).

> 
>>> I don't see it mentioned here (maybe I just missed it), but even though we 
>>> *could* do exhaustiveness checking on non-open protocols, I'm not convinced 
>>> that's a good idea. Usually when you have several types conforming to a 
>>> protocol, you should access type-specific behavior through polymorphism, 
>>> not by switching on the protocol. A protocol is supposed to represent a 
>>> behavior, not just mark a type in some arbitrary way.
>> 
>> I agree that you should usually be adding polymorphism, but preventing 
>> exhaustive switch on what is effectively a style argument seems like an 
>> unnecessary restriction to me.  There will be times when it could be used to 
>> good effect.  I think the community has done a pretty good job of figuring 
>> out how to use Swift’s many features well and don’t believe it would be 
>> frequently abused.
> 
> I agree we shouldn't change the language to *prevent* bad style. But this 
> would go beyond that—we'd be putting specific engineering effort solely into 
> *enabling* bad style. At minimum, this should fall so far down our to-do list 
> that we'll probably never get to it.

This assumes that switching over conforming types is bad style.  One of the 
biggest problems with switching over subclasses or conforming types is the fact 
that you don’t get compiler verification of exhaustiveness.  If the language 
supports exhaustive switching for closed classes and protocols this becomes a 
non-issue.

I don’t know of any languages that support a kind of type which supports 
generic and dynamic dispatch as well as exhaustive switch.  It may be 
interesting to have the ability to organize some methods by type (i.e. protocol 
requirements) and other methods by function (i.e. a protocol extension method 
with an exhaustive switch).  

When you have exhaustive switch these are really just two different ways to 
organize code.  Neither one is inherently better.  Each has

Re: [swift-evolution] Class and Subclass Existentials (Round 2)

2017-02-14 Thread Matthew Johnson via swift-evolution
>>> <https://github.com/hartbit/swift-evolution/tree/subclass-existentials#3-when-a-protocol-composition-type-contains-a-typealias-the-validity-of-the-type-is-determined-using-the-following-steps>3.
>>>  When a protocol composition type contains a typealias, the validity of the 
>>> type is determined using the following steps:
>>> 
>>> Expand the typealias
>>> Normalize the type by removing duplicate constraints and replacing less 
>>> specific constraints by more specific constraints (a class constraint is 
>>> less specific than a class type constraint, which is less specific than a 
>>> constraint of a subclass of that class).
>>> Check that the type does not contain two class-type constraints
>> 
>> You could generalize this and instead say that if the type contains two 
>> class-type constraints, the resulting existential type is the common base 
>> class of the two classes, or AnyObject if they do not share a common base 
>> class.
> 
> But if they share a common base class, the existential is invalid. Did I 
> misunderstand your generalization?

Did you mean to say if they *don’t* share a common base class?

> 
>> Also, I’d like to see some discussion about class-constrained existentials 
>> appearing in the inheritance clause of a protocol. IMHO, we should ban this:
>> 
>> typealias MyType = SomeClass & SomeProtocol
>> 
>> protocol SomeOtherProtocol : MyType {}
> 
> Yep, I'll make that clear. It should be disallowed IMHO. Thanks!
> 
>> Slava
>> 
>>> class C {}
>>> class D : C {}
>>> class E {}
>>> protocol P1 {}
>>> protocol P2 {}
>>> typealias TA1 = AnyObject & P1
>>> typealias TA2 = AnyObject & P2
>>> typealias TA3 = C & P2
>>> typealias TA4 = D & P2
>>> typealias TA5 = E & P2
>>> 
>>> typealias TA5 = TA1 & TA2
>>> // Expansion: typealias TA5 = AnyObject & P1 & AnyObject & P2
>>> // Normalization: typealias TA5 = AnyObject & P1 & P2 
>>> // TA5 is valid
>>> 
>>> typealias TA6 = TA1 & TA3
>>> // Expansion: typealias TA6 = AnyObject & P1 & C & P2 
>>> // Normalization (AnyObject < C): typealias TA6 = C & P1 & P2 
>>> // TA6 is valid
>>> 
>>> typealias TA7 = TA3 & TA4
>>> // Expansion: typealias TA7 = C & P2 & D & P2
>>> // Normalization (C < D): typealias TA7 = D & P2
>>> // TA7 is valid
>>> 
>>> typealias TA8 = TA4 & TA5
>>> // Expansion: typealias TA8 = D & P2 & E & P2
>>> // Normalization: typealias TA8 = D & E & P2
>>> // TA8 is invalid because the D and E constraints are incompatible
>>>  
>>> <https://github.com/hartbit/swift-evolution/tree/subclass-existentials#class-and-anyobject>class
>>>  and AnyObject
>>> 
>>> This proposal merges the concepts of class and AnyObject, which now have 
>>> the same meaning: they represent an existential for classes. To get rid of 
>>> the duplication, we suggest only keeping AnyObject around. To reduce 
>>> source-breakage to a minimum, class could be redefined as typealias class = 
>>> AnyObject and give a deprecation warning on class for the first version of 
>>> Swift this proposal is implemented in. Later, class could be removed in a 
>>> subsequent version of Swift.
>>> 
>>>  
>>> <https://github.com/hartbit/swift-evolution/tree/subclass-existentials#source-compatibility>Source
>>>  compatibility
>>> 
>>> This change will not break Swift 3 compability mode because Objective-C 
>>> types will continue to be imported as before. But in Swift 4 mode, all 
>>> types bridged from Objective-C which use the equivalent Objective-C 
>>> existential syntax could break code which does not meet the new protocol 
>>> requirements. For example, the following Objective-C code:
>>> 
>>> @interface MyViewController
>>> - (void)setup:(nonnull 
>>> UIViewController*)tableViewController;
>>> @end
>>> is imported into Swift-3 mode as:
>>> 
>>> class MyViewController {
>>> func setup(tableViewController: UIViewController) {}
>>> }
>>> which allows calling the function with an invalid parameter:
>>> 
>>> let myViewController: MyViewController()
>>> myViewController.setup(UIViewController())
>>> The previous code continues to compile but still crashs 

Re: [swift-evolution] Class and Subclass Existentials (Round 2)

2017-02-14 Thread Matthew Johnson via swift-evolution
gt;> 
>>>> typealias TA6 = TA1 & TA3
>>>> // Expansion: typealias TA6 = AnyObject & P1 & C & P2 
>>>> // Normalization (AnyObject < C): typealias TA6 = C & P1 & P2 
>>>> // TA6 is valid
>>>> 
>>>> typealias TA7 = TA3 & TA4
>>>> // Expansion: typealias TA7 = C & P2 & D & P2
>>>> // Normalization (C < D): typealias TA7 = D & P2
>>>> // TA7 is valid
>>>> 
>>>> typealias TA8 = TA4 & TA5
>>>> // Expansion: typealias TA8 = D & P2 & E & P2
>>>> // Normalization: typealias TA8 = D & E & P2
>>>> // TA8 is invalid because the D and E constraints are incompatible
>>>>  
>>>> <https://github.com/hartbit/swift-evolution/tree/subclass-existentials#class-and-anyobject>class
>>>>  and AnyObject
>>>> 
>>>> This proposal merges the concepts of class and AnyObject, which now have 
>>>> the same meaning: they represent an existential for classes. To get rid of 
>>>> the duplication, we suggest only keeping AnyObject around. To reduce 
>>>> source-breakage to a minimum, class could be redefined as typealias class 
>>>> = AnyObject and give a deprecation warning on class for the first version 
>>>> of Swift this proposal is implemented in. Later, class could be removed in 
>>>> a subsequent version of Swift.
>>>> 
>>>>  
>>>> <https://github.com/hartbit/swift-evolution/tree/subclass-existentials#source-compatibility>Source
>>>>  compatibility
>>>> 
>>>> This change will not break Swift 3 compability mode because Objective-C 
>>>> types will continue to be imported as before. But in Swift 4 mode, all 
>>>> types bridged from Objective-C which use the equivalent Objective-C 
>>>> existential syntax could break code which does not meet the new protocol 
>>>> requirements. For example, the following Objective-C code:
>>>> 
>>>> @interface MyViewController
>>>> - (void)setup:(nonnull 
>>>> UIViewController*)tableViewController;
>>>> @end
>>>> is imported into Swift-3 mode as:
>>>> 
>>>> class MyViewController {
>>>> func setup(tableViewController: UIViewController) {}
>>>> }
>>>> which allows calling the function with an invalid parameter:
>>>> 
>>>> let myViewController: MyViewController()
>>>> myViewController.setup(UIViewController())
>>>> The previous code continues to compile but still crashs if the Objective-C 
>>>> code calls a method of UITableViewDataSource or UITableViewDelegate. But 
>>>> if this proposal is accepted and implemented as-is, the Objective-C code 
>>>> will be imported in Swift 4 mode as:
>>>> 
>>>> class MyViewController {
>>>> func setup(tableViewController: UIViewController & 
>>>> UITableViewDataSource & UITableViewDelegate) {}
>>>> }
>>>> That would then cause the Swift code run in version 4 mode to fail to 
>>>> compile with an error which states that UIViewController does not conform 
>>>> to the UITableViewDataSource and UITableViewDelegate protocols.
>>>> 
>>>>  
>>>> <https://github.com/hartbit/swift-evolution/tree/subclass-existentials#alternatives-considered>Alternatives
>>>>  considered
>>>> 
>>>> An alternative solution to the class/AnyObject duplication was to keep 
>>>> both, redefine AnyObject as typealias AnyObject = class and favor the 
>>>> latter when used as a type name.
>>>> 
>>>>  
>>>> <https://github.com/hartbit/swift-evolution/tree/subclass-existentials#acknowledgements>Acknowledgements
>>>> 
>>>> Thanks to Austin Zheng <http://github.com/austinzheng> and Matthew Johnson 
>>>> <https://github.com/anandabits> who brought a lot of attention to 
>>>> existentials in this mailing-list and from whom most of the ideas in the 
>>>> proposal come from.
>>>> 
>>>>> On 9 Feb 2017, at 21:50, Matthew Johnson >>>> <mailto:matt...@anandabits.com>> wrote:
>>>>> 
>>>>> 
>>>>>> On Feb 9, 2017, at 2:44 PM, David Hart >>>>> <mailto:da...@hartbit.com>> wrote:
>>>>>> 
>>>>>> 
>>>>>> On 9 Feb 2017, a

Re: [swift-evolution] final + lazy + fileprivate modifiers

2017-02-13 Thread Matthew Johnson via swift-evolution

> On Feb 13, 2017, at 12:40 PM, Zach Waldowski via swift-evolution 
>  wrote:
> 
> I still haven't been convinced by this. What are these incredibly large files 
> that people are dealing with, and why should a crucial feature of the 
> language be built around servicing anti patterns?

I agree that it is usually better to avoid having files get too large.  But 
large is relative and subject.  My 27” iMac displays about 100 lines of code at 
a time in Xcode.  `private` can be useful any time you go much beyond that - it 
can help you know that you’re looking at all of the relevant code.  Files in 
the 5-600 line range are pretty common and `private` can become quite useful 
once you start getting to getting that many lines in a file.  Of course this is 
an opinion so your mileage may vary.

> 
> Zachary
> 
> On Mon, Feb 13, 2017, at 01:26 PM, William Sumner via swift-evolution wrote:
>> 
>>> On Feb 12, 2017, at 9:19 AM, David Hart via swift-evolution 
>>> mailto:swift-evolution@swift.org>> wrote:
>>> 
>>> 
>>> Fileprivate 
>>> 
>>> I started the discussion early during the Swift 4 timeframe that I regret 
>>> the change in Swift 3 which introduced a scoped private keyword. For me, 
>>> it's not worth the increase in complexity in access modifiers. I was very 
>>> happy with the file-scope of Swift pre-3. When discussing that, Chris 
>>> Latner mentioned we'd have to wait for Phase 2 to re-discuss it and also 
>>> show proof that people mostly used 'fileprivate' and not the new 'private' 
>>> modifier as proof if we want the proposal to have any weight. Does anybody 
>>> have a good idea for compiling stats from GitHub on this subject? First of 
>>> all, I've always found the GitHub Search quite bad and don't know how much 
>>> it can be trusted. Secondly, because 'private' in Swift 2 and 3 have 
>>> different meanings, a simple textual search might get us wrong results if 
>>> we don't find a way to filter on Swift 3 code.
>> 
>> 
>> I find the “Motivation” section of SE-0025 convincing. Private/fileprivate 
>> allows for distinguishing between shared and hidden details among related 
>> code in a file. Not only is there benefit in knowing intent when reading, 
>> but there is also benefit in writing because the IDE won’t autocomplete 
>> hidden details. I work on large files I’m not the sole author of, so this is 
>> important to me.
>> 
>> Preston
>> ___
>> 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] [Pitch] consistent public access modifiers

2017-02-13 Thread Matthew Johnson via swift-evolution

> On Feb 13, 2017, at 11:28 AM, James Froggatt via swift-evolution 
>  wrote:
> 
> Having loosely followed this discussion, the way I'm thinking of ‘closed’ is 
> as a modifier which would let you switch over something from outside the 
> module in which it is declared.
> 
> From outside the declaring module:
> • A closed enum's cases can be exhaustively switched.
> • A closed protocol's conforming types can be exhaustively switched.
> • A closed class's subclasses can be exhaustively switched.
> 
> If this is correct, I can't help but think ‘closed’ is describing something 
> subtly different in each case - picking and choosing the ‘important’ 
> relationship for each type, while protocols already have a subtyping 
> relationship, and it sounds like there's possibility for enum subtyping in 
> the future.
> 
> I'd rather keep ‘open’ (and a potential future ‘closed’) purely describing 
> the subtyping relationship, and have some other means of labelling 
> conformance and cases as switchable.

I am drafting a manifesto-style document regarding value subtyping which will 
make it clear how value subtypes fit into the picture.  This document covers 
the relationship of enum cases with value subtyping and will show clearly how 
enum cases are analogous to subclasses.

> ___
> 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] [Pitch] consistent public access modifiers

2017-02-13 Thread Matthew Johnson via swift-evolution

> On Feb 13, 2017, at 10:14 AM, Adrian Zubarev via swift-evolution 
>  wrote:
> 
> Is that assumption correct?
> 
> // Module A
> public protocol SQLiteValue {
> init(statement: SQLiteStatement, columnAt index: Int) throws
> func bind(to statement: SQLiteStatement, at index: Int) throws
> }
> 
> // Module B
> protocol SQLiteLoggable : SQLiteValue {
> var logDescription: String { get }
> }
> I could not follow your example there. If SQLiteLoggable is from module B 
> than this should be an error in my opinion.
> 
Yes, Brent was using `public protocol` with the same semantics that `public 
class` has today (i.e. not open) so this would be an error.

> Otherwise open would have less meaning on protocols, because you always could 
> create an empty protocol that has a super public protocol which you’re not 
> allowed to conform to in module B. This would be a silly workaround to being 
> able to conform to it SQLiteValue indirectly without any further requirement 
> like in SQLiteValueConvertible.
> 
> That said, it makes no sense to me to allow that, because it’s simply a 
> workaround to conform to a protocol which public-but-not-open tries to 
> prevent.
> 
> // Module X
> public protocol A {}
> 
> open protocol AA : A { func foo() } // Fine
> 
> // Module Y
> struct B : A {} // Error
> struct B : AA { func foo() { .. } } // Okay
No, `struct B : AA` is an error because in order to conform to `AA`, `B` must 
also conform to `A`, which it cannot because `A` is closed.


> 
> protocol C : A {} // Error because `struct B : C` would equal `struct B : A`
No, this is allowed.  However the only types that can conform to `C` are types 
declared in module X that *already* conform to `A`.  They may be extended to 
retroactively conform to `C`.

> protocol CC : AA {} // Should work even empty, because we have more 
> requirement from `AA`
> public should have a consistent meaning across all types from module A in 
> module B, which is ‘not allowed to sub-type from’ and in case of protocols 
> additionally ‘not allowed to conform to’.
> 
> ___
> 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] [Pitch] consistent public access modifiers

2017-02-13 Thread Matthew Johnson via swift-evolution

> On Feb 13, 2017, at 10:19 AM, Karl Wagner  wrote:
> 
>> 
>>> 
>>> As I mentioned earlier, I don't think `closed` is a good keyword standing 
>>> alone. And I also think that, given that we have `open`, `closed` also 
>>> won't pair well with `public`—they sound like antonyms when they aren’t.
>> 
>> The semantics I am proposing do have an inverse relationship.  That said, it 
>> may not be an intuitive or immediately obvious inverse.  I am certainly not 
>> wedded to the idea of using `closed` as the keyword.
>> 
>>> 
>>> What I instead suggest is that we think of a closed enum as being like a 
>>> fragile (non-resilient) struct. In both cases, you are committing to a 
>>> particular design for the type. So I think we should give them both the 
>>> same keyword—something like:
>>> 
>>> @fixed struct Person {
>>> var name: String
>>> var birthDate: Date
>>> }
>>> @fixed enum Edge {
>>> case start
>>> case end
>>> }
>>> 
>> 
> 
> What about “final”?
> 

Final has a very different meaning: this type has no subtypes.___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Pitch] consistent public access modifiers

2017-02-13 Thread Matthew Johnson via swift-evolution

> On Feb 13, 2017, at 8:24 AM, Brent Royal-Gordon  
> wrote:
> 
> Sorry, I meant to jump in a lot earlier than this, but lost track of this 
> thread on my mental to-do list. I've read most of the thread, but I really 
> can't keep all the replies in my head at once, so I apologize if some of this 
> is duplicative.

Hi Brent, no problem!  Thanks for taking time to read it and offer feedback.

> 
> I agree with Jordan Rose that "closed enums" and "closed protocols" are 
> separate things and they should be discussed separately, so I'll be doing 
> that here. But first, a criticism of both:

I agree that they are separate things.  But there is also important semantic 
overlap.  One of the major motivations behind my proposal is that I think we’re 
ignoring this semantic overlap and therefore being sloppy with our terminology. 
 I think it would be wise to consider carefully whether it is a good idea to 
continue ignoring the overlap.  I think one can make an argument that it 
ignoring it is a pragmatic choice, but one can also make an argument that it is 
hand-wavy.  

If you look closely, when most people say “closed enum” they mean a fixed, 
complete set of cases that are all public.  But when people say “closed 
protocol” they don’t actually mean a fixed, complete set of conformances that 
are all public.  They simply mean clients cannot add conformances.  This is the 
semantic contract of resilient enums, not closed enums.

> 
>> On Feb 8, 2017, at 3:05 PM, Matthew Johnson via swift-evolution 
>>  wrote:
>> 
>> This proposal introduces the new access modifier `closed` as well as 
>> clarifying the meaning of `public` and expanding the use of `open`.
> 
> If the `closed` keyword is to stand alone as an access level, I think 
> `closed` is a bad choice. `open` is acceptable because it sounds as visible 
> or even *more* visible than `public`. (AppKit is "public", but GTK is "open". 
> Which exposes more of itself to a programmer?) But `closed` sounds like some 
> form of privacy. I think that, unless it's paired with a word like `public`, 
> it will not be understood correctly.

This certainly is a fair criticism.  `closed` is the term that has been heavily 
used by the community and is an inverse of `open`, which makes sense because it 
is in many respects a semantic inverse.  That said, I would embrace a healthy 
round of bike shedding to try and find a better keyword.

> 
> Closed enums:
> 
>> A recent thread 
>> (https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170206/031566.html)
>>  discussed a similar tradeoff regarding whether public enums should commit 
>> to a fixed set of cases by default or not.  The current behavior is that 
>> they *do* commit to a fixed set of cases and there is no option (afaik) to 
>> modify that behavior.  The Library Evolution document 
>> (https://github.com/apple/swift/blob/master/docs/LibraryEvolution.rst#enums) 
>> suggests a desire to change this before locking down ABI such that public 
>> enums *do not* make this commitment by default, and are required to opt-in 
>> to this behavior using an `@closed` annotation.
>> 
>> In the previous discussion I stated a strong preference that closed enums 
>> *not* be penalized with an additional annotation.  This is because I feel 
>> pretty strongly that it is a design smell to: 1) expose cases publicly if 
>> consumers of the API are not expected to switch on them and 2) require users 
>> to handle unknown future cases if they are likely to switch over the cases 
>> in correct use of the API.
> 
> The thing is, you do *lots* of things with enums other than exhaustively 
> switching on them. One extremely common example is `Error` enums. But even 
> leaving that aside, there are lots of cases where you construct an enum and 
> hand it off to a library to work or interpret it; adding a case won't break 
> these.
> 
> Basically, when an enum is an input to a library, adding cases is safe. When 
> it's an output from a library, adding cases is potentially unsafe, unless the 
> code using the enum is designed to permit additional cases. 

Yes, I agree with this.  I was overreaching a bit in that paragraph.  My point 
is that you can achieve the same client syntax for library inputs using designs 
that don’t expose cases publicly (i.e. discourage users from writing a switch). 
 Maybe, at least in some cases, that is what a library should do.  Saying it 
*is* a design smell was an exaggeration, but saying it is a contract worthy of 
close consideration is accurate.

> 
>> The conclusion I came to in that thread is that we should adopt the same 
>> strategy as we did with classes: there should not be a d

Re: [swift-evolution] Simplifying Default Access Modifiers

2017-02-13 Thread Matthew Johnson via swift-evolution


Sent from my iPad

> On Feb 13, 2017, at 3:02 AM, Jonathan Hull via swift-evolution 
>  wrote:
> 
> I would like to propose a change to the default access modifier within an 
> enclosing scope.  The default for top level definitions would stay internal, 
> but anything within a scope would by default have the same visibility as it’s 
> enclosing scope.
> 
> The main reason for this is readability/maintainability, and having the 
> intention clearly stand out.  It would also reduce a great amount of 
> boilerplate.  It also matches the mental model of how scopes normally work 
> regarding inheritance of visibility/properties (which means less to teach 
> newbies).
> 
> Right now if I want to make a type and all of it’s vars/methods public, I 
> have to mark each individual var/method public, which leads to a lot of 
> boilerplate/noise and makes everything harder to read:
> 
>public struct MyStruct {
>public var a:Int
>public var b:Int
>private var c:Int
>public var d:Int
>}
> 
> Notice that the private var doesn’t really stand out as such very well.  
> Also, it is exceedingly rare (at least in my own coding style) that I 
> actually want an internal variable unless the type itself is internal, and in 
> those cases, I would like that choice to stand out as deliberate the same way 
> I want ‘private' to stand out.  As it stands, I wait until I think I am done 
> modifying a type to mark it public because of the extra noise generated.  I 
> also make a point to write ‘internal' for things that I explicitly want to 
> restrict to internal.
> 
> Consider the alternative:
> 
>public struct MyStruct {
>var a:Int
>var b:Int
>private var c:Int
>var d:Int
>}

There was a very intentional decision made to *not* do this.  The reason is 
that we don't want to allow a library to accidentally commit to a public API 
contract through an "error of omission".  For example, suppose `d` wasn't 
really intended to be visible outside the module but the author forgot to add 
an `internal` annotation.  This is a problem as soon as the library is 
published.

I think this was the right decision.  It's also worth noting the fact that most 
Swift users have a couple years of experience where omitting the access 
modifier means `internal`.  This means an "error of omission" in this regard is 
more likely for experienced Swift users than it might otherwise be if things 
worked the way you suggest from the beginning.

> 
> Now the fact that I have chosen to make ‘c’ private really stands out much 
> better.  When revisiting the code in 6 months, the struct is much more 
> “glance-able” (as a friend of mine likes to say).
> 
> Note also the nuance that I didn’t say that those vars were marked public (or 
> had the same modifier), I said that they had the SAME VISIBILITY as the 
> enclosing scope (which in this case happens to be public).  This is a concept 
> which is hard to express currently, and IIRC this is what we had to do to 
> make the edge cases of swift 3’s private modifier work properly.  
> 
> Basically, it already works this way for ‘private’, ‘fileprivate’, & 
> ‘internal’, just not for ‘public’ or ‘open’… which can be surprising, 
> especially since you don’t discover these differences until you are working 
> across modules.  We should just extend that mental model up to include public 
> and open.  Migration would just take internal variables of public/open types 
> and mark them explicitly with the word ‘internal'.
> 
> Thanks,
> Jon
> 
> ___
> 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] final + lazy + fileprivate modifiers

2017-02-13 Thread Matthew Johnson via swift-evolution


Sent from my iPad

> On Feb 13, 2017, at 1:35 AM, Rien via swift-evolution 
>  wrote:
> 
> 
>> On 13 Feb 2017, at 06:16, Derrick Ho via swift-evolution 
>>  wrote:
>> 
>> I think I we can live with the original three: public, internal, and private
>> 
>> Where public is visible to all,
>> Internal is visible to all within the module, and private is visible only to 
>> the class and the same file.
>> 
>> We can still fulfill the same roles that the current five fill.
>> 
>> Open can become public again.
>> Public can become final public

This is incorrect.  The way `public` behaves today is very different than 
`final public`.  Today it only restricts clients of a library from subclassing 
the class.  `final public` also prevents the library itself from doing this not 
only in future versions, but also in the current version.  This is very useful 
behavior that is not available if we adopt your suggestion.

>> Internal remains the same
>> Fileprivate assimilates into private
>> 
>> Make access control simple again!
> 
> Agree.
> 
> To me this discussion exemplifies the “square peg in a round hole” problem.
> None of these (fileprivate & open) keywords add information to a source code. 
> They do add noise however.
> 
> The difference between fileprivate and private is only of importance to a 
> group development effort. And then it is used for internal communication 
> within that group, never to the outside world. In a way “private” tells other 
> group members that they should ask the original developer why he choose 
> private instead of fileprivate. (And more than often be told “just change it”)
> This is something that would be better solved by comments imo.

This is not true at all.  I have found the distinction useful both in personal 
projects and in a team environment.

> 
> Open vs public is less obvious as there seems to be a use case for this. 
> However in the end it only “forces” an API user to wrap the “public” 
> interface so he can then use it again as “open”.
> Hence it does not solve a design problem, it only leads to a cumbersome 
> interface.

Composition is often a better approach than inheritance.  Allowing a library to 
expose classes publicly is very valuable.  It allows them the ability to design 
classes that are not intended to be subclasses and have that intent verified by 
the compiler.  Supporting subclassing correctly is difficult and not always 
appropriate.

> 
> 
> Now, if we really want to add information to the source code, then we would 
> do away with the restriction approach entirely and adopt an access list 
> approach. I.e. it would be possible to specify for each interface element 
> which other module/file has access to it.

A long list of access specifications does not lend itself to clarity or 
conciseness.  While it is more specific, it is also far more difficult to 
comprehend.  Swift strikes a pretty good balance of control, clarity of intent 
and conciseness  IMO, but ultimately this is a judgement call.

> 
> Regards,
> Rien
> 
> Site: http://balancingrock.nl
> Blog: http://swiftrien.blogspot.com
> Github: http://github.com/Balancingrock
> Project: http://swiftfire.nl
>> 
> 
>> On Sun, Feb 12, 2017 at 9:42 PM Xiaodi Wu via swift-evolution 
>>  wrote:
>> On Sun, Feb 12, 2017 at 8:37 PM, Dietmar Planitzer  wrote:
>> I know that private was scoped to files before Swift 3.
>> 
>> Fileprivate should obviously be removed because it is, like I said 
>> previously, just a poor man’s package access level. Yes, private was scoped 
>> to a file before Swift 3, but at least there wasn’t two kinds of private for 
>> a single file. Also scoping private to a file makes sense in Swift because 
>> it plays well with the ability to organize the implementation of a type 
>> inside of a file into the base type and a number of extensions. I now have 
>> to use fileprivate in Swift 3 to pull this off while there isn’t a 
>> requirement for a separate private access level. The fileprivate / private 
>> distinction also needlessly gets in the way when you want to refactor an 
>> existing type implementation into base type + extensions, all living in the 
>> same file.
>> 
>> Anyway, I don’t see a good reason why we should end up with this, once 
>> sub-modules exist:
>> 
>> open, public, module, fileprivate, private
>> 
>> when we can live with this:
>> 
>> open, public, module, private
>> 
>> and we’re not losing anything that would be significant compared to the 
>> alternative scenario.
>> 
>> Well, there's also internal: open, public, internal, (submodule, however it 
>> is named), private.
>> 
>> The question being discussed here is whether private should have the old or 
>> new meaning. I tend to agree with others that the new `private` doesn't add 
>> much. Modules are a different conversation.
>> 
>> Regards,
>> 
>> Dietmar Planitzer
>> 
>>> On Feb 12, 2017, at 18:16, Xiaodi Wu  wrote:
>>> 
>>> What was added in Swift 3 was `private`; the old `private` was renamed 
>>> `

Re: [swift-evolution] final + lazy + fileprivate modifiers

2017-02-12 Thread Matthew Johnson via swift-evolution

> On Feb 12, 2017, at 3:52 PM, Xiaodi Wu  wrote:
> 
> On Sun, Feb 12, 2017 at 3:47 PM, Matthew Johnson  > wrote:
> 
>> On Feb 12, 2017, at 3:45 PM, Xiaodi Wu > > wrote:
>> 
>> On Sun, Feb 12, 2017 at 3:24 PM, Matthew Johnson > > wrote:
>> 
>>> On Feb 12, 2017, at 2:35 PM, Xiaodi Wu via swift-evolution 
>>> mailto:swift-evolution@swift.org>> wrote:
>>> 
>>> _Potentially_ meaningful, certainly. But what I'm hearing is that it isn't 
>>> actually meaningful. Here's why:
>>> 
>>> If I see `fileprivate` and can understand that to mean "gee, the author 
>>> _designed_ this member to be visible elsewhere inside the file," then it's 
>>> actually meaningful. OTOH, if I see `fileprivate` and can only deduce "gee, 
>>> the author mashed some button in his or her IDE," then it's not really 
>>> telling me anything.
>> 
>> You’re looking at it backward.  It’s when you see `private` and can deduce 
>> “this member is only visible inside it’s declaring scope” that can be really 
>> helpful.  *This* is what matters.
>> 
>> In what ways can that information help you?
>> 
>>> What you've said above, as I understand it, is that it's not currently 
>>> meaningful to see `fileprivate` because the migrator is writing it and not 
>>> the author. The improved approach you proposed is the additional warning. 
>>> In that case, the compiler will help to ensure that when I see 
>>> `fileprivate`, at least I know it's necessary. But that's only telling me a 
>>> fact (this member is accessed at least once outside the private scope), but 
>>> it's still machine-based bookkeeping, not authorial intent.
>> 
>> The important thing is that this machine-based bookkeeping results in a 
>> proof about the code.  This facilitates reasoning about the code.  You can 
>> make an argument that this proof is not important enough to matter, but you 
>> must admit that this is a real concrete gain in information that is 
>> immediately available to a reader of the code (after they know that it 
>> compiles).  Personally, I find this proof to be valuable.
>> 
>> Comparison has been made to `let` and `var`. In that case, whether a 
>> variable is mutated can be non-trivial to deduce (as Swift has no uniform 
>> scheme for distinguishing mutating from non-mutating functions; the ed/ing 
>> rule has many exceptions). By contrast, here, I don't see any gain in 
>> information. You can literally *see* where the (file)private member is 
>> accessed, and when a file gets too long, even a simple text editor can do a 
>> decent enough find.
>> 
>> If you're right that the real value is that seeing `private` helps you 
>> reason about the code, then that value must be commensurate to how often we 
>> see Swift users amending the migrator to take advantage of it. For me, the 
>> compelling evidence that Swift users don't find this proof to be valuable is 
>> that, by examination of Swift 3 code, Swift users haven't bothered. If we 
>> add a new fix-it to force them to, then of course they'll mash the buttons, 
>> but it's pretty much declaring that they are wrong not to care about what it 
>> seems they do not care at present.
> 
> This is really subjective and it’s not clear to me that there is substantial 
> evidence one way or another.  I know that `private` is valued and used 
> heavily by the teams I have worked with.
> 
> It wasn't a rhetorical question that I asked: what value do you perceive in 
> the new `private` in terms of helping you reason through code?

You are right that any time it really matters it’s not hard to answer the 
question with a search, so it’s largely a convenience.  

That said, I find it quite useful to be able to mark helper methods and types 
within an extension `private` to make it clear that they are indeed local 
helper methods or types that are not accessed more broadly.  This communicates 
an intent.  As long as your extensions don’t get too large, a whole extension 
is usually visible on a single screen on a 27” iMac which is very useful - you 
don’t have to consider code that is scrolled out of sight.

I also find it useful to be able to mark stored properties `private` and 
therefore *not* available to extensions.  This can facilitate tighter 
encapsulation of state, especially when there is a handful of basis methods 
through which the extensions access that state.

> 
> Maybe that’s an exception, but maybe not.  I don’t think we know yet and I 
> think this is what Chris is hoping to learn.
> 
>> 
>>> On Sun, Feb 12, 2017 at 2:14 PM, Chris Lattner >> > wrote:
>>> I don't fully agree: you are right that that is the case when writing code. 
>>>  However, when reading/maintaining code, the distinction is meaningful and 
>>> potentially important.
>>> 
>>> -Chris
>>> 
>>> On Feb 12, 2017, at 12:02 PM, Xiaodi Wu >> > wrote:
>>> 
 If the overwhelming use case is that developers

Re: [swift-evolution] final + lazy + fileprivate modifiers

2017-02-12 Thread Matthew Johnson via swift-evolution

> On Feb 12, 2017, at 3:45 PM, Xiaodi Wu  wrote:
> 
> On Sun, Feb 12, 2017 at 3:24 PM, Matthew Johnson  > wrote:
> 
>> On Feb 12, 2017, at 2:35 PM, Xiaodi Wu via swift-evolution 
>> mailto:swift-evolution@swift.org>> wrote:
>> 
>> _Potentially_ meaningful, certainly. But what I'm hearing is that it isn't 
>> actually meaningful. Here's why:
>> 
>> If I see `fileprivate` and can understand that to mean "gee, the author 
>> _designed_ this member to be visible elsewhere inside the file," then it's 
>> actually meaningful. OTOH, if I see `fileprivate` and can only deduce "gee, 
>> the author mashed some button in his or her IDE," then it's not really 
>> telling me anything.
> 
> You’re looking at it backward.  It’s when you see `private` and can deduce 
> “this member is only visible inside it’s declaring scope” that can be really 
> helpful.  *This* is what matters.
> 
> In what ways can that information help you?
> 
>> What you've said above, as I understand it, is that it's not currently 
>> meaningful to see `fileprivate` because the migrator is writing it and not 
>> the author. The improved approach you proposed is the additional warning. In 
>> that case, the compiler will help to ensure that when I see `fileprivate`, 
>> at least I know it's necessary. But that's only telling me a fact (this 
>> member is accessed at least once outside the private scope), but it's still 
>> machine-based bookkeeping, not authorial intent.
> 
> The important thing is that this machine-based bookkeeping results in a proof 
> about the code.  This facilitates reasoning about the code.  You can make an 
> argument that this proof is not important enough to matter, but you must 
> admit that this is a real concrete gain in information that is immediately 
> available to a reader of the code (after they know that it compiles).  
> Personally, I find this proof to be valuable.
> 
> Comparison has been made to `let` and `var`. In that case, whether a variable 
> is mutated can be non-trivial to deduce (as Swift has no uniform scheme for 
> distinguishing mutating from non-mutating functions; the ed/ing rule has many 
> exceptions). By contrast, here, I don't see any gain in information. You can 
> literally *see* where the (file)private member is accessed, and when a file 
> gets too long, even a simple text editor can do a decent enough find.
> 
> If you're right that the real value is that seeing `private` helps you reason 
> about the code, then that value must be commensurate to how often we see 
> Swift users amending the migrator to take advantage of it. For me, the 
> compelling evidence that Swift users don't find this proof to be valuable is 
> that, by examination of Swift 3 code, Swift users haven't bothered. If we add 
> a new fix-it to force them to, then of course they'll mash the buttons, but 
> it's pretty much declaring that they are wrong not to care about what it 
> seems they do not care at present.

This is really subjective and it’s not clear to me that there is substantial 
evidence one way or another.  I know that `private` is valued and used heavily 
by the teams I have worked with.  Maybe that’s an exception, but maybe not.  I 
don’t think we know yet and I think this is what Chris is hoping to learn.

> 
>> On Sun, Feb 12, 2017 at 2:14 PM, Chris Lattner > > wrote:
>> I don't fully agree: you are right that that is the case when writing code.  
>> However, when reading/maintaining code, the distinction is meaningful and 
>> potentially important.
>> 
>> -Chris
>> 
>> On Feb 12, 2017, at 12:02 PM, Xiaodi Wu > > wrote:
>> 
>>> If the overwhelming use case is that developers should pick one over the 
>>> other primarily because it looks nicer, then blindly click the fix-it when 
>>> things stop working, then the distinction between private and fileprivate 
>>> is pretty clearly a mere nuisance that doesn't carry its own weight.
>>> On Sun, Feb 12, 2017 at 13:33 Jean-Daniel via swift-evolution 
>>> mailto:swift-evolution@swift.org>> wrote:
 Le 12 févr. 2017 à 18:24, Chris Lattner via swift-evolution 
 mailto:swift-evolution@swift.org>> a écrit :
 
 On Feb 12, 2017, at 8:19 AM, David Hart via swift-evolution 
 mailto:swift-evolution@swift.org>> wrote:
> Final
> Can someone tell me what is the use of 'final' now that we have 'public' 
> default to disallowing subclassing in importing modules? I know that 
> 'final' has the added constraint of disallowing subclassing in the same 
> module, but how useful is that? Does it hold its weight? Would we add it 
> now if it did not exist?
 
 As Matthew says, this is still important.
 
> Lazy
> This one is clearer: if Joe Groff's property behaviors proposal from last 
> year is brought forward again, lazy can be demoted from a language 
> keyword to a Standard Library property behavior. If Joe or anybody from 

Re: [swift-evolution] final + lazy + fileprivate modifiers

2017-02-12 Thread Matthew Johnson via swift-evolution

> On Feb 12, 2017, at 2:35 PM, Xiaodi Wu via swift-evolution 
>  wrote:
> 
> _Potentially_ meaningful, certainly. But what I'm hearing is that it isn't 
> actually meaningful. Here's why:
> 
> If I see `fileprivate` and can understand that to mean "gee, the author 
> _designed_ this member to be visible elsewhere inside the file," then it's 
> actually meaningful. OTOH, if I see `fileprivate` and can only deduce "gee, 
> the author mashed some button in his or her IDE," then it's not really 
> telling me anything.

You’re looking at it backward.  It’s when you see `private` and can deduce 
“this member is only visible inside it’s declaring scope” that can be really 
helpful.  *This* is what matters.

> 
> What you've said above, as I understand it, is that it's not currently 
> meaningful to see `fileprivate` because the migrator is writing it and not 
> the author. The improved approach you proposed is the additional warning. In 
> that case, the compiler will help to ensure that when I see `fileprivate`, at 
> least I know it's necessary. But that's only telling me a fact (this member 
> is accessed at least once outside the private scope), but it's still 
> machine-based bookkeeping, not authorial intent.

The important thing is that this machine-based bookkeeping results in a proof 
about the code.  This facilitates reasoning about the code.  You can make an 
argument that this proof is not important enough to matter, but you must admit 
that this is a real concrete gain in information that is immediately available 
to a reader of the code (after they know that it compiles).  Personally, I find 
this proof to be valuable.

> 
> 
> On Sun, Feb 12, 2017 at 2:14 PM, Chris Lattner  > wrote:
> I don't fully agree: you are right that that is the case when writing code.  
> However, when reading/maintaining code, the distinction is meaningful and 
> potentially important.
> 
> -Chris
> 
> On Feb 12, 2017, at 12:02 PM, Xiaodi Wu  > wrote:
> 
>> If the overwhelming use case is that developers should pick one over the 
>> other primarily because it looks nicer, then blindly click the fix-it when 
>> things stop working, then the distinction between private and fileprivate is 
>> pretty clearly a mere nuisance that doesn't carry its own weight.
>> On Sun, Feb 12, 2017 at 13:33 Jean-Daniel via swift-evolution 
>> mailto:swift-evolution@swift.org>> wrote:
>>> Le 12 févr. 2017 à 18:24, Chris Lattner via swift-evolution 
>>> mailto:swift-evolution@swift.org>> a écrit :
>>> 
>>> On Feb 12, 2017, at 8:19 AM, David Hart via swift-evolution 
>>> mailto:swift-evolution@swift.org>> wrote:
 Final
 Can someone tell me what is the use of 'final' now that we have 'public' 
 default to disallowing subclassing in importing modules? I know that 
 'final' has the added constraint of disallowing subclassing in the same 
 module, but how useful is that? Does it hold its weight? Would we add it 
 now if it did not exist?
>>> 
>>> As Matthew says, this is still important.
>>> 
 Lazy
 This one is clearer: if Joe Groff's property behaviors proposal from last 
 year is brought forward again, lazy can be demoted from a language keyword 
 to a Standard Library property behavior. If Joe or anybody from the core 
 team sees this: do we have any luck of having this awesome feature we 
 discussed/designed/implemented in the Swift 4 timeframe?
>>> 
>>> Sadly, there is no chance to get property behaviors into Swift 4.  
>>> Hopefully Swift 5, but it’s impossible to say right now.
>>> 
 Fileprivate 
 
 I started the discussion early during the Swift 4 timeframe that I regret 
 the change in Swift 3 which introduced a scoped private keyword. For me, 
 it's not worth the increase in complexity in access modifiers. I was very 
 happy with the file-scope of Swift pre-3. When discussing that, Chris 
 Latner mentioned we'd have to wait for Phase 2 to re-discuss it and also 
 show proof that people mostly used 'fileprivate' and not the new 'private' 
 modifier as proof if we want the proposal to have any weight. Does anybody 
 have a good idea for compiling stats from GitHub on this subject? First of 
 all, I've always found the GitHub Search quite bad and don't know how much 
 it can be trusted. Secondly, because 'private' in Swift 2 and 3 have 
 different meanings, a simple textual search might get us wrong results if 
 we don't find a way to filter on Swift 3 code.
>>> 
>>> I would still like to re-evaluate fileprivate based on information in the 
>>> field.  The theory of the SE-0025 
>>> (https://github.com/apple/swift-evolution/blob/master/proposals/0025-scoped-access-level.md
>>>  
>>> )
>>>  was that the fileprivate keyword would be used infrequently: this means 
>>> that it would uglify very little 

Re: [swift-evolution] [Pitch] consistent public access modifiers

2017-02-12 Thread Matthew Johnson via swift-evolution

> On Feb 12, 2017, at 10:39 AM, Nevin Brackett-Rozinsky via swift-evolution 
>  wrote:
> 
> Alternative: leave “public enum” as it is now, and spell the resilient 
> version “@resilient enum”

The problem with this approach is that the “default” is the stricter contract 
and library authors have to remember to add the annotation to opt-out of that 
stricter contract.  The problems created by the stricter contract will only 
appear later when the author realizes they need to add new cases and now it’s a 
breaking change.  

Responsible library authors should always make an intentional choice, but 
sometimes even the best of us make mistakes.  If a library author makes this 
mistake it is likely that it won’t be noticed until it is too late.  Requiring 
the library author to make a choice between mutually exclusive options rather 
than a choice to add or omit an annotation reduces the chance of the library 
author making this error.  

This is the rationale that led to us adding `open` rather than adding something 
like an `@closed` annotation for classes.  The desire to avoid growing lots of 
annotations in the language was also an important consideration that I believe 
applies here.

> 
> Nevin
> 
> 
> On Sunday, February 12, 2017, Matthew Johnson via swift-evolution 
> mailto:swift-evolution@swift.org>> wrote:
> 
>> On Feb 12, 2017, at 10:24 AM, David Hart > > wrote:
>> 
>> 
>> On 12 Feb 2017, at 16:38, Matthew Johnson > > wrote:
>> 
>>> 
>>>> On Feb 12, 2017, at 12:50 AM, David Hart >>> > wrote:
>>>> 
>>>> Hi Matthew,
>>>> 
>>>> I've read your proposal ideas and most of the discussions on the thread, 
>>>> and I'd like to provide some personal feedback.
>>>> 
>>>> Swift already has a complicated "access modifier" story so I think we 
>>>> really want a good reason to introduce a new one. And the problem I see is 
>>>> that `closed` has much less semantic weight than the other modifiers.
>>> 
>>> How so?  I’m not sure if I catch your meaning here.  It feels to me like it 
>>> has the same semantic weight as `open`: prohibiting future versions of a 
>>> module from adding cases / subclasses / conformances is roughly the inverse 
>>> of lifting the restriction that clients cannot add those things.  Therefore 
>>> it has roughly the same degree of additional meaning over `public` as 
>>> `open` does.
>> 
>> The difference I see is precisely that 'public' and 'open' modifiers limit 
>> what the client of a module can do while closed limits what future versions 
>> of a module can do. Feels quite different to me.
> 
> This is a reasonable point and is perhaps the strongest argument made against 
> my proposal thus far.  However, I think we have to consider my proposal 
> relative to the alternatives.  
> 
> The only alternative I am aware of is making `public enum` the resilient 
> variety and using `@closed public enum` for the closed variety.  This means 
> that `public` will have at least two different semantics (three if we don’t 
> reconcile classes and protocols).  It also means that the resilient variety 
> is effectively the default.  I am really happy that we decide not to have a 
> default between `open` and `public` and think the best choice is that we 
> don’t have one here either.  The fact that we have a way to do this while 
> solving the inconsistent semantics of `public` feels like a net win to me.
> 
>> 
>>>> 
>>>> First of all, the Library Evolution document you linked says toward at the 
>>>> top that "this document is primarily concerned with binary compatibility, 
>>>> i.e. what changes can safely be made to a library between releases that 
>>>> will not break memory-safety or type-safety, or cause clients to fail to 
>>>> run at all." It seems to me that the @closed introduced in that document 
>>>> is much more about library resilience than about only closing down the 
>>>> addition of new cases: that's why it also talks about reordering and all 
>>>> other changes that can change the memory layout.
>>>> 
>>>> Swift 3 having introduced both fileprivate and open has complexified the 
>>>> access level story for developers and library authors. That complexity is 
>>>> the cost that we have paid for more expressiveness. But if we continue 
>>>> adding new access control modifiers to express new semantics, we may be 
>>>> going too far: perfect is the enemy of good.
>>>> 
>>>>

Re: [swift-evolution] final + lazy + fileprivate modifiers

2017-02-12 Thread Matthew Johnson via swift-evolution

> On Feb 12, 2017, at 10:34 AM, Charlie Monroe via swift-evolution 
>  wrote:
> 
> 
>> On Feb 12, 2017, at 5:19 PM, David Hart via swift-evolution 
>> mailto:swift-evolution@swift.org>> wrote:
>> 
>> I was reading this nice listing of Swift keywords 
>> (https://medium.com/the-traveled-ios-developers-guide/swift-keywords-v-3-0-1-f59783bf26c#.2s2yis3zh
>>  
>> )
>>  and three of them struck me as potentially not long for this world and I 
>> was thinking if we needed/could deprecate them before any kind of ABI 
>> stability set in.
>> 
>> I'm listing them here but it might be worth starting separate discussions 
>> for each of them.
>> 
>> Final
>> 
>> Can someone tell me what is the use of 'final' now that we have 'public' 
>> default to disallowing subclassing in importing modules? I know that 'final' 
>> has the added constraint of disallowing subclassing in the same module, but 
>> how useful is that? Does it hold its weight? Would we add it now if it did 
>> not exist?
> 
> To me, it's useful a lot. The module doesn't necessarily be a 1KLOC framework 
> - I've been recently refactoring a 90KLOC module and the final keyword was 
> fairly useful since some subclasses used hacks by overriding some vars or 
> methods. This allowed me to look at it from a different perspecitve, make 
> some members final and create better API endpoints for customization.
> 
> Not to mention that it allows the compiler to access stored properties 
> directly when they're final - if I recall correctly someone from the core 
> team mentioning that.
> 
>> 
>> Lazy
>> 
>> This one is clearer: if Joe Groff's property behaviors proposal from last 
>> year is brought forward again, lazy can be demoted from a language keyword 
>> to a Standard Library property behavior. If Joe or anybody from the core 
>> team sees this: do we have any luck of having this awesome feature we 
>> discussed/designed/implemented in the Swift 4 timeframe?
>> 
>> Fileprivate 
>> 
>> I started the discussion early during the Swift 4 timeframe that I regret 
>> the change in Swift 3 which introduced a scoped private keyword. For me, 
>> it's not worth the increase in complexity in access modifiers. I was very 
>> happy with the file-scope of Swift pre-3. When discussing that, Chris Latner 
>> mentioned we'd have to wait for Phase 2 to re-discuss it and also show proof 
>> that people mostly used 'fileprivate' and not the new 'private' modifier as 
>> proof if we want the proposal to have any weight. Does anybody have a good 
>> idea for compiling stats from GitHub on this subject? First of all, I've 
>> always found the GitHub Search quite bad and don't know how much it can be 
>> trusted. Secondly, because 'private' in Swift 2 and 3 have different 
>> meanings, a simple textual search might get us wrong results if we don't 
>> find a way to filter on Swift 3 code.
> 
> I like the scoped access, I actually find it useful when declaring several 
> classes within one file, so that I know I'm not accessing that class' private 
> members. That said, I agree that the change to fileprivate was IMHO a mistake 
> - aside from the fact that I dislike the fileprivate keyword, I was more 
> leaning towards the idea that fileprivate would be default for private and 
> when someone really wants to make some member scope-private, private(scope) 
> could be used.

I also like the scoped access control but think we probably made a mistake in 
the choice of keywords.  The problem was that nobody could come up with a name 
for specifying scoped access that had broad consensus.  I hope that if somebody 
identifies a really obviously good keyword for scoped access that we might 
consider making a breaking change to fix this problem.  But I think it would 
have to be very clearly better, and even then may not provide enough benefit to 
justify a breaking change.

> 
>> 
>> Thanks for hearing me out!
>> 
>> David.
>> ___
>> 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] [Pitch] consistent public access modifiers

2017-02-12 Thread Matthew Johnson via swift-evolution
ft, regardless of how we 
>> spell it.  What my proposal aims to do is to incorporate it into a 
>> consistent system of outside-the-module access modifiers.  
>> 
>> One can make a very reasonable argument that access modifiers should *only* 
>> be in the business of talking about visibility and should stay out of the 
>> business of talking about “who can add to the set of cases / subclasses / 
>> conformances”.  The time for that argument was when we had the `open` 
>> discussion last year.  I happen to like the direction we went because it 
>> places `public` and `open` on equal footing.  And now that we *have* decided 
>> to go in this direction, I think we should stick with it when we introduce 
>> `closed`.
>> 
>>>  
>>> David
>>> 
>>> On 9 Feb 2017, at 00:05, Matthew Johnson via swift-evolution 
>>> mailto:swift-evolution@swift.org>> wrote:
>>> 
>>>> I’ve been thinking a lot about our public access modifier story lately in 
>>>> the context of both protocols and enums.  I believe we should move further 
>>>> in the direction we took when introducing the `open` keyword.  I have 
>>>> identified what I think is a promising direction and am interested in 
>>>> feedback from the community.  If community feedback is positive I will 
>>>> flesh this out into a more complete proposal draft.
>>>> 
>>>> 
>>>> Background and Motivation:
>>>> 
>>>> In Swift 3 we had an extended debate regarding whether or not to allow 
>>>> inheritance of public classes by default or to require an annotation for 
>>>> classes that could be subclassed outside the module.  The decision we 
>>>> reached was to avoid having a default at all, and instead make `open` an 
>>>> access modifier.  The result is library authors are required to consider 
>>>> the behavior they wish for each class.  Both behaviors are equally 
>>>> convenient (neither is penalized by requiring an additional boilerplate-y 
>>>> annotation).
>>>> 
>>>> A recent thread 
>>>> (https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170206/031566.html
>>>>  
>>>> <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170206/031566.html>)
>>>>  discussed a similar tradeoff regarding whether public enums should commit 
>>>> to a fixed set of cases by default or not.  The current behavior is that 
>>>> they *do* commit to a fixed set of cases and there is no option (afaik) to 
>>>> modify that behavior.  The Library Evolution document 
>>>> (https://github.com/apple/swift/blob/master/docs/LibraryEvolution.rst#enums
>>>>  
>>>> <https://github.com/apple/swift/blob/master/docs/LibraryEvolution.rst#enums>)
>>>>  suggests a desire to change this before locking down ABI such that public 
>>>> enums *do not* make this commitment by default, and are required to opt-in 
>>>> to this behavior using an `@closed` annotation.
>>>> 
>>>> In the previous discussion I stated a strong preference that closed enums 
>>>> *not* be penalized with an additional annotation.  This is because I feel 
>>>> pretty strongly that it is a design smell to: 1) expose cases publicly if 
>>>> consumers of the API are not expected to switch on them and 2) require 
>>>> users to handle unknown future cases if they are likely to switch over the 
>>>> cases in correct use of the API.
>>>> 
>>>> The conclusion I came to in that thread is that we should adopt the same 
>>>> strategy as we did with classes: there should not be a default.
>>>> 
>>>> There have also been several discussions both on the list and via Twitter 
>>>> regarding whether or not we should allow closed protocols.  In a recent 
>>>> Twitter discussion Joe Groff suggested that we don’t need them because we 
>>>> should use an enum when there is a fixed set of conforming types.  There 
>>>> are at least two  reasons why I still think we *should* add support for 
>>>> closed protocols.
>>>> 
>>>> As noted above (and in the previous thread in more detail), if the set of 
>>>> types (cases) isn’t intended to be fixed (i.e. the library may add new 
>>>> types in the future) an enum is likely not a good choice.  Using a closed 
>>>> protocol discourages the user from switching and prevents the user from 
>>>> adding conformanc

Re: [swift-evolution] final + lazy + fileprivate modifiers

2017-02-12 Thread Matthew Johnson via swift-evolution

> On Feb 12, 2017, at 10:19 AM, David Hart via swift-evolution 
>  wrote:
> 
> I was reading this nice listing of Swift keywords 
> (https://medium.com/the-traveled-ios-developers-guide/swift-keywords-v-3-0-1-f59783bf26c#.2s2yis3zh
>  
> )
>  and three of them struck me as potentially not long for this world and I was 
> thinking if we needed/could deprecate them before any kind of ABI stability 
> set in.
> 
> I'm listing them here but it might be worth starting separate discussions for 
> each of them.
> 
> Final
> 
> Can someone tell me what is the use of 'final' now that we have 'public' 
> default to disallowing subclassing in importing modules? I know that 'final' 
> has the added constraint of disallowing subclassing in the same module, but 
> how useful is that? Does it hold its weight? Would we add it now if it did 
> not exist?

Final is used abundantly by the teams I have worked with.  These are iOS apps 
with no external consumers of the module.  My experience is that it is a very 
useful communication of intent to future readers of the code.

That aside, I think the criteria for a change are different now.  Your criteria 
were relevant during the big breaking change era of Swift 3.  I think the 
criteria for removing a feature at this point should be: is it causing problems 
that justify the breaking change required to remove it?

> 
> Lazy
> 
> This one is clearer: if Joe Groff's property behaviors proposal from last 
> year is brought forward again, lazy can be demoted from a language keyword to 
> a Standard Library property behavior. If Joe or anybody from the core team 
> sees this: do we have any luck of having this awesome feature we 
> discussed/designed/implemented in the Swift 4 timeframe?
> 
> Fileprivate 
> 
> I started the discussion early during the Swift 4 timeframe that I regret the 
> change in Swift 3 which introduced a scoped private keyword. For me, it's not 
> worth the increase in complexity in access modifiers. I was very happy with 
> the file-scope of Swift pre-3. When discussing that, Chris Latner mentioned 
> we'd have to wait for Phase 2 to re-discuss it and also show proof that 
> people mostly used 'fileprivate' and not the new 'private' modifier as proof 
> if we want the proposal to have any weight. Does anybody have a good idea for 
> compiling stats from GitHub on this subject? First of all, I've always found 
> the GitHub Search quite bad and don't know how much it can be trusted. 
> Secondly, because 'private' in Swift 2 and 3 have different meanings, a 
> simple textual search might get us wrong results if we don't find a way to 
> filter on Swift 3 code.
> 
> Thanks for hearing me out!
> 
> David.
> ___
> 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] [Pitch] consistent public access modifiers

2017-02-12 Thread Matthew Johnson via swift-evolution

> On Feb 12, 2017, at 12:50 AM, David Hart  wrote:
> 
> Hi Matthew,
> 
> I've read your proposal ideas and most of the discussions on the thread, and 
> I'd like to provide some personal feedback.
> 
> Swift already has a complicated "access modifier" story so I think we really 
> want a good reason to introduce a new one. And the problem I see is that 
> `closed` has much less semantic weight than the other modifiers.

How so?  I’m not sure if I catch your meaning here.  It feels to me like it has 
the same semantic weight as `open`: prohibiting future versions of a module 
from adding cases / subclasses / conformances is roughly the inverse of lifting 
the restriction that clients cannot add those things.  Therefore it has roughly 
the same degree of additional meaning over `public` as `open` does.

> 
> First of all, the Library Evolution document you linked says toward at the 
> top that "this document is primarily concerned with binary compatibility, 
> i.e. what changes can safely be made to a library between releases that will 
> not break memory-safety or type-safety, or cause clients to fail to run at 
> all." It seems to me that the @closed introduced in that document is much 
> more about library resilience than about only closing down the addition of 
> new cases: that's why it also talks about reordering and all other changes 
> that can change the memory layout.
> 
> Swift 3 having introduced both fileprivate and open has complexified the 
> access level story for developers and library authors. That complexity is the 
> cost that we have paid for more expressiveness. But if we continue adding new 
> access control modifiers to express new semantics, we may be going too far: 
> perfect is the enemy of good.
> 
> Both of those arguments explain why I think closed should be introduced, but 
> only as a rarely-used attribute for library authors which need to express ABI 
> resilience, and not as an extra access modifier.

`closed` is about much more than binary compatibility.  Any time a library 
publishes an enum that clients can reasonably be expected to switch statements 
over the library should strive to make it `closed` wherever possible.  
Otherwise clients are expected to handle unknown future cases by design.  That 
is a design smell if you ask me.  This means that we can expect libraries to 
often carefully design such enums in a way that allows them to be `closed`.  
The use case for resilient enums is in things like mutually exclusive option 
sets received as input to the module and for which it would be unusual for 
clients of the library to write a switch statement over.

With this in mind, `closed` should not be a rarely-used attribute at all.  In 
fact it will often be the best choice.  This is a big motivation behind my 
desire to see it on equal footing with `public` and `open`.

In regards to the complexity of the access model - if you look closely, 
`public` has three subtly different meanings today.  That kind of inconsistency 
is part of the complexity of it.  And as noted, `closed` is a concept that 
*will* play a significant role in Swift, regardless of how we spell it.  What 
my proposal aims to do is to incorporate it into a consistent system of 
outside-the-module access modifiers.  

One can make a very reasonable argument that access modifiers should *only* be 
in the business of talking about visibility and should stay out of the business 
of talking about “who can add to the set of cases / subclasses / conformances”. 
 The time for that argument was when we had the `open` discussion last year.  I 
happen to like the direction we went because it places `public` and `open` on 
equal footing.  And now that we *have* decided to go in this direction, I think 
we should stick with it when we introduce `closed`.

>  
> David
> 
> On 9 Feb 2017, at 00:05, Matthew Johnson via swift-evolution 
> mailto:swift-evolution@swift.org>> wrote:
> 
>> I’ve been thinking a lot about our public access modifier story lately in 
>> the context of both protocols and enums.  I believe we should move further 
>> in the direction we took when introducing the `open` keyword.  I have 
>> identified what I think is a promising direction and am interested in 
>> feedback from the community.  If community feedback is positive I will flesh 
>> this out into a more complete proposal draft.
>> 
>> 
>> Background and Motivation:
>> 
>> In Swift 3 we had an extended debate regarding whether or not to allow 
>> inheritance of public classes by default or to require an annotation for 
>> classes that could be subclassed outside the module.  The decision we 
>> reached was to avoid having a default at all, and instead make `open` an 
>> access modifier.  The result is 

Re: [swift-evolution] [Pitch] consistent public access modifiers

2017-02-12 Thread Matthew Johnson via swift-evolution

> On Feb 11, 2017, at 4:41 PM, Karl Wagner  wrote:
> 
> 
>> On 11 Feb 2017, at 20:50, Matthew Johnson via swift-evolution 
>> mailto:swift-evolution@swift.org>> wrote:
>> 
>>> 
>>> On Feb 11, 2017, at 12:40 PM, Xiaodi Wu >> <mailto:xiaodi...@gmail.com>> wrote:
>>> 
>>> On Sat, Feb 11, 2017 at 6:41 AM, Matthew Johnson >> <mailto:matt...@anandabits.com>> wrote:
>>> 
>>> 
>>> Sent from my iPad
>>> 
>>> On Feb 10, 2017, at 9:48 PM, Xiaodi Wu >> <mailto:xiaodi...@gmail.com>> wrote:
>>> 
>>>> On Wed, Feb 8, 2017 at 5:05 PM, Matthew Johnson via swift-evolution 
>>>> mailto:swift-evolution@swift.org>> wrote:
>>>> I’ve been thinking a lot about our public access modifier story lately in 
>>>> the context of both protocols and enums.  I believe we should move further 
>>>> in the direction we took when introducing the `open` keyword.  I have 
>>>> identified what I think is a promising direction and am interested in 
>>>> feedback from the community.  If community feedback is positive I will 
>>>> flesh this out into a more complete proposal draft.
>>>> 
>>>> 
>>>> Background and Motivation:
>>>> 
>>>> In Swift 3 we had an extended debate regarding whether or not to allow 
>>>> inheritance of public classes by default or to require an annotation for 
>>>> classes that could be subclassed outside the module.  The decision we 
>>>> reached was to avoid having a default at all, and instead make `open` an 
>>>> access modifier.  The result is library authors are required to consider 
>>>> the behavior they wish for each class.  Both behaviors are equally 
>>>> convenient (neither is penalized by requiring an additional boilerplate-y 
>>>> annotation).
>>>> 
>>>> A recent thread 
>>>> (https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170206/031566.html
>>>>  
>>>> <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170206/031566.html>)
>>>>  discussed a similar tradeoff regarding whether public enums should commit 
>>>> to a fixed set of cases by default or not.  The current behavior is that 
>>>> they *do* commit to a fixed set of cases and there is no option (afaik) to 
>>>> modify that behavior.  The Library Evolution document 
>>>> (https://github.com/apple/swift/blob/master/docs/LibraryEvolution.rst#enums
>>>>  
>>>> <https://github.com/apple/swift/blob/master/docs/LibraryEvolution.rst#enums>)
>>>>  suggests a desire to change this before locking down ABI such that public 
>>>> enums *do not* make this commitment by default, and are required to opt-in 
>>>> to this behavior using an `@closed` annotation.
>>>> 
>>>> In the previous discussion I stated a strong preference that closed enums 
>>>> *not* be penalized with an additional annotation.  This is because I feel 
>>>> pretty strongly that it is a design smell to: 1) expose cases publicly if 
>>>> consumers of the API are not expected to switch on them and 2) require 
>>>> users to handle unknown future cases if they are likely to switch over the 
>>>> cases in correct use of the API.
>>>> 
>>>> The conclusion I came to in that thread is that we should adopt the same 
>>>> strategy as we did with classes: there should not be a default.
>>>> 
>>>> There have also been several discussions both on the list and via Twitter 
>>>> regarding whether or not we should allow closed protocols.  In a recent 
>>>> Twitter discussion Joe Groff suggested that we don’t need them because we 
>>>> should use an enum when there is a fixed set of conforming types.  There 
>>>> are at least two  reasons why I still think we *should* add support for 
>>>> closed protocols.
>>>> 
>>>> As noted above (and in the previous thread in more detail), if the set of 
>>>> types (cases) isn’t intended to be fixed (i.e. the library may add new 
>>>> types in the future) an enum is likely not a good choice.  Using a closed 
>>>> protocol discourages the user from switching and prevents the user from 
>>>> adding conformances that are not desired.
>>>> 
>>>> Another use case supported by closed protocols is a design where users are 
>>>> not allowed to

Re: [swift-evolution] [Pitch] consistent public access modifiers

2017-02-11 Thread Matthew Johnson via swift-evolution

> On Feb 11, 2017, at 12:40 PM, Xiaodi Wu  wrote:
> 
> On Sat, Feb 11, 2017 at 6:41 AM, Matthew Johnson  <mailto:matt...@anandabits.com>> wrote:
> 
> 
> Sent from my iPad
> 
> On Feb 10, 2017, at 9:48 PM, Xiaodi Wu  <mailto:xiaodi...@gmail.com>> wrote:
> 
>> On Wed, Feb 8, 2017 at 5:05 PM, Matthew Johnson via swift-evolution 
>> mailto:swift-evolution@swift.org>> wrote:
>> I’ve been thinking a lot about our public access modifier story lately in 
>> the context of both protocols and enums.  I believe we should move further 
>> in the direction we took when introducing the `open` keyword.  I have 
>> identified what I think is a promising direction and am interested in 
>> feedback from the community.  If community feedback is positive I will flesh 
>> this out into a more complete proposal draft.
>> 
>> 
>> Background and Motivation:
>> 
>> In Swift 3 we had an extended debate regarding whether or not to allow 
>> inheritance of public classes by default or to require an annotation for 
>> classes that could be subclassed outside the module.  The decision we 
>> reached was to avoid having a default at all, and instead make `open` an 
>> access modifier.  The result is library authors are required to consider the 
>> behavior they wish for each class.  Both behaviors are equally convenient 
>> (neither is penalized by requiring an additional boilerplate-y annotation).
>> 
>> A recent thread 
>> (https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170206/031566.html
>>  
>> <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170206/031566.html>)
>>  discussed a similar tradeoff regarding whether public enums should commit 
>> to a fixed set of cases by default or not.  The current behavior is that 
>> they *do* commit to a fixed set of cases and there is no option (afaik) to 
>> modify that behavior.  The Library Evolution document 
>> (https://github.com/apple/swift/blob/master/docs/LibraryEvolution.rst#enums 
>> <https://github.com/apple/swift/blob/master/docs/LibraryEvolution.rst#enums>)
>>  suggests a desire to change this before locking down ABI such that public 
>> enums *do not* make this commitment by default, and are required to opt-in 
>> to this behavior using an `@closed` annotation.
>> 
>> In the previous discussion I stated a strong preference that closed enums 
>> *not* be penalized with an additional annotation.  This is because I feel 
>> pretty strongly that it is a design smell to: 1) expose cases publicly if 
>> consumers of the API are not expected to switch on them and 2) require users 
>> to handle unknown future cases if they are likely to switch over the cases 
>> in correct use of the API.
>> 
>> The conclusion I came to in that thread is that we should adopt the same 
>> strategy as we did with classes: there should not be a default.
>> 
>> There have also been several discussions both on the list and via Twitter 
>> regarding whether or not we should allow closed protocols.  In a recent 
>> Twitter discussion Joe Groff suggested that we don’t need them because we 
>> should use an enum when there is a fixed set of conforming types.  There are 
>> at least two  reasons why I still think we *should* add support for closed 
>> protocols.
>> 
>> As noted above (and in the previous thread in more detail), if the set of 
>> types (cases) isn’t intended to be fixed (i.e. the library may add new types 
>> in the future) an enum is likely not a good choice.  Using a closed protocol 
>> discourages the user from switching and prevents the user from adding 
>> conformances that are not desired.
>> 
>> Another use case supported by closed protocols is a design where users are 
>> not allowed to conform directly to a protocol, but instead are required to 
>> conform to one of several protocols which refine the closed protocol.  Enums 
>> are not a substitute for this use case.  The only option is to resort to 
>> documentation and runtime checks.
>> 
>> 
>> Proposal:
>> 
>> This proposal introduces the new access modifier `closed` as well as 
>> clarifying the meaning of `public` and expanding the use of `open`.  This 
>> provides consistent capabilities and semantics across enums, classes and 
>> protocols.
>> 
>> `open` is the most permissive modifier.  The symbol is visible outside the 
>> module and both users and future versions of the library are allowed to add 
>> new cases, subclasses or conformances.  (Note: this proposal does not 
>> introduce user-ex

Re: [swift-evolution] [Pitch] consistent public access modifiers

2017-02-11 Thread Matthew Johnson via swift-evolution

> On Feb 11, 2017, at 7:56 AM, Karl Wagner  wrote:
> 
> 
>> On 11 Feb 2017, at 14:37, Karl Wagner > <mailto:karl.sw...@springsup.com>> wrote:
>> 
>> 
>>> On 9 Feb 2017, at 00:05, Matthew Johnson via swift-evolution 
>>> mailto:swift-evolution@swift.org>> wrote:
>>> 
>>> I’ve been thinking a lot about our public access modifier story lately in 
>>> the context of both protocols and enums.  I believe we should move further 
>>> in the direction we took when introducing the `open` keyword.  I have 
>>> identified what I think is a promising direction and am interested in 
>>> feedback from the community.  If community feedback is positive I will 
>>> flesh this out into a more complete proposal draft.
>>> 
>>> 
>>> Background and Motivation:
>>> 
>>> In Swift 3 we had an extended debate regarding whether or not to allow 
>>> inheritance of public classes by default or to require an annotation for 
>>> classes that could be subclassed outside the module.  The decision we 
>>> reached was to avoid having a default at all, and instead make `open` an 
>>> access modifier.  The result is library authors are required to consider 
>>> the behavior they wish for each class.  Both behaviors are equally 
>>> convenient (neither is penalized by requiring an additional boilerplate-y 
>>> annotation).
>>> 
>>> A recent thread 
>>> (https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170206/031566.html
>>>  
>>> <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170206/031566.html>)
>>>  discussed a similar tradeoff regarding whether public enums should commit 
>>> to a fixed set of cases by default or not.  The current behavior is that 
>>> they *do* commit to a fixed set of cases and there is no option (afaik) to 
>>> modify that behavior.  The Library Evolution document 
>>> (https://github.com/apple/swift/blob/master/docs/LibraryEvolution.rst#enums 
>>> <https://github.com/apple/swift/blob/master/docs/LibraryEvolution.rst#enums>)
>>>  suggests a desire to change this before locking down ABI such that public 
>>> enums *do not* make this commitment by default, and are required to opt-in 
>>> to this behavior using an `@closed` annotation.
>>> 
>>> In the previous discussion I stated a strong preference that closed enums 
>>> *not* be penalized with an additional annotation.  This is because I feel 
>>> pretty strongly that it is a design smell to: 1) expose cases publicly if 
>>> consumers of the API are not expected to switch on them and 2) require 
>>> users to handle unknown future cases if they are likely to switch over the 
>>> cases in correct use of the API.
>>> 
>>> The conclusion I came to in that thread is that we should adopt the same 
>>> strategy as we did with classes: there should not be a default.
>>> 
>>> There have also been several discussions both on the list and via Twitter 
>>> regarding whether or not we should allow closed protocols.  In a recent 
>>> Twitter discussion Joe Groff suggested that we don’t need them because we 
>>> should use an enum when there is a fixed set of conforming types.  There 
>>> are at least two  reasons why I still think we *should* add support for 
>>> closed protocols.
>>> 
>>> As noted above (and in the previous thread in more detail), if the set of 
>>> types (cases) isn’t intended to be fixed (i.e. the library may add new 
>>> types in the future) an enum is likely not a good choice.  Using a closed 
>>> protocol discourages the user from switching and prevents the user from 
>>> adding conformances that are not desired.
>>> 
>>> Another use case supported by closed protocols is a design where users are 
>>> not allowed to conform directly to a protocol, but instead are required to 
>>> conform to one of several protocols which refine the closed protocol.  
>>> Enums are not a substitute for this use case.  The only option is to resort 
>>> to documentation and runtime checks.
>>> 
>>> 
>>> Proposal:
>>> 
>>> This proposal introduces the new access modifier `closed` as well as 
>>> clarifying the meaning of `public` and expanding the use of `open`.  This 
>>> provides consistent capabilities and semantics across enums, classes and 
>>> protocols.
>>> 
>>> `open` is the most permissive modifier.  The symbol is visible outs

Re: [swift-evolution] [Pitch] consistent public access modifiers

2017-02-11 Thread Matthew Johnson via swift-evolution

> On Feb 11, 2017, at 7:37 AM, Karl Wagner  wrote:
> 
> 
>> On 9 Feb 2017, at 00:05, Matthew Johnson via swift-evolution 
>> mailto:swift-evolution@swift.org>> wrote:
>> 
>> I’ve been thinking a lot about our public access modifier story lately in 
>> the context of both protocols and enums.  I believe we should move further 
>> in the direction we took when introducing the `open` keyword.  I have 
>> identified what I think is a promising direction and am interested in 
>> feedback from the community.  If community feedback is positive I will flesh 
>> this out into a more complete proposal draft.
>> 
>> 
>> Background and Motivation:
>> 
>> In Swift 3 we had an extended debate regarding whether or not to allow 
>> inheritance of public classes by default or to require an annotation for 
>> classes that could be subclassed outside the module.  The decision we 
>> reached was to avoid having a default at all, and instead make `open` an 
>> access modifier.  The result is library authors are required to consider the 
>> behavior they wish for each class.  Both behaviors are equally convenient 
>> (neither is penalized by requiring an additional boilerplate-y annotation).
>> 
>> A recent thread 
>> (https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170206/031566.html
>>  
>> <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170206/031566.html>)
>>  discussed a similar tradeoff regarding whether public enums should commit 
>> to a fixed set of cases by default or not.  The current behavior is that 
>> they *do* commit to a fixed set of cases and there is no option (afaik) to 
>> modify that behavior.  The Library Evolution document 
>> (https://github.com/apple/swift/blob/master/docs/LibraryEvolution.rst#enums 
>> <https://github.com/apple/swift/blob/master/docs/LibraryEvolution.rst#enums>)
>>  suggests a desire to change this before locking down ABI such that public 
>> enums *do not* make this commitment by default, and are required to opt-in 
>> to this behavior using an `@closed` annotation.
>> 
>> In the previous discussion I stated a strong preference that closed enums 
>> *not* be penalized with an additional annotation.  This is because I feel 
>> pretty strongly that it is a design smell to: 1) expose cases publicly if 
>> consumers of the API are not expected to switch on them and 2) require users 
>> to handle unknown future cases if they are likely to switch over the cases 
>> in correct use of the API.
>> 
>> The conclusion I came to in that thread is that we should adopt the same 
>> strategy as we did with classes: there should not be a default.
>> 
>> There have also been several discussions both on the list and via Twitter 
>> regarding whether or not we should allow closed protocols.  In a recent 
>> Twitter discussion Joe Groff suggested that we don’t need them because we 
>> should use an enum when there is a fixed set of conforming types.  There are 
>> at least two  reasons why I still think we *should* add support for closed 
>> protocols.
>> 
>> As noted above (and in the previous thread in more detail), if the set of 
>> types (cases) isn’t intended to be fixed (i.e. the library may add new types 
>> in the future) an enum is likely not a good choice.  Using a closed protocol 
>> discourages the user from switching and prevents the user from adding 
>> conformances that are not desired.
>> 
>> Another use case supported by closed protocols is a design where users are 
>> not allowed to conform directly to a protocol, but instead are required to 
>> conform to one of several protocols which refine the closed protocol.  Enums 
>> are not a substitute for this use case.  The only option is to resort to 
>> documentation and runtime checks.
>> 
>> 
>> Proposal:
>> 
>> This proposal introduces the new access modifier `closed` as well as 
>> clarifying the meaning of `public` and expanding the use of `open`.  This 
>> provides consistent capabilities and semantics across enums, classes and 
>> protocols.
>> 
>> `open` is the most permissive modifier.  The symbol is visible outside the 
>> module and both users and future versions of the library are allowed to add 
>> new cases, subclasses or conformances.  (Note: this proposal does not 
>> introduce user-extensible `open` enums, but provides the syntax that would 
>> be used if they are added to the language)
>> 
>> `public` makes the symbol visible without allowing the user to add new 
>> cases, subclass

Re: [swift-evolution] [Pitch] consistent public access modifiers

2017-02-11 Thread Matthew Johnson via swift-evolution


Sent from my iPad

> On Feb 11, 2017, at 12:44 PM, Xiaodi Wu  wrote:
> 
>> On Sat, Feb 11, 2017 at 12:42 PM, Matthew Johnson via swift-evolution 
>>  wrote:
>> 
>> 
>> Sent from my iPad
>> 
>> > On Feb 11, 2017, at 7:22 AM, Rien  wrote:
>> >
>> > I admit that I have not followed all of this discussion, but as far as I 
>> > see, we could equally well do this by calling “not-open” enum’s “final”.
>> > It seems like a better fit to me.
>> 
>> That is actually not a very good fit at all.  `final` means a class cannot 
>> have any subclasses.  If we applied it to enums I think the closest parallel 
>> would be an enum with no cases.  But this makes the enum uninhabited so it 
>> is not just like `final class`, but actually more like `abstract final 
>> class`.
> 
> Well, you _could_ move `final` to the cases themselves, and it would mean the 
> right thing: `enum Foo { final case bar, baz }`.

I don't quite follow this.  In order for `final` to mean something when applied 
to a kind of entity it should also be meaningful to non-final entities of that 
same kind.  What would a non-final case be?

> 
>> 
>> >
>> > Regards,
>> > Rien
>> >
>> > Site: http://balancingrock.nl
>> > Blog: http://swiftrien.blogspot.com
>> > Github: http://github.com/Balancingrock
>> > Project: http://swiftfire.nl
>> >
>> >
>> >
>> >
>> >
>> >> On 11 Feb 2017, at 14:07, Matthew Johnson via swift-evolution 
>> >>  wrote:
>> >>
>> >>
>> >>
>> >> Sent from my iPad
>> >>
>> >>> On Feb 11, 2017, at 4:25 AM, Adrian Zubarev via swift-evolution 
>> >>>  wrote:
>> >>>
>> >>> I’m probably better describing things with some bikeshedding code, but 
>> >>> feel free to criticize it as much as you’d like.
>> >>>
>> >>> //===- Module A -===//
>> >>> @closed public enum A {
>> >>>case a
>> >>> }
>> >>>
>> >>> extension A {
>> >>>case aa // error, because enum is closed
>> >>> }
>> >>>
>> >> This is an error because you can't add cases in an extension.  I imagine 
>> >> this is how cases would be added outside the module if we allow `open 
>> >> enum` in the future.  But whether or not this is allowed *within* the 
>> >> module is a separate question that is orthogonal to `closed` and `open`.
>> >>
>> >>
>> >>>
>> >>> public func foo(a: A) {
>> >>>switch a {
>> >>>case .a:
>> >>>print("done")
>> >>>}
>> >>> }
>> >>>
>> >>> public enum B {
>> >>>case b
>> >>> }
>> >>>
>> >>> extension B {
>> >>>case bb // fine, because not-closed enums are extensible
>> >>> }
>> >>>
>> >> As noted above, whether this is allowed or not *within* the module is 
>> >> orthogonal to `closed`.  *Outside* the module it would only be possible 
>> >> for enum declared `open` (if we add this feature in the future).
>> >>
>> >>>
>> >>> public func bar(b: B) {
>> >>>switch b {
>> >>>case .b:
>> >>>print("b")
>> >>>
>> >>>default: // always needed
>> >>>print("some other case")
>> >>>}
>> >>> }
>> >>>
>> >>> // Sub-enum relationships
>> >>>
>> >>> // Possible even the enum A is closed, because `@closed` only
>> >>> // closes the extensibility of an enum
>> >>> enum SubA : A {
>> >>>case aa
>> >>> }
>> >>>
>> >>>
>> >> Now you're talking about value subtypes.  That is orthogonal.  Also, this 
>> >> syntax already has a meaning (the raw value of the enum is A) so we 
>> >> wouldn't be able to use it the way you are intending here.  Finally, it 
>> >> is misleading syntax because what you mean here is "A is a subtype of 
>> >> SubA" which is exactly the opposite of what the syntax implies.
>> >>
>> >> All values of A are valid valu

Re: [swift-evolution] [Pitch] consistent public access modifiers

2017-02-11 Thread Matthew Johnson via swift-evolution
s always known at any point, no matter 
>>>>>> // where the instance comes from, right?
>>>>>> 
>>>>>> let subA = SubA.aa
>>>>>> let otherSubA = SubA.a // Inherited case
>>>>>> 
>>>>>> let a: A = subA// error, downgrade the sub-enum to A first
>>>>>> let a: A = otherSubA   // okay
>>>>>> 
>>>>>> foo(a: subA)   // error, downgrade the sub-enum to A first
>>>>>> foo(a: otherSubA)  // okay
>>>>>> 
>>>>>> //===- Module B -===//
>>>>>> 
>>>>>> // Totally fine 
>>>>>> switch A.a {
>>>>>> case .a:
>>>>>> print("done")
>>>>>> }
>>>>>> 
>>>>>> extension A {
>>>>>> case aa // not allowed because the enum is closed
>>>>>> }
>>>>>> 
>>>>>> extension B {
>>>>>> case bbb
>>>>>> }
>>>>>> 
>>>>>> switch B.b {
>>>>>> case .b:
>>>>>> print("b")
>>>>>> default: 
>>>>>> print("somethine else")
>>>>>> }
>>>>>> 
>>>>>> bar(b: B.bbb) // fine, because the switch statement on enums without 
>>>>>> // `@closed` has always`default`
>>>>>> 
>>>>>> // Allowed because `C` is open, and open allows sub-typing, conforming   
>>>>>>   
>>>>>> // and overriding to the client
>>>>>> enum SubC : C {
>>>>>> case cc
>>>>>> }
>>>>>> 
>>>>>> let subC = SubC.cc
>>>>>> 
>>>>>> cool(c: subC) // okay
>>>>>> 
>>>>>> enum SubD : D {
>>>>>> case dd
>>>>>> }
>>>>>> 
>>>>>> doo(d: D.dd)// error, downgrade sub-enum to D first
>>>>>> My point here is, that we should not think of (possible) open enums as 
>>>>>> enums that the client is allowed to extend. That way we’re only creating 
>>>>>> another inconsistent case for the open access modifier. As far as I can 
>>>>>> tell, open as for today means “the client is allowed to 
>>>>>> subclass/override things from a different module”.
>>>>>> 
>>>>> Yes, but subclasses are analogous to enum cases.  A subtype of an enum 
>>>>> would remove cases.  I think you are misunderstanding the relationship of 
>>>>> enums to classes and protocols.
>>>>> 
>>>>>> And I already said it hundred of times that we should extend this to 
>>>>>> make open a true access modifier in Swift. That said the meaning of open 
>>>>>> should become:
>>>>>> 
>>>>>> The client is allowed to sub-type (currently only classes are supported).
>>>>>> The client is allowed to conform to open protocols
>>>>>> The client is allowed to override open type members
>>>>>> This also means that extensibility is still allowed to public types. 
>>>>>> Public-but-not-open classes are still extensible today, which is the 
>>>>>> correct behavior. Extending an enum which is not closed could or 
>>>>>> probably should be made possible through extensions, because I cannot 
>>>>>> think of anther elegant way for the client to do so.
>>>>>> 
>>>>> This is what `open enum` would allow.  It is the proper enum analogue of 
>>>>> open classes.
>>>>> 
>>>>>> That will leave us the possibility to think of sub-typing enums in the 
>>>>>> future (I sketched it out a little above).
>>>>>> 
>>>>> Value subtyping is very interesting.  I have been working on some ideas 
>>>>> around this but I want to keep this thread focused.
>>>>> 
>>>>>> If I’m not mistaken, every enum case is known at compile time,
>>>>>> 
>>>>> This is true today but will not always be true in the future.  That is in 
>>>>> large part what this thread is about.
>>>>> 
>>>>>> which means to me that we can safely check th

Re: [swift-evolution] [Pitch] consistent public access modifiers

2017-02-11 Thread Matthew Johnson via swift-evolution


Sent from my iPad

> On Feb 11, 2017, at 7:22 AM, Rien  wrote:
> 
> I admit that I have not followed all of this discussion, but as far as I see, 
> we could equally well do this by calling “not-open” enum’s “final”.
> It seems like a better fit to me.

That is actually not a very good fit at all.  `final` means a class cannot have 
any subclasses.  If we applied it to enums I think the closest parallel would 
be an enum with no cases.  But this makes the enum uninhabited so it is not 
just like `final class`, but actually more like `abstract final class`.

> 
> Regards,
> Rien
> 
> Site: http://balancingrock.nl
> Blog: http://swiftrien.blogspot.com
> Github: http://github.com/Balancingrock
> Project: http://swiftfire.nl
> 
> 
> 
> 
> 
>> On 11 Feb 2017, at 14:07, Matthew Johnson via swift-evolution 
>>  wrote:
>> 
>> 
>> 
>> Sent from my iPad
>> 
>>> On Feb 11, 2017, at 4:25 AM, Adrian Zubarev via swift-evolution 
>>>  wrote:
>>> 
>>> I’m probably better describing things with some bikeshedding code, but feel 
>>> free to criticize it as much as you’d like.
>>> 
>>> //===- Module A -===//
>>> @closed public enum A {
>>>case a
>>> }
>>> 
>>> extension A {
>>>case aa // error, because enum is closed
>>> }
>>> 
>> This is an error because you can't add cases in an extension.  I imagine 
>> this is how cases would be added outside the module if we allow `open enum` 
>> in the future.  But whether or not this is allowed *within* the module is a 
>> separate question that is orthogonal to `closed` and `open`.
>> 
>> 
>>> 
>>> public func foo(a: A) {
>>>switch a {
>>>case .a:
>>>print("done")
>>>}
>>> }
>>> 
>>> public enum B {
>>>case b
>>> }
>>> 
>>> extension B {
>>>case bb // fine, because not-closed enums are extensible
>>> }
>>> 
>> As noted above, whether this is allowed or not *within* the module is 
>> orthogonal to `closed`.  *Outside* the module it would only be possible for 
>> enum declared `open` (if we add this feature in the future).
>> 
>>> 
>>> public func bar(b: B) {
>>>switch b {
>>>case .b:
>>>print("b")
>>> 
>>>default: // always needed
>>>print("some other case")
>>>}
>>> }
>>> 
>>> // Sub-enum relationships
>>> 
>>> // Possible even the enum A is closed, because `@closed` only  
>>> // closes the extensibility of an enum
>>> enum SubA : A {
>>>case aa
>>> }
>>> 
>>> 
>> Now you're talking about value subtypes.  That is orthogonal.  Also, this 
>> syntax already has a meaning (the raw value of the enum is A) so we wouldn't 
>> be able to use it the way you are intending here.  Finally, it is misleading 
>> syntax because what you mean here is "A is a subtype of SubA" which is 
>> exactly the opposite of what the syntax implies.
>> 
>> All values of A are valid values of SubA, but SubA has values that are not 
>> valid values of A.
>> 
>>> // The following enum can have a sub-enum in the clients module
>>> open enum C {
>>>case c
>>> }
>>> 
>>> public func cool(c: C) {
>>>switch c {
>>>case .c:
>>>print("c")
>>> 
>>>default: // always needed
>>>print("some other case")
>>>}
>>> }
>>> 
>>> @closed open enum D {
>>>case d
>>> }
>>> 
>>> public func doo(d: D) {
>>>switch b {
>>>case .b:
>>>print("b")
>>>}
>>> }
>>> 
>>> // The enum case is always known at any point, no matter  
>>> // where the instance comes from, right?
>>> 
>>> let subA = SubA.aa
>>> let otherSubA = SubA.a // Inherited case
>>> 
>>> let a: A = subA// error, downgrade the sub-enum to A first
>>> let a: A = otherSubA   // okay
>>> 
>>> foo(a: subA)   // error, downgrade the sub-enum to A first
>>> foo(a: otherSubA)  // okay
>>> 
>>> //===- Module B -===//
>>> 
>>> // Totally fine  
>>> switch A.a 

Re: [swift-evolution] [Pitch] consistent public access modifiers

2017-02-11 Thread Matthew Johnson via swift-evolution
>>>> }
>>>>> 
>>>>> doo(d: D.dd)// error, downgrade sub-enum to D first
>>>>> My point here is, that we should not think of (possible) open enums as 
>>>>> enums that the client is allowed to extend. That way we’re only creating 
>>>>> another inconsistent case for the open access modifier. As far as I can 
>>>>> tell, open as for today means “the client is allowed to subclass/override 
>>>>> things from a different module”.
>>>>> 
>>>> Yes, but subclasses are analogous to enum cases.  A subtype of an enum 
>>>> would remove cases.  I think you are misunderstanding the relationship of 
>>>> enums to classes and protocols.
>>>> 
>>>>> And I already said it hundred of times that we should extend this to make 
>>>>> open a true access modifier in Swift. That said the meaning of open 
>>>>> should become:
>>>>> 
>>>>> The client is allowed to sub-type (currently only classes are supported).
>>>>> The client is allowed to conform to open protocols
>>>>> The client is allowed to override open type members
>>>>> This also means that extensibility is still allowed to public types. 
>>>>> Public-but-not-open classes are still extensible today, which is the 
>>>>> correct behavior. Extending an enum which is not closed could or probably 
>>>>> should be made possible through extensions, because I cannot think of 
>>>>> anther elegant way for the client to do so.
>>>>> 
>>>> This is what `open enum` would allow.  It is the proper enum analogue of 
>>>> open classes.
>>>> 
>>>>> That will leave us the possibility to think of sub-typing enums in the 
>>>>> future (I sketched it out a little above).
>>>>> 
>>>> Value subtyping is very interesting.  I have been working on some ideas 
>>>> around this but I want to keep this thread focused.
>>>> 
>>>>> If I’m not mistaken, every enum case is known at compile time,
>>>>> 
>>>> This is true today but will not always be true in the future.  That is in 
>>>> large part what this thread is about.
>>>> 
>>>>> which means to me that we can safely check the case before allowing to 
>>>>> assign or pass an instance of a sub-enum to some of its super-enum. 
>>>>> (Downgrading an enum case means that you will have to write some code 
>>>>> that either mutates your current instance or creates a new one which 
>>>>> matches one of the super-enum cases.) Furthermore that allows a clear 
>>>>> distinction of what open access modifier does and how @closed behaves.
>>>>> 
>>>> I'm not going to comment on the rest because it is premised on a 
>>>> misunderstanding of what value subtyping is.  I'm going to share some 
>>>> ideas around value subtyping in a new thread as soon as I have a chance to 
>>>> finish putting them together.
>>>> 
>>>>> To summarize:
>>>>> 
>>>>> @closed enum - you’re not allowed to add new cases to the enum in your 
>>>>> lib + (you’re allowed to create sub-enums)
>>>>> @closed public enum - you and the client are not allowed to add new cases 
>>>>> (+ the client is not allowed to create sub-enums)
>>>>> @closed open enum - you and the client are not allowed to add new cases 
>>>>> (+ the client might create new sub-enums)
>>>>> enum - you’re allowed to add new cases (default is needed in switch 
>>>>> statements) (+ you can create new sub-enums)
>>>>> public enum - you and the client are allowed to add new cases (+ only you 
>>>>> are allowed to create new sub-enums)
>>>>> open enum - you and the client are allowed to add new cases (everyone can 
>>>>> create new sub-enums)
>>>>> This is a lot of bike shedding of mine, and the idea might not even see 
>>>>> any light in Swift at all, but I’d like to share my ideas with the 
>>>>> community. Feel free to criticize them or flesh something out into 
>>>>> something real. :)
>>>>> 
>>>>> P.S.: If we had something like this:
>>>>> 
>>>>> @closed enum X {
>>>>> case x, y
>>>>> func foo() {
>>>>>  switch self {
>>>

Re: [swift-evolution] [Pitch] consistent public access modifiers

2017-02-11 Thread Matthew Johnson via swift-evolution
the correct 
> behavior. Extending an enum which is not closed could or probably should be 
> made possible through extensions, because I cannot think of anther elegant 
> way for the client to do so.
> 
This is what `open enum` would allow.  It is the proper enum analogue of open 
classes.

> That will leave us the possibility to think of sub-typing enums in the future 
> (I sketched it out a little above).
> 
Value subtyping is very interesting.  I have been working on some ideas around 
this but I want to keep this thread focused.

> If I’m not mistaken, every enum case is known at compile time,
> 
This is true today but will not always be true in the future.  That is in large 
part what this thread is about.

> which means to me that we can safely check the case before allowing to assign 
> or pass an instance of a sub-enum to some of its super-enum. (Downgrading an 
> enum case means that you will have to write some code that either mutates 
> your current instance or creates a new one which matches one of the 
> super-enum cases.) Furthermore that allows a clear distinction of what open 
> access modifier does and how @closed behaves.
> 
I'm not going to comment on the rest because it is premised on a 
misunderstanding of what value subtyping is.  I'm going to share some ideas 
around value subtyping in a new thread as soon as I have a chance to finish 
putting them together.

> To summarize:
> 
> @closed enum - you’re not allowed to add new cases to the enum in your lib + 
> (you’re allowed to create sub-enums)
> @closed public enum - you and the client are not allowed to add new cases (+ 
> the client is not allowed to create sub-enums)
> @closed open enum - you and the client are not allowed to add new cases (+ 
> the client might create new sub-enums)
> enum - you’re allowed to add new cases (default is needed in switch 
> statements) (+ you can create new sub-enums)
> public enum - you and the client are allowed to add new cases (+ only you are 
> allowed to create new sub-enums)
> open enum - you and the client are allowed to add new cases (everyone can 
> create new sub-enums)
> This is a lot of bike shedding of mine, and the idea might not even see any 
> light in Swift at all, but I’d like to share my ideas with the community. 
> Feel free to criticize them or flesh something out into something real. :)
> 
> P.S.: If we had something like this:
> 
> @closed enum X {
> case x, y
> func foo() {
>  switch self {
> case .x, .y:
> print("swift")
> }
> }
> 
> enum Z : X {
> case z, zz
>     override func foo() {
> // Iff `self` is `z` or `zz` then calling super will result in an 
> error.
> // Possible solution: always tell the client to downgrade explicitly 
> the  
> // case first if there is an attempt to call super (if mutating),  
> // or handle all cases
> 
> switch self {
> case .z, .zz:
> print("custom work")
> default: // or all super-enum cases
> super.foo()
> }
> }
> }
> 
> 
> -- 
> Adrian Zubarev
> Sent with Airmail
> 
> Am 11. Februar 2017 um 04:49:11, Xiaodi Wu via swift-evolution 
> (swift-evolution@swift.org) schrieb:
> 
>> On Wed, Feb 8, 2017 at 5:05 PM, Matthew Johnson via swift-evolution 
>>  wrote:
>>> I’ve been thinking a lot about our public access modifier story lately in 
>>> the context of both protocols and enums.  I believe we should move further 
>>> in the direction we took when introducing the `open` keyword.  I have 
>>> identified what I think is a promising direction and am interested in 
>>> feedback from the community.  If community feedback is positive I will 
>>> flesh this out into a more complete proposal draft.
>>> 
>>> 
>>> Background and Motivation:
>>> 
>>> In Swift 3 we had an extended debate regarding whether or not to allow 
>>> inheritance of public classes by default or to require an annotation for 
>>> classes that could be subclassed outside the module.  The decision we 
>>> reached was to avoid having a default at all, and instead make `open` an 
>>> access modifier.  The result is library authors are required to consider 
>>> the behavior they wish for each class.  Both behaviors are equally 
>>> convenient (neither is penalized by requiring an additional boilerplate-y 
>>> annotation).
>>> 
>>> A recent thread 
>>> (https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170206/031566.html)
>>>  discussed a similar tradeoff regarding whether public enums should 

Re: [swift-evolution] [Pitch] consistent public access modifiers

2017-02-11 Thread Matthew Johnson via swift-evolution


Sent from my iPad

> On Feb 10, 2017, at 9:48 PM, Xiaodi Wu  wrote:
> 
>> On Wed, Feb 8, 2017 at 5:05 PM, Matthew Johnson via swift-evolution 
>>  wrote:
>> I’ve been thinking a lot about our public access modifier story lately in 
>> the context of both protocols and enums.  I believe we should move further 
>> in the direction we took when introducing the `open` keyword.  I have 
>> identified what I think is a promising direction and am interested in 
>> feedback from the community.  If community feedback is positive I will flesh 
>> this out into a more complete proposal draft.
>> 
>> 
>> Background and Motivation:
>> 
>> In Swift 3 we had an extended debate regarding whether or not to allow 
>> inheritance of public classes by default or to require an annotation for 
>> classes that could be subclassed outside the module.  The decision we 
>> reached was to avoid having a default at all, and instead make `open` an 
>> access modifier.  The result is library authors are required to consider the 
>> behavior they wish for each class.  Both behaviors are equally convenient 
>> (neither is penalized by requiring an additional boilerplate-y annotation).
>> 
>> A recent thread 
>> (https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170206/031566.html)
>>  discussed a similar tradeoff regarding whether public enums should commit 
>> to a fixed set of cases by default or not.  The current behavior is that 
>> they *do* commit to a fixed set of cases and there is no option (afaik) to 
>> modify that behavior.  The Library Evolution document 
>> (https://github.com/apple/swift/blob/master/docs/LibraryEvolution.rst#enums) 
>> suggests a desire to change this before locking down ABI such that public 
>> enums *do not* make this commitment by default, and are required to opt-in 
>> to this behavior using an `@closed` annotation.
>> 
>> In the previous discussion I stated a strong preference that closed enums 
>> *not* be penalized with an additional annotation.  This is because I feel 
>> pretty strongly that it is a design smell to: 1) expose cases publicly if 
>> consumers of the API are not expected to switch on them and 2) require users 
>> to handle unknown future cases if they are likely to switch over the cases 
>> in correct use of the API.
>> 
>> The conclusion I came to in that thread is that we should adopt the same 
>> strategy as we did with classes: there should not be a default.
>> 
>> There have also been several discussions both on the list and via Twitter 
>> regarding whether or not we should allow closed protocols.  In a recent 
>> Twitter discussion Joe Groff suggested that we don’t need them because we 
>> should use an enum when there is a fixed set of conforming types.  There are 
>> at least two  reasons why I still think we *should* add support for closed 
>> protocols.
>> 
>> As noted above (and in the previous thread in more detail), if the set of 
>> types (cases) isn’t intended to be fixed (i.e. the library may add new types 
>> in the future) an enum is likely not a good choice.  Using a closed protocol 
>> discourages the user from switching and prevents the user from adding 
>> conformances that are not desired.
>> 
>> Another use case supported by closed protocols is a design where users are 
>> not allowed to conform directly to a protocol, but instead are required to 
>> conform to one of several protocols which refine the closed protocol.  Enums 
>> are not a substitute for this use case.  The only option is to resort to 
>> documentation and runtime checks.
>> 
>> 
>> Proposal:
>> 
>> This proposal introduces the new access modifier `closed` as well as 
>> clarifying the meaning of `public` and expanding the use of `open`.  This 
>> provides consistent capabilities and semantics across enums, classes and 
>> protocols.
>> 
>> `open` is the most permissive modifier.  The symbol is visible outside the 
>> module and both users and future versions of the library are allowed to add 
>> new cases, subclasses or conformances.  (Note: this proposal does not 
>> introduce user-extensible `open` enums, but provides the syntax that would 
>> be used if they are added to the language)
>> 
>> `public` makes the symbol visible without allowing the user to add new 
>> cases, subclasses or conformances.  The library reserves the right to add 
>> new cases, subclasses or conformances in a future version.
>> 
>> `closed` is the most restrictive modifier.  The symbol is visible publicly 
>> with the

Re: [swift-evolution] [Pitch] consistent public access modifiers

2017-02-11 Thread Matthew Johnson via swift-evolution
 contortions I had to go through to justify `open` as 
> a spelling, and I'd be a little sad to see such reasoning propagate further. 
> But at the end of the day, I think if we go in with eyes open and explicitly 
> accept or reject a non-linear access modifier scheme, it'll work out OK.

If you are still uncomfortable with `open` as an access level I can understand 
why you don't want to proceed further in that direction.  

It seemed a little bit odd at first, but I think it accomplishes two very 
important things.  It requires library authors to explicitly choose a contract 
regarding how they type may be "refined" (does this work as a general term to 
refer to cases, subclasses, and protocols?).  And it does this without favoring 
or penalizing any of the options syntactically.  

This second point received quite a bit of consideration in the review of 
`open`.  There is a strong desire to avoid having Swift grow a bunch of 
annotations that lead to code feeling boilerplate-y.  Making `open` an access 
modifier accomplished both of these goals very well IMO.


> 
>>> 
>>>> On the other hand, you might be suggesting that `public` enums maintain 
>>>> their current behavior and we simply introduce `open` as a modifier that 
>>>> reserves the right for the *library* to introduce new cases while 
>>>> continuing to prohibit *users* from introducing new cases.  This approach 
>>>> has inconsistent semantics for both `public` and `open`.  These keywords 
>>>> would indicate a different API contract for enums than they do for classes 
>>>> and protocols.  In fact, `open` for enums would have a contract analagous 
>>>> with `public` for classes and protocols.  This feels like a recipe for 
>>>> confusion.  IMO, having consistent semantics for each keyword is pretty 
>>>> important.  We already have, and desire to continue to have, three 
>>>> distinct semantic contracts.  If we want keywords with consistent 
>>>> semantics we are going to have to introduce a new keyword for the third 
>>>> meaning.
>>>> 
>>>> 
>>>>> On Wed, Feb 8, 2017 at 17:05 Matthew Johnson via swift-evolution 
>>>>>  wrote:
>>>>>> I’ve been thinking a lot about our public access modifier story lately 
>>>>>> in the context of both protocols and enums.  I believe we should move 
>>>>>> further in the direction we took when introducing the `open` keyword.  I 
>>>>>> have identified what I think is a promising direction and am interested 
>>>>>> in feedback from the community.  If community feedback is positive I 
>>>>>> will flesh this out into a more complete proposal draft.
>>>>>> 
>>>>>> 
>>>>>> Background and Motivation:
>>>>>> 
>>>>>> In Swift 3 we had an extended debate regarding whether or not to allow 
>>>>>> inheritance of public classes by default or to require an annotation for 
>>>>>> classes that could be subclassed outside the module.  The decision we 
>>>>>> reached was to avoid having a default at all, and instead make `open` an 
>>>>>> access modifier.  The result is library authors are required to consider 
>>>>>> the behavior they wish for each class.  Both behaviors are equally 
>>>>>> convenient (neither is penalized by requiring an additional 
>>>>>> boilerplate-y annotation).
>>>>>> 
>>>>>> A recent thread 
>>>>>> (https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170206/031566.html)
>>>>>>  discussed a similar tradeoff regarding whether public enums should 
>>>>>> commit to a fixed set of cases by default or not.  The current behavior 
>>>>>> is that they *do* commit to a fixed set of cases and there is no option 
>>>>>> (afaik) to modify that behavior.  The Library Evolution document 
>>>>>> (https://github.com/apple/swift/blob/master/docs/LibraryEvolution.rst#enums)
>>>>>>  suggests a desire to change this before locking down ABI such that 
>>>>>> public enums *do not* make this commitment by default, and are required 
>>>>>> to opt-in to this behavior using an `@closed` annotation.
>>>>>> 
>>>>>> In the previous discussion I stated a strong preference that closed 
>>>>>> enums *not* be penalized with an additional annotation.  This is because 
>>>>>> I feel pretty 

Re: [swift-evolution] Warning when omitting default case for imported enums

2017-02-11 Thread Matthew Johnson via swift-evolution


Sent from my iPad

> On Feb 11, 2017, at 5:11 AM, Tino Heth via swift-evolution 
>  wrote:
> 
> 
>> Closed would not be an access level, just an attribute orthogonal to the 
>> others.
> As Xiaodi pointed out, there's still no agreement on that — so basically I'm 
> saying that I prefer your interpretation, because imho five access levels are 
> already a alarmingly high number.

Well we're going to have a concept of closed enum regardless of how we spell it 
syntactically.  I don't think making it an access level adds any complexity 
over using an attribute.  I think it reduces complexity by making the language 
more consistent.

> 
>> What do you mean by the six different flavors?
> 1) cases with associated objects
> 2) raw-based enums
> 3) everything else (not that much different from int-based)
> 
> With the new attribute, there would be a new variant for each type, therefor 
> six flavours (I choose this term because it's only small variation — but 
> still, it might look quite complex to someone coming from C or Java).
> 
> The major issue I have with this change is how it will work in real live:
> When I write a library and declare that I'll never add new cases to an enum, 
> who will enforce this?
> Will the compiler interact with git and look for release tags, or will there 
> be a lockdown-command that records all cases and compares them with the last 
> time the command was triggered?
> This feels really brittle to me, and I haven't seen a approach that would be 
> fundamental different (and better).

We are not talking about *adding* closed enums to the language.  They already 
exist and will continue to exist.  We're just talking about how to spell them 
in the future when we also have resilient enums (i.e. allowing a library to add 
new cases in a future version without breaking compatibility).  I don't have a 
complete answer here about the details, but there is a plan to provide tool 
support to help with library evolution and detecting breaking changes.  

> ___
> 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] Warning when omitting default case for imported enums

2017-02-11 Thread Matthew Johnson via swift-evolution


Sent from my iPad

> On Feb 10, 2017, at 9:22 PM, Xiaodi Wu via swift-evolution 
>  wrote:
> 
>> On Fri, Feb 10, 2017 at 7:23 PM, Slava Pestov via swift-evolution 
>>  wrote:
>> 
>>> On Feb 10, 2017, at 8:55 AM, Tino Heth <2...@gmx.de> wrote:
>>> 
> I'm not sure if I like the concept of having two kinds of enum.
 
 Why not? Bool-like enums would be declared ‘closed’, and would not require 
 a default case (but adding a new case would then break ABI).
>>> 
>>> Well, enums are already (relative) complex, and with this addition, there 
>>> would be six different flavors.
>>> Imho it would be less bad if we could recycle existing modifiers, but with 
>>> a hypothetic "closed" access level added as well, I have strong doubts that 
>>> the feature carries its weight.
>> 
>> Closed would not be an access level, just an attribute orthogonal to the 
>> others. What do you mean by the six different flavors?
> 
> My read of Matthew Johnson's pitch is that `closed` is to be a sixth access 
> level.

This is correct.  It isn't immediately obvious, but when you step back and 
consider things from a high level point of view it seems to fall pretty 
naturally out of the logic we used when we made `open` and access level.  

Closed is talking about the same thing `open` is: who is allowed to add to the 
set of cases, subclasses or protocols of an enum, class, or protocol.  It just 
moves in the opposite direction from `public` than `open` does.  Once you 
realize this, any other spelling of `closed` would make the language feel 
inconsistent IMO.  If `open` works as an access level `closed` should also.

> 
 For better or worse we need the ability to define enums that admit new 
 cases without breaking ABI. Whether or not this is the default for all 
 enums, or enabled with a special attribute can be designed later when we 
 send out evolution proposals for resilience-related features.
>>> Intuitively, I thought this should not affect ABI… but no matter what 
>>> instability this is, I guess it could definitely crash an application that 
>>> is confronted with an unexpected case ;-)
>>> 
>>> Wouldn't it be possible to create an implicit default case for every 
>>> switch-statement?
>> 
>> 
>> ___
>> 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] [Pitch] consistent public access modifiers - protocols

2017-02-10 Thread Matthew Johnson via swift-evolution
n transition.  Users who don’t use the 
migrator will receive a warning in one version which becomes an error in the 
next, giving them plenty of time to update their code without preventing it 
from compiling and with no semantic impact.


> 
> It's worth noting that this can all be emulated by a struct with a non-public 
> field of protocol type and forwarding operations, but that's a lot of extra 
> work today. We want to make the correct thing easy; in the face of writing a 
> wrapper type, I suspect many library authors would just give up and make the 
> protocol public.
> 
> I don't think the proposed "closed" for classes and protocols is interesting. 
> "No new subclasses/adopters" seems only marginally useful for optimization, 
> and not at all useful at a semantic level. "public-but-not-open" is the 
> interesting access level.

I agree that there may not be interesting use cases for this.  I would be happy 
to treat them the same way as `open enum`: as something that could potentially 
be added in the future that we know how to spell if we ever decide to add it.  
The primary point I am making is that there is a semantic equivalent of closed 
enums for classes and protocols.  Perhaps somebody will find an interesting use 
case.  If we adopt consistent terminology we know how to apply it to these use 
cases.

> 
> That's about all I've got for protocols. Thanks again for bringing it up.
> Jordan
> 
> P.S. For classes, note that 'final' is essentially a performance optimization 
> at this point. I'm not even sure we should bother displaying it in generated 
> interfaces (although the compiler should still be able to take advantage of 
> it in clients).

`final` can be pretty useful when reasoning about code.  It’s more than just a 
performance optimization.  It also represents a compiler proof about our code.

> 
> 
> 
>> On Feb 8, 2017, at 15:05, Matthew Johnson via swift-evolution 
>> mailto:swift-evolution@swift.org>> wrote:
>> 
>> I’ve been thinking a lot about our public access modifier story lately in 
>> the context of both protocols and enums.  I believe we should move further 
>> in the direction we took when introducing the `open` keyword.  I have 
>> identified what I think is a promising direction and am interested in 
>> feedback from the community.  If community feedback is positive I will flesh 
>> this out into a more complete proposal draft.
>> 
>> 
>> Background and Motivation:
>> 
>> In Swift 3 we had an extended debate regarding whether or not to allow 
>> inheritance of public classes by default or to require an annotation for 
>> classes that could be subclassed outside the module.  The decision we 
>> reached was to avoid having a default at all, and instead make `open` an 
>> access modifier.  The result is library authors are required to consider the 
>> behavior they wish for each class.  Both behaviors are equally convenient 
>> (neither is penalized by requiring an additional boilerplate-y annotation).
>> 
>> A recent thread 
>> (https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170206/031566.html
>>  
>> <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170206/031566.html>)
>>  discussed a similar tradeoff regarding whether public enums should commit 
>> to a fixed set of cases by default or not.  The current behavior is that 
>> they *do* commit to a fixed set of cases and there is no option (afaik) to 
>> modify that behavior.  The Library Evolution document 
>> (https://github.com/apple/swift/blob/master/docs/LibraryEvolution.rst#enums 
>> <https://github.com/apple/swift/blob/master/docs/LibraryEvolution.rst#enums>)
>>  suggests a desire to change this before locking down ABI such that public 
>> enums *do not* make this commitment by default, and are required to opt-in 
>> to this behavior using an `@closed` annotation.
>> 
>> In the previous discussion I stated a strong preference that closed enums 
>> *not* be penalized with an additional annotation.  This is because I feel 
>> pretty strongly that it is a design smell to: 1) expose cases publicly if 
>> consumers of the API are not expected to switch on them and 2) require users 
>> to handle unknown future cases if they are likely to switch over the cases 
>> in correct use of the API.
>> 
>> The conclusion I came to in that thread is that we should adopt the same 
>> strategy as we did with classes: there should not be a default.
>> 
>> There have also been several discussions both on the list and via Twitter 
>> regarding whether or not we should allow clos

Re: [swift-evolution] Warning when omitting default case for imported enums

2017-02-10 Thread Matthew Johnson via swift-evolution

> On Feb 10, 2017, at 10:55 AM, Tino Heth via swift-evolution 
>  wrote:
> 
>>> I'm not sure if I like the concept of having two kinds of enum.
>> 
>> Why not? Bool-like enums would be declared ‘closed’, and would not require a 
>> default case (but adding a new case would then break ABI).
> 
> Well, enums are already (relative) complex, and with this addition, there 
> would be six different flavors.
> Imho it would be less bad if we could recycle existing modifiers, but with a 
> hypothetic "closed" access level added as well, I have strong doubts that the 
> feature carries its weight.
> 
>> For better or worse we need the ability to define enums that admit new cases 
>> without breaking ABI. Whether or not this is the default for all enums, or 
>> enabled with a special attribute can be designed later when we send out 
>> evolution proposals for resilience-related features.
> Intuitively, I thought this should not affect ABI… but no matter what 
> instability this is, I guess it could definitely crash an application that is 
> confronted with an unexpected case ;-)
> 
> Wouldn't it be possible to create an implicit default case for every 
> switch-statement?

What do you suggest this implicit default case do?  Just break?  That seems 
like the only option besides trapping.  I wouldn’t want the compiler doing 
either of these after the fact.  If we’re going to allow a library to add new 
cases without making that a breaking change it must communicate that to users 
*ahead of time* and the compiler must require a default clause in any switch 
over that type.

> ___
> 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] [Pitch] consistent public access modifiers

2017-02-10 Thread Matthew Johnson via swift-evolution
is that the compiler does not make a choice for the user because 
they omitted an annotation.  We require a class visible outside the module to 
chooses `open` or chooses `public`.  By making that choice it opts-in to one 
semantic or the other.  There is no "deliberate effort to reject a more natural 
choice” required at all.  All that is required is that intent is unambiguous.  

However, the same logic you used for `open` also works for `closed` using the 
hierarchy I visualized above.  I find the logic of that hierarchy very 
convincing (regardless of the final name we choose for `closed`).


> 
> 
> On the other hand, you might be suggesting that `public` enums maintain their 
> current behavior and we simply introduce `open` as a modifier that reserves 
> the right for the *library* to introduce new cases while continuing to 
> prohibit *users* from introducing new cases.  This approach has inconsistent 
> semantics for both `public` and `open`.  These keywords would indicate a 
> different API contract for enums than they do for classes and protocols.  In 
> fact, `open` for enums would have a contract analagous with `public` for 
> classes and protocols.  This feels like a recipe for confusion.  IMO, having 
> consistent semantics for each keyword is pretty important.  We already have, 
> and desire to continue to have, three distinct semantic contracts.  If we 
> want keywords with consistent semantics we are going to have to introduce a 
> new keyword for the third meaning.
> 
> 
>> On Wed, Feb 8, 2017 at 17:05 Matthew Johnson via swift-evolution 
>> mailto:swift-evolution@swift.org>> wrote:
>> I’ve been thinking a lot about our public access modifier story lately in 
>> the context of both protocols and enums.  I believe we should move further 
>> in the direction we took when introducing the `open` keyword.  I have 
>> identified what I think is a promising direction and am interested in 
>> feedback from the community.  If community feedback is positive I will flesh 
>> this out into a more complete proposal draft.
>> 
>> 
>> Background and Motivation:
>> 
>> In Swift 3 we had an extended debate regarding whether or not to allow 
>> inheritance of public classes by default or to require an annotation for 
>> classes that could be subclassed outside the module.  The decision we 
>> reached was to avoid having a default at all, and instead make `open` an 
>> access modifier.  The result is library authors are required to consider the 
>> behavior they wish for each class.  Both behaviors are equally convenient 
>> (neither is penalized by requiring an additional boilerplate-y annotation).
>> 
>> A recent thread 
>> (https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170206/031566.html
>>  
>> <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170206/031566.html>)
>>  discussed a similar tradeoff regarding whether public enums should commit 
>> to a fixed set of cases by default or not.  The current behavior is that 
>> they *do* commit to a fixed set of cases and there is no option (afaik) to 
>> modify that behavior.  The Library Evolution document 
>> (https://github.com/apple/swift/blob/master/docs/LibraryEvolution.rst#enums 
>> <https://github.com/apple/swift/blob/master/docs/LibraryEvolution.rst#enums>)
>>  suggests a desire to change this before locking down ABI such that public 
>> enums *do not* make this commitment by default, and are required to opt-in 
>> to this behavior using an `@closed` annotation.
>> 
>> In the previous discussion I stated a strong preference that closed enums 
>> *not* be penalized with an additional annotation.  This is because I feel 
>> pretty strongly that it is a design smell to: 1) expose cases publicly if 
>> consumers of the API are not expected to switch on them and 2) require users 
>> to handle unknown future cases if they are likely to switch over the cases 
>> in correct use of the API.
>> 
>> The conclusion I came to in that thread is that we should adopt the same 
>> strategy as we did with classes: there should not be a default.
>> 
>> There have also been several discussions both on the list and via Twitter 
>> regarding whether or not we should allow closed protocols.  In a recent 
>> Twitter discussion Joe Groff suggested that we don’t need them because we 
>> should use an enum when there is a fixed set of conforming types.  There are 
>> at least two  reasons why I still think we *should* add support for closed 
>> protocols.
>> 
>> As noted above (and in the previous thread in more detail), if the set of 
>> types (cases) isn’

Re: [swift-evolution] [swift-users] Plan to move swift-evolution and swift-users mailing lists to Discourse

2017-02-09 Thread Matthew Johnson via swift-evolution

> On Feb 9, 2017, at 6:04 PM, Ted Kremenek  wrote:
> 
> 
>> On Feb 9, 2017, at 3:52 PM, Ted Kremenek via swift-users 
>> mailto:swift-us...@swift.org>> wrote:
>> 
>>> I’ve been mostly silent in this conversation largely because I didn’t 
>>> realize it was leading up to a formal decision.  I wish it would have 
>>> followed the proposal process so it was clear to everyone that a decision 
>>> was being considered and this was our chance to offer input.  
>> 
>> FWIW, I am not ignoring this thread.  At some point there was diminishing 
>> signal on the thread, and it felt like the category of opinions that had 
>> been voiced had been vocalized on the thread.  Looping in swift-users into 
>> that thread would have been a good thing to do in hindsight so more people 
>> felt like they had a chance to participate.  Based on what I am seeing in 
>> reaction to this decision, however, I’m not seeing much new signal.
> 
> Just to add to this point — new insights on this topic are welcome, and will 
> be paid attention to.  The decision to change to a forum is because that was 
> evaluated as being the best thing for the community, based on the range of 
> opinions provided and the tradeoffs made.  If there is something important 
> that was missed, obviously that is not going to be ignored.  We want to do 
> the right thing.  So far I still feel that moving to a forum software is the 
> right choice, but I’d like to do that in a way that allows people to still 
> participate effectively via email.

Is there any way to have a trial run so we can evaluate the email experience of 
using the forum software before we make the final switch?  I agree that this 
sounds like the right direction, but it’s hard to know what the email 
experience will really be like until we give it a try for a week or so.___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Class and Subclass Existentials (Round 2)

2017-02-09 Thread Matthew Johnson via swift-evolution

> On Feb 9, 2017, at 2:44 PM, David Hart  wrote:
> 
> 
> On 9 Feb 2017, at 20:43, Matthew Johnson via swift-evolution 
> mailto:swift-evolution@swift.org>> wrote:
> 
>> 
>> 
>> Sent from my iPad
>> 
>> On Feb 9, 2017, at 1:30 PM, Hooman Mehr via swift-evolution 
>> mailto:swift-evolution@swift.org>> wrote:
>> 
>>> 
>>>> On Feb 9, 2017, at 10:47 AM, Joe Groff via swift-evolution 
>>>> mailto:swift-evolution@swift.org>> wrote:
>>>>> On Feb 9, 2017, at 4:26 AM, Step Christopher via swift-evolution 
>>>>> mailto:swift-evolution@swift.org>> wrote:
>>>>> Looks good. Minor comments below:
>>>>> The typealias 'T5' is repeated as both an initial composition, and as a 
>>>>> demonstration of combining typealiases. 
>>>>> 
>>>>>> This proposal merges the concepts of class and AnyObject, which now have 
>>>>>> the same meaning: they represent an existential for classes. They are 
>>>>>> four solutions to this dilemna:
>>>>>> Do nothing.
>>>>>> Replace all uses of AnyObject by class, breaking source compatibility.
>>>>>> Replace all uses of class by AnyObject, breaking source compatibility.
>>>>>> Redefine AnyObject as typealias AnyObject = class.
>>>>> I agree with other comments on recommending 4 here, and covering the 
>>>>> others as alternatives
>>>>>>  
>>>>>> <https://github.com/hartbit/swift-evolution/blob/e6411d8a9e7924bbd8a48fc292bf08d58a8d1199/proposals/-subclass-existentials.md#source-compatibility>I
>>>>>>  agree that we need the typealias for compatibility. I think it's still 
>>>>>> worth discussing whether the `AnyObject` typealias should *only* be 
>>>>>> there for compatibility; it could be deprecated or obsoleted in Swift 4 
>>>>>> or future language versions.
>>> 
>>> I think it might be worth keeping to provide a more sensible capitalization 
>>> alternative than lower case “class” when used as a type name:
>>> 
>>> var obj: class // this looks weird because of capitalization.
>>> 
>>> var obj: AnyObject // this looks better.
>> 
>> I agree that it looks better and would choose AnyObject if source 
>> compatibility weren't an issue.  One option that wasn't listed was to drop 
>> 'class' but use a multi-release deprecation strategy and a fix-it to 
>> facilitate a smooth transition.  If the community is willing to adopt this 
>> approach it would be my first choice.
> 
> You mean option 3?

Pretty much, but option 3 does not make it clear that it won’t break source 
immediately in Swift 4.  I think it becomes much more reasonable if Swift 3.1 
code still compiles in Swift 4 mode, but with a deprecation warning.

The reason I prefer `AnyObject` to `class` is because I think it’s ugly to have 
`class` as the name of an existential type.  Type names are uppercase in Swift. 
 It is also used to compose with protocols which also use uppercase names in 
Swift.  Because it appears in contexts which use an uppercase convention it 
makes sense for this to have an uppercase name.  `AnyObject` seems like the 
obvious choice if we’re going to go in that direction.

> 
>>> 
>>>> 
>>>> -Joe
>>>> ___
>>>> swift-evolution mailing list
>>>> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
>>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>> ___
>>> swift-evolution mailing list
>>> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> <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] Class and Subclass Existentials (Round 2)

2017-02-09 Thread Matthew Johnson via swift-evolution


Sent from my iPad

> On Feb 9, 2017, at 1:30 PM, Hooman Mehr via swift-evolution 
>  wrote:
> 
> 
>>> On Feb 9, 2017, at 10:47 AM, Joe Groff via swift-evolution 
>>>  wrote:
>>> On Feb 9, 2017, at 4:26 AM, Step Christopher via swift-evolution 
>>>  wrote:
>>> Looks good. Minor comments below:
>>> The typealias 'T5' is repeated as both an initial composition, and as a 
>>> demonstration of combining typealiases. 
>>> 
 This proposal merges the concepts of class and AnyObject, which now have 
 the same meaning: they represent an existential for classes. They are four 
 solutions to this dilemna:
 Do nothing.
 Replace all uses of AnyObject by class, breaking source compatibility.
 Replace all uses of class by AnyObject, breaking source compatibility.
 Redefine AnyObject as typealias AnyObject = class.
>>> I agree with other comments on recommending 4 here, and covering the others 
>>> as alternatives
>> I agree that we need the typealias for compatibility. I think it's still 
>> worth discussing whether the `AnyObject` typealias should *only* be there 
>> for compatibility; it could be deprecated or obsoleted in Swift 4 or future 
>> language versions.
> 
> I think it might be worth keeping to provide a more sensible capitalization 
> alternative than lower case “class” when used as a type name:
> 
> var obj: class // this looks weird because of capitalization.
> 
> var obj: AnyObject // this looks better.

I agree that it looks better and would choose AnyObject if source compatibility 
weren't an issue.  One option that wasn't listed was to drop 'class' but use a 
multi-release deprecation strategy and a fix-it to facilitate a smooth 
transition.  If the community is willing to adopt this approach it would be my 
first choice.

> 
>> 
>> -Joe
>> ___
>> 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-users] Plan to move swift-evolution and swift-users mailing lists to Discourse

2017-02-09 Thread Matthew Johnson via swift-evolution

> On Feb 9, 2017, at 11:16 AM, Jens Alfke via swift-users 
>  wrote:
> 
> 
>> On Feb 9, 2017, at 3:41 AM, Jan Neumüller via swift-users 
>> mailto:swift-us...@swift.org>> wrote:
>> 
>> I would prefer http://www.fudforum.org/  that has 
>> good mailing list support, too.
> 
> Well, we appear to have completely opposite opinions on UI/usability. I took 
> a look at fudforum and yeah, to my eyes it exemplifies the awful clutter 
> that’s been a hallmark of web forums since before PHPBB. There’s so much 
> visual noise it’s very hard to parse or to find anything. Clearly designed by 
> a coder with a big hammer named “”. I’m not a UI designer, but I’ve 
> worked extensively with UI designers (I spent 15 years at Apple working on 
> stuff like iChat and AppleScript) so I think I have some grounding in the 
> field.
> 
> I do believe, though, that whatever solution swift.org  
> switches to needs to have good email support. That way the people who hate 
> the web UI, or who just don’t prefer to use the web for discussions, can keep 
> using email as we do today. This is perfectly feasible to do; again, 
> groups.io  is a good example. 
> 
> Here my concern is that I have not found a way to configure Discourse to make 
> its email notifications work well as a substitute for a mailing list. I have 
> admin privileges on a Discourse installation run by my employer, so I’ve 
> looked through the entire admin UI for ways to improve the emails, and some 
> of the problems don’t seem fixable by tweaking settings.
> 
> At this point I’m going to shut up because it sounds like the decision has 
> been made, and I don’t want to contribute to further bike-shedding.

I’ve been mostly silent in this conversation largely because I didn’t realize 
it was leading up to a formal decision.  I wish it would have followed the 
proposal process so it was clear to everyone that a decision was being 
considered and this was our chance to offer input.  

I really like the experience of participating in the community via email.  If I 
knew a decision was being seriously considered I would have taken a closer look 
at Discourse and likely offered more input.  I will be disappointed if the 
experience of participating is not at least as good as it is using email.

One of the most important reasons I like using email is that Mail offers a 
great experience on iPhone and iPad.  I am skeptical that a web-based forum 
could offer the same level of convenience and efficiency for keeping up with 
the community that email provides.

I hope that we do find a way to configure our tool (probably Discourse) so that 
the email experience on iPhone and iPad does not suffer.  If we can meet that 
criteria and *also* offer the advantages of a web-based tool I will be very 
happy.  But I think the current email experience on iPhone and iPad should set 
a minimum criteria that any tool must meet.

> 
> —Jens
> ___
> swift-users mailing list
> swift-us...@swift.org
> https://lists.swift.org/mailman/listinfo/swift-users

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


Re: [swift-evolution] [Pitch] consistent public access modifiers

2017-02-09 Thread Matthew Johnson via swift-evolution

> On Feb 9, 2017, at 10:33 AM, Adrian Zubarev  
> wrote:
> 
> The last explanation is great, now I could follow the idea behind the 
> proposed closed keyword/access modifier. I do now understand the contract on 
> enums, but I’m struggling to understand how closed would work in my own 
> codebase. Assume I had a closed (not the public meaning of your proposal) 
> protocol.
> 
> Am I allowed to conform to that protocol inside my library? If it’s a version 
> controlled feature, how to prevent further conformance to that protocol in a 
> newer version?
> 
Yes, you are allowed to have as many conforming types inside the library as you 
wish, as long as the conformances are introduced alongside the protocol.  New 
conformances may not be added in future versions.

I don’t know exactly what the enforcement mechanism would look like, but I 
imagine it would be similar or identical to the mechanism used for `closed` 
enums.  Maybe someone from the core team can elaborate on what this will look 
like.
> What would an access modifier like closed mean on type members (final 
> public)? If it’s only a type scope access modifier, it leans towards being an 
> attribute instead.
> 
I hadn’t considered this yet but it’s a good question.  I don’t have time to 
consider it deeply, but I think the implication for members is that all 
overrides are public and no new overrides will be added in the future.  It 
isn’t likely to be useful in this case, but I think we could provide a clear 
definition.
> If it’s not an access modifier, would closed have some versioning paramerters?
> Bikeshedding: @closed(1.0.0) (The version, the type was closed)
> On current enums: @closed(*) (From the start)
Good question.  This is what the Library Evolution document has to say:

@closed is a versioned attribute. This is so that clients can deploy against 
older versions of the library, which may have non-public cases in the enum. (In 
this case the client must manipulate the enum as if the @closed attribute were 
absent.) All cases that are not versioned become implicitly versioned with this 
number.

I would prefer to see `closed` be an access modifier so it isn’t penalized with 
verbosity, particularly for enums.  I think the best approach is that `closed` 
with no version specifier is allowed if it is included in the initial release 
of a module.  `public` enums may be changed to `closed(n.m.x)` in future 
versions of a module.  There is already precedent for parameterized access 
modifiers: `private(set)`.

> The latter implies in my head that each type needs an explicit version 
> annotation like @available(1.0.0, *)!?
> 
No, I don’t think so.
> How do we handle bug fixes on closed types? Assume all current enums would 
> get an annotation like @closed(*) public. After normalize enum case 
> representation proposal 
> <https://github.com/dduan/swift-evolution/blob/185b12711bfe1e3b7982d255b538f8dad9ae242c/proposals/-Normalize-Enum-Case-Representation.md>
>  you might also want to clean up the names of your cases. That means you have 
> to perform a breaking API change.
Both proposals would be part of Swift 4. No module would be able to publish a 
production-ready version until Swift 4 is released.  Also, `closed` wouldn’t 
have ABI implications until ABI is locked down, which won’t happen until Swift 
4 is released (or later).  So you would have the chance to clean up case names 
at the same time as you introduce `closed`.

It’s also worth pointing out that changing a case name is going to be a 
breaking change regardless of whether an enum is `closed` or not.  It might be 
possible to minimize the impact of these changes if there was a way to specify 
the prior, deprecated name for the case, but this issue is orthogonal to 
`closed`.
> For example in one of my ‘just for fun’ projects I have two enum cases that 
> look as follows:
> 
> case javaScript(String)
> case scopedJavaScript(String, scope: Document)
> If the mentioned proposal will be accepted I’d like to make these cases shiny.
> 
> // v1:
> case javaScript(String)
> case javaScript(String, scope: Document)
>  
> // or v2:
> case javaScript(String, scope: Document? = nil)
> 
> 
> 
> -- 
> Adrian Zubarev
> Sent with Airmail
> 
> Am 9. Februar 2017 um 16:57:40, Matthew Johnson via swift-evolution 
> (swift-evolution@swift.org <mailto:swift-evolution@swift.org>) schrieb:
> 
>> 
>>> On Feb 8, 2017, at 5:48 PM, Xiaodi Wu >> <mailto:xiaodi...@gmail.com>> wrote:
>>> 
>>> I agree very much with rationalizing access levels, but I'm not sure I like 
>>> this proposal for public vs. closed. How would the compiler stop me from 
>>> editing my own code if something is closed? The answer must be that it 
>>> can't, so I can't se

Re: [swift-evolution] [Pitch] consistent public access modifiers

2017-02-09 Thread Matthew Johnson via swift-evolution
ar)
> }
>  
> // This is invalid because it overrides a method that is
> // defined outside of the current module but is not `open'.
> override func foo() { }
> 
> // This is allowed since the superclass's method is overridable.
> // It does not need to be marked `open` because it is defined on
> // an `internal` class.
> override func bar() { }
> }
> required should always match the same scope level as the type in which it’s 
> defined. That means if the class is open, than any of it’s required 
> initializers will be open as well.
> 
> 
> 
> 
> -- 
> Adrian Zubarev
> Sent with Airmail
> 
> Am 9. Februar 2017 um 00:49:04, Xiaodi Wu via swift-evolution 
> (swift-evolution@swift.org <mailto:swift-evolution@swift.org>) schrieb:
> 
>> I agree very much with rationalizing access levels, but I'm not sure I like 
>> this proposal for public vs. closed. How would the compiler stop me from 
>> editing my own code if something is closed? The answer must be that it 
>> can't, so I can't see it as a co-equal to open but rather simply a statement 
>> of intention. Therefore I think use cases for the proposed behavior of 
>> closed would be better served by annotations and proper semantic versioning.
>> 
>> As this change didn't seem in scope for Swift 4 phase 1, I've held off on 
>> discussing my own thoughts on access levels. The idea I was going to propose 
>> in phase 2 was to have simply open and public enums (and protocols). I 
>> really think that completes access levels in a rational way without 
>> introducing another keyword.
>> On Wed, Feb 8, 2017 at 17:05 Matthew Johnson via swift-evolution 
>> mailto:swift-evolution@swift.org>> wrote:
>> I’ve been thinking a lot about our public access modifier story lately in 
>> the context of both protocols and enums.  I believe we should move further 
>> in the direction we took when introducing the `open` keyword.  I have 
>> identified what I think is a promising direction and am interested in 
>> feedback from the community.  If community feedback is positive I will flesh 
>> this out into a more complete proposal draft.
>> 
>> 
>> Background and Motivation:
>> 
>> In Swift 3 we had an extended debate regarding whether or not to allow 
>> inheritance of public classes by default or to require an annotation for 
>> classes that could be subclassed outside the module.  The decision we 
>> reached was to avoid having a default at all, and instead make `open` an 
>> access modifier.  The result is library authors are required to consider the 
>> behavior they wish for each class.  Both behaviors are equally convenient 
>> (neither is penalized by requiring an additional boilerplate-y annotation).
>> 
>> A recent thread 
>> (https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170206/031566.html
>>  
>> <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170206/031566.html>)
>>  discussed a similar tradeoff regarding whether public enums should commit 
>> to a fixed set of cases by default or not.  The current behavior is that 
>> they *do* commit to a fixed set of cases and there is no option (afaik) to 
>> modify that behavior.  The Library Evolution document 
>> (https://github.com/apple/swift/blob/master/docs/LibraryEvolution.rst#enums 
>> <https://github.com/apple/swift/blob/master/docs/LibraryEvolution.rst#enums>)
>>  suggests a desire to change this before locking down ABI such that public 
>> enums *do not* make this commitment by default, and are required to opt-in 
>> to this behavior using an `@closed` annotation.
>> 
>> In the previous discussion I stated a strong preference that closed enums 
>> *not* be penalized with an additional annotation.  This is because I feel 
>> pretty strongly that it is a design smell to: 1) expose cases publicly if 
>> consumers of the API are not expected to switch on them and 2) require users 
>> to handle unknown future cases if they are likely to switch over the cases 
>> in correct use of the API.
>> 
>> The conclusion I came to in that thread is that we should adopt the same 
>> strategy as we did with classes: there should not be a default.
>> 
>> There have also been several discussions both on the list and via Twitter 
>> regarding whether or not we should allow closed protocols.  In a recent 
>> Twitter discussion Joe Groff suggested that we don’t need them because we 
>> should use an enum when there is a fixed set of conforming types.  There are 
>> at least two  reasons why

Re: [swift-evolution] [Pitch] consistent public access modifiers

2017-02-09 Thread Matthew Johnson via swift-evolution

> On Feb 8, 2017, at 5:48 PM, Xiaodi Wu  wrote:
> 
> I agree very much with rationalizing access levels, but I'm not sure I like 
> this proposal for public vs. closed. How would the compiler stop me from 
> editing my own code if something is closed? The answer must be that it can't, 
> so I can't see it as a co-equal to open but rather simply a statement of 
> intention. Therefore I think use cases for the proposed behavior of closed 
> would be better served by annotations and proper semantic versioning.

The most important point IMO is that they *are* co-equal in the sense that they 
define a contract between library authors, library users and the compiler.  As 
you note, there are some differences in how the `closed` contract is supported. 
 But that is far less important than the meaning of the contract itself.

Dave's comment about tools to assist with contract-compatible API evolution is 
the right way to think about this.  Of course you *can* make breaking changes, 
but we want to make it clear when you *are* making a breaking change, both for 
source and for ABI compatibility.  This will help library authors, but it also 
helps users as well as the compiler reason about code when we are able to offer 
stronger guarantees.

Most notably, the behavior of public enums *already* has the API contract of 
`closed` and we do not want to remove that capability.  This proposal only 
formalizes how that contract is specified and makes it consistent across all 
kinds of types.  It *does not* introduce the idea of a closed semantic contract 
for a type.

> As this change didn't seem in scope for Swift 4 phase 1, I've held off on 
> discussing my own thoughts on access levels. The idea I was going to propose 
> in phase 2 was to have simply open and public enums (and protocols). I really 
> think that completes access levels in a rational way without introducing 
> another keyword.

The reason I posted now is because formalizing this API contract for enums must 
happen before ABI is locked down, and also because there is at least one 
protocol in the standard library (`MirrorPath`) which is documented with the 
intent that it be `closed`.

I understand the reluctance to introduce another keyword.  It isn’t clear to me 
what semantics you assign to `open` and `public` enums.

Are you suggesting that they match the semantics defined in my proposal and 
suggesting closed enums (i.e. matching the current behavior of `public` enums) 
would require an `@closed` annotation as suggested in the Library Evolution 
document?  I am opposed to this approach because it penalizes the API contract 
that I think is often the most appropriate for enums.  I strongly prefer that 
we adopt the same neutral stance that we when we introduced `open`.  

On the other hand, you might be suggesting that `public` enums maintain their 
current behavior and we simply introduce `open` as a modifier that reserves the 
right for the *library* to introduce new cases while continuing to prohibit 
*users* from introducing new cases.  This approach has inconsistent semantics 
for both `public` and `open`.  These keywords would indicate a different API 
contract for enums than they do for classes and protocols.  In fact, `open` for 
enums would have a contract analagous with `public` for classes and protocols.  
This feels like a recipe for confusion.  IMO, having consistent semantics for 
each keyword is pretty important.  We already have, and desire to continue to 
have, three distinct semantic contracts.  If we want keywords with consistent 
semantics we are going to have to introduce a new keyword for the third meaning.


> On Wed, Feb 8, 2017 at 17:05 Matthew Johnson via swift-evolution 
> mailto:swift-evolution@swift.org>> wrote:
> I’ve been thinking a lot about our public access modifier story lately in the 
> context of both protocols and enums.  I believe we should move further in the 
> direction we took when introducing the `open` keyword.  I have identified 
> what I think is a promising direction and am interested in feedback from the 
> community.  If community feedback is positive I will flesh this out into a 
> more complete proposal draft.
> 
> 
> Background and Motivation:
> 
> In Swift 3 we had an extended debate regarding whether or not to allow 
> inheritance of public classes by default or to require an annotation for 
> classes that could be subclassed outside the module.  The decision we reached 
> was to avoid having a default at all, and instead make `open` an access 
> modifier.  The result is library authors are required to consider the 
> behavior they wish for each class.  Both behaviors are equally convenient 
> (neither is penalized by requiring an additional boilerplate-y annotation).
> 
> A recent thread 
> (https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-201

[swift-evolution] [Pitch] consistent public access modifiers

2017-02-08 Thread Matthew Johnson via swift-evolution
I’ve been thinking a lot about our public access modifier story lately in the 
context of both protocols and enums.  I believe we should move further in the 
direction we took when introducing the `open` keyword.  I have identified what 
I think is a promising direction and am interested in feedback from the 
community.  If community feedback is positive I will flesh this out into a more 
complete proposal draft.


Background and Motivation:

In Swift 3 we had an extended debate regarding whether or not to allow 
inheritance of public classes by default or to require an annotation for 
classes that could be subclassed outside the module.  The decision we reached 
was to avoid having a default at all, and instead make `open` an access 
modifier.  The result is library authors are required to consider the behavior 
they wish for each class.  Both behaviors are equally convenient (neither is 
penalized by requiring an additional boilerplate-y annotation).

A recent thread 
(https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170206/031566.html
 
)
 discussed a similar tradeoff regarding whether public enums should commit to a 
fixed set of cases by default or not.  The current behavior is that they *do* 
commit to a fixed set of cases and there is no option (afaik) to modify that 
behavior.  The Library Evolution document 
(https://github.com/apple/swift/blob/master/docs/LibraryEvolution.rst#enums 
) 
suggests a desire to change this before locking down ABI such that public enums 
*do not* make this commitment by default, and are required to opt-in to this 
behavior using an `@closed` annotation.

In the previous discussion I stated a strong preference that closed enums *not* 
be penalized with an additional annotation.  This is because I feel pretty 
strongly that it is a design smell to: 1) expose cases publicly if consumers of 
the API are not expected to switch on them and 2) require users to handle 
unknown future cases if they are likely to switch over the cases in correct use 
of the API.

The conclusion I came to in that thread is that we should adopt the same 
strategy as we did with classes: there should not be a default.

There have also been several discussions both on the list and via Twitter 
regarding whether or not we should allow closed protocols.  In a recent Twitter 
discussion Joe Groff suggested that we don’t need them because we should use an 
enum when there is a fixed set of conforming types.  There are at least two  
reasons why I still think we *should* add support for closed protocols.

As noted above (and in the previous thread in more detail), if the set of types 
(cases) isn’t intended to be fixed (i.e. the library may add new types in the 
future) an enum is likely not a good choice.  Using a closed protocol 
discourages the user from switching and prevents the user from adding 
conformances that are not desired.

Another use case supported by closed protocols is a design where users are not 
allowed to conform directly to a protocol, but instead are required to conform 
to one of several protocols which refine the closed protocol.  Enums are not a 
substitute for this use case.  The only option is to resort to documentation 
and runtime checks.


Proposal:

This proposal introduces the new access modifier `closed` as well as clarifying 
the meaning of `public` and expanding the use of `open`.  This provides 
consistent capabilities and semantics across enums, classes and protocols.

`open` is the most permissive modifier.  The symbol is visible outside the 
module and both users and future versions of the library are allowed to add new 
cases, subclasses or conformances.  (Note: this proposal does not introduce 
user-extensible `open` enums, but provides the syntax that would be used if 
they are added to the language)

`public` makes the symbol visible without allowing the user to add new cases, 
subclasses or conformances.  The library reserves the right to add new cases, 
subclasses or conformances in a future version.

`closed` is the most restrictive modifier.  The symbol is visible publicly with 
the commitment that future versions of the library are *also* prohibited from 
adding new cases, subclasses or conformances.  Additionally, all cases, 
subclasses or conformances must be visible outside the module.

Note: the `closed` modifier only applies to *direct* subclasses or 
conformances.  A subclass of a `closed` class need not be `closed`, in fact it 
may be `open` if the design of the library requires that.  A class that 
conforms to a `closed` protocol also need not be `closed`.  It may also be 
`open`.  Finally, a protocol that refines a `closed` protocol need not be 
`closed`.  It may also be `open`.

This proposal is consistent with the principle that libraries should opt-in to 
all public API co

Re: [swift-evolution] Warning when omitting default case for imported enums

2017-02-07 Thread Matthew Johnson via swift-evolution

> On Feb 7, 2017, at 3:01 PM, Michael Ilseman via swift-evolution 
>  wrote:
> 
> BTW, this will likely be part of the eventual design of “open”/resilient 
> enums ala 
> https://github.com/apple/swift/blob/master/docs/LibraryEvolution.rst#enums 
> . 
> There, the goal is to reduce both ABI and source breakage caused by this sort 
> of thing. It seems like for your purposes, you’re less inclined to care about 
> ABI breakage than source breakage, though that may change in the future.

Source breakage is generally *desirable* in the context of switch statements 
over the cases of an enum.  This is why I am strongly opposed to the idea of 
making open enums the default.  

It feels like this would only be a desirable API contract for enums which it 
would be unusual for user code to switch over.  Any time user code might 
reasonably switch over the cases it feels like the wrong API contract.  How is 
the user code supposed to handle the unknown future cases correctly?  

I think it’s also worth asking the question: if user code is not supposed to 
switch over the cases of the enum, why is the type exposed publicly as an enum 
at all?  This means the cases are only intended to be used by the user to 
create values of the type.  Maybe a better API design would be something like 
the following:

public struct Foo {
private enum Value {
case foo1
case foo2(String)
}

private let value: Value
private init(_ value: Value) {
self.value = value
}

public static var foo1: Foo {
return Foo(.foo1)
}
public static func foo2(_ value: String) -> Foo {
return Foo(.foo2(value))
}
}

public func apiFunctionTakingFoo(_ foo: Foo) {}

// user code:
apiFunctionTakingFoo(.foo1)
apiFunctionTakingFoo(.foo2(""))

This provides the same syntactic convenience for users when constructing values 
and allows adding new values (i.e. “cases”), retains the ability to use an enum 
internally in the implementation, and intentionally prevents users from 
switching over the open set of values in a fragile way (i.e. handling unknown 
future values / cases in a `default` clause).  

This requires some boilerplate but it feels like it may often be a better API 
design when the library author is not willing to commit to the contract of a 
closed enum.  It feels like it should be unusual when a library author expects 
users to switch over the cases, but also wants to add new cases in the future.


> 
> 
> 
>> On Feb 7, 2017, at 7:12 AM, Tanner Nelson via swift-evolution 
>> mailto:swift-evolution@swift.org>> wrote:
>> 
>> Hello Swift Evolution,
>> 
>> I'd like to propose that a warning be emitted when default cases are omitted 
>> for enums from other modules. 
>> 
>> What this would look like:
>> 
>> OtherModule:
>> ```
>> public enum SomeEnum {
>> case one
>> case two
>> }
>> 
>> public let global: SomeEnum = .one
>> ```
>> 
>> executable:
>> ```
>> import OtherModule
>> 
>> switch OtherModule.global {
>> case .one: break
>> case .two: break
>> ^ ⚠︎ Warning: Default case recommended for imported enums. Fix-it: 
>> Add `default: break`
>> }
>> ```
>> 
>> Why:
>> 
>> Allowing the omission of a default case in an exhaustive switch makes the 
>> addition of a new case to the enum a breaking change. 
>> In other words, if you're exhaustively switching on an enum from an imported 
>> library, the imported library can break your code by adding a new case to 
>> that enum (which the library authors may erroneously view as an 
>> additive/minor-bump change).
>> 
>> Background:
>> 
>> As a maintainer of a Swift framework, public enums have been a pain point in 
>> maintaining semver. They've made it difficult to implement additive features 
>> and have necessitated the avoidance of enums in our future public API plans.
>> 
>> Related Twitter thread: 
>> https://twitter.com/tanner0101/status/796860273760104454 
>> 
>> 
>> Looking forward to hearing your thoughts.
>> 
>> Best,
>> Tanner
>> 
>> Tanner Nelson
>> Vapor 
>> +1 (435) 773-2831
>> 
>> 
>> 
>> 
>> 
>> 
>> 
>> ___
>> 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] Warning when omitting default case for imported enums

2017-02-07 Thread Matthew Johnson via swift-evolution

> On Feb 7, 2017, at 1:45 PM, Robert Widmann via swift-evolution 
>  wrote:
> 
> I lean +1, but this answer on its own seems incomplete.  Exhaustiveness is an 
> important property, and it’s not clear what happens here now when you fall 
> through a “complete” case tree without matching a pattern, and in that sense 
> this plan solves a problem.  But it also would hinder a “future-you” from 
> going back and dealing with the ramifications of swapping a dependency for a 
> newer version, in that with a default now covering the rest of the cases the 
> compiler is unable to tell you which cases you are actually missing 
> post-upgrade.
> 
> Library Evolution 
>  
> includes what I think is the more complete response here: An @closed 
> attribute for enums where a switch is guaranteed to be exhaustive.  (Though, 
> after the open discussion, I wonder if that keyword can’t be reused in some 
> way to provide the inverse restriction instead).

I agree that we probably need to allow both and the question is whether we have 
a default or not, and if we do, which one is the default.  

Personally, if we have a default I would prefer for the default to be closed.  
One of the most important attributes of enums is the fact that they encompass a 
fixed set of known cases.  I *want* my code to break if a new case is added to 
an enum of another module I depend on.  As the Library Evolution document notes 
"adding new cases should not be done lightly. Any clients attempting to do an 
exhaustive switch over all enum cases will likely not handle new cases well.”.  
Perhaps if a module author is not willing to commit to a fixed set of cases 
maybe publicly exposing an enum’s cases is not the best way to model the API in 
question.

I understand that making closed the default is the is slightly contrary to the 
principle that a module author explicitly opts-in to public API contracts.  
With that in mind, I would also consider it acceptable to decide that there 
should be *no* default, as we did in the `open` discussion.

It’s also worth noting that in the context of enums there are two ways in which 
an enum might be considered open - open to future extension by the module 
itself and open to extension by other modules.  The latter most closely matches 
the meaning of the `open` access modifier as it is currently used and I believe 
it has been requested on the list once or twice.  With that in mind, I don’t 
think we should reuse the `open` keyword to mean “open to extension in a future 
version of the module, but not open to extension by users of the module”.  That 
is basically equivalent to the meaning of `public` for classes.

This leads me to conclude that maybe the right answer here is to require 
library authors to specify `closed` *or* `public` when exposing an enum outside 
the module.  This follows the principle of library authors explicitly opting in 
to public API contracts, but also does not penalize the library author with 
additional verbosity for the contract which is more likely to lead to correct 
client code.


> 
>> On Feb 7, 2017, at 10:12 AM, Tanner Nelson via swift-evolution 
>> mailto:swift-evolution@swift.org>> wrote:
>> 
>> Hello Swift Evolution,
>> 
>> I'd like to propose that a warning be emitted when default cases are omitted 
>> for enums from other modules. 
>> 
>> What this would look like:
>> 
>> OtherModule:
>> ```
>> public enum SomeEnum {
>> case one
>> case two
>> }
>> 
>> public let global: SomeEnum = .one
>> ```
>> 
>> executable:
>> ```
>> import OtherModule
>> 
>> switch OtherModule.global {
>> case .one: break
>> case .two: break
>> ^ ⚠︎ Warning: Default case recommended for imported enums. Fix-it: 
>> Add `default: break`
>> }
>> ```
>> 
>> Why:
>> 
>> Allowing the omission of a default case in an exhaustive switch makes the 
>> addition of a new case to the enum a breaking change. 
>> In other words, if you're exhaustively switching on an enum from an imported 
>> library, the imported library can break your code by adding a new case to 
>> that enum (which the library authors may erroneously view as an 
>> additive/minor-bump change).
>> 
>> Background:
>> 
>> As a maintainer of a Swift framework, public enums have been a pain point in 
>> maintaining semver. They've made it difficult to implement additive features 
>> and have necessitated the avoidance of enums in our future public API plans.
>> 
>> Related Twitter thread: 
>> https://twitter.com/tanner0101/status/796860273760104454 
>> 
>> 
>> Looking forward to hearing your thoughts.
>> 
>> Best,
>> Tanner
>> 
>> Tanner Nelson
>> Vapor 
>> +1 (435) 773-2831
>> 
>> 
>> 
>> 
>> 
>> 
>> 
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org 
>> https://lists.swift.org/mailman/listinfo/

Re: [swift-evolution] [RFC][Proposal] Ease restrictions on protocol nesting

2017-02-07 Thread Matthew Johnson via swift-evolution

> On Feb 6, 2017, at 11:12 PM, Karl Wagner via swift-evolution 
>  wrote:
> 
> 
>> On 7 Feb 2017, at 06:05, Slava Pestov > > wrote:
>> 
>>> 
>>> On Feb 6, 2017, at 9:00 PM, Karl Wagner via swift-evolution 
>>> mailto:swift-evolution@swift.org>> wrote:
>>> - Nested protocols in generic types are not parameterised by the parent's 
>>> generic parameters.
>> So if I write GenericType.SomeProto and GenericType.SomeProto, 
>> is it the same protocol? What about GenericType.SomeProto, is that allowed?
>> 
>> Slava
> 
> GenericType.SomeProto (without parameters) is the only spelling that is 
> allowed. There is no GenericType.SomeProto.
> 
> That way we avoid every bound-generic type creating a new protocol. 

I have only had a chance to scan the proposal so I will probably have more 
comments after I take a closer look, but I want to respond to this topic right 
away.

I understand the reason why you want it to work this way, but think it will be 
a significant source of confusion.  Protocols will behave differently than any 
other entity nested in a generic type.  This means the protocols nested in 
generic types will likely be counterintuitive for most people.  

I know this was the case for me while I was scanning the proposal.  I had to 
think carefully to understand how you want this to work and why you want this 
behavior.  That is despite it being a relatively direct consequence of the 
Swift’s design for protocols, which uses associated types and intentionally 
does not allow generic protocols.

It may be that there isn’t a good way to avoid that and we need to try to 
address it through documentation and education.  But I think this should 
receive careful consideration before we commit to this direction.

Overall the proposal looks really great!  I’m really looking forward to this 
feature.  

> I think it works really nicely when you consider what it would like like with 
> existential-based capturing. Notice that there is only one 
> ‘MyCollectionView.Source’, and compatibility is determined based on 
> existential constraints.
> 
> - Karl
> 
> 
> class MyCollectionView : UICollectionView {
> 
> protocol Source {
> // [implicit] associatedtype MediaItem
> func item(at: Int) -> MediaItem
> var numberOfItems: Int { get }
> }
> var source: Any // 
> Not possible today.
> }
> 
> class BookSource: MyCollectionView.Source {
> typealias MediaItem = Book
> 
> func item(at: Int) -> Book { /* ... */ }
> var numberOfItems: Int { /* ... */ }
> }
> 
> class DummySource: MyCollectionView.Source where MediaItem: 
> DummyConstructable {
> // associatedtype 'MediaItem' bound to generic parameter.
> 
> func item(at: Int) -> MediaItem { /* ... */ }
> var numberOfItems: Int  { /* ... */ } 
> }
> 
> MyCollectionView().source = BookSource()
> MyCollectionView().source = DummySource()
> MyCollectionView().source  = DummySource() // type is: DummySource
> MyCollectionView().source = DummySource() // type is: 
> DummySource
> 
> 
> 
> ___
> 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-build-dev] Package manager support for versioning (both language and tools)

2017-02-06 Thread Matthew Johnson via swift-evolution

> On Feb 6, 2017, at 2:06 PM, Rick Ballard  wrote:
> 
> Hi Matthew,
> 
> The reason I was suggesting a simple DSL in a comment instead of using Swift 
> for that declaration is because we need to know what this value is before we 
> start the Swift interpreter, so that we know what Swift language 
> compatibility mode to run the interpreter in. I suppose that it'd be possible 
> to work around that; for example, we could grab the first line of the file 
> and run it through the Swift interpreter in the latest language compatibility 
> mode, assuming that a simple let statement and enum will always compile the 
> same way in all future versions of Swift. We'd figure out the Swift tools 
> version from that and then re-run the interpreter over the entire file in the 
> right language compatibility mode.
> 
> That's some fairly magic behavior to understand, though; if it's a place that 
> you can write Swift code, it's non-obvious that we're only reading a single 
> line of it. It would also be difficult to enforce the restrictions that we'd 
> like on the first line; if we're using the Swift interpreter, how do we make 
> sure that you haven't written a more complicated expression that might not 
> compile in all future versions of Swift, and/or referenced any of the 
> version-specific PackageDescription API beyond that enum? And from an 
> aesthetic standpoint, I imagine that many people would be annoyed to have a 
> single line of Swift code at the top of the file right before any comment 
> header that they'd otherwise lead their file with (e.g. containing a 
> copyright header, author info, etc).
> 
> Overall, I don't see any concrete benefit to making that first line be Swift, 
> and it adds new complications. This was worth considering, however, so thanks 
> for suggesting it!

Hi Rick,

Thanks for the reply.  I wasn’t suggesting that you actually use the Swift 
interpreter to parse this line.  My idea was that if the package format uses a 
top-level constant named `toolsVersion` that *must* be initialized with a 
direct reference to the enum case it would be easy enough to parse *without* 
using the Swift interpreter.  You would just look for a line that begins with 
`let toolsVersion = ToolsVersion._n_n_n`.  It wouldn’t necessarily need to be 
the first line.  This statement has a very simple grammar that could be parsed 
directly just as easily as a DSL we invent and put in comments.

I agree that the primary downside of this is that it would be specified using 
normal Swift syntax but would not allow the full expressivity that Swift allows 
(this constant must be initialized via directly specifying a case name rather 
than with any value of the correct type).  However, it has the advantage of 
using normal Swift syntax and all the benefits derived from that (for example, 
cmd-click in Xcode to see the valid values, reading like a normal part of the 
package specification, etc).  If the user attempted to use an expression that 
is valid Swift but does not a direct reference to one of the case names the 
package manager would handle that in the same way it would handle an invalid 
tools version in the comment DSL.

It’s not immediately obvious to me which approach makes the best overall 
tradeoff.  It seems like a topic worthy of discussion by the community, 
especially since you have already listed several options and asked for 
community input on the subject.  Does anyone else have any thoughts on this?

> 
>   - Rick
> 
>> On Feb 4, 2017, at 8:28 AM, Matthew Johnson  wrote:
>> 
>> It’s clear that a lot of work has gone into identifying and evaluating 
>> several different approaches.  Thank you for doing the hard work here!
>> 
>> I think I might have one additional alternative to consider.  I like the 
>> idea of using Package.swift to specify the tools version, but I think the 
>> disadvantages of using a DSL in a comment is less than ideal.  Is there a 
>> way we can design this to rely on normal Swift syntax?  For example, what if 
>> we required Package.swift to include a line whose first non-whitespace 
>> character is the following (possibly allowing trailing comments):
>> 
>> let toolsVersion = ToolsVersion._3_1
>> 
>> This would be supported by a ToolsVersion enum to which we add a new case 
>> with each new version of the tools.  If no such declaration is found it will 
>> be it would be considered to be 3.0.0 just as with the comment approach.
>> 
>> Is there any reason why using a comment DSL is preferable to something like 
>> this?
>> 
>> 
>> 
>>> On Feb 3, 2017, at 3:03 PM, Rick Ballard via swift-build-dev 
>>>  wrote:
>>> 
>>> As part of Swift source compatibility, the Swift compiler added a new flag 
>>> for controlling what Swift language version should be used to compile with. 
>>> Currently there is no good way to specify this for Swift packages. We've 
>>> got a proposal ready that provides a mechanism for controlling this. I'd 
>>> appreciate any feedback the community 

Re: [swift-evolution] Class and Subclass Existentials (Round 2)

2017-02-06 Thread Matthew Johnson via swift-evolution
This looks really good, thank you for your work on this proposal David!  

I agree with Doug’s suggestion to pick #4 (typealias AnyObject = class) and 
move the other options to alternatives considered.  This seems like the best 
way to go given Swift’s source compatibility promise and will probably be the 
least controversial option as well.

> On Feb 6, 2017, at 3:18 PM, David Hart via swift-evolution 
>  wrote:
> 
> Hello mailing-list,
> 
> I rewrote the draft proposal concerning the class and subclass existentials. 
> Please let me know what you think, especially concerning the class and 
> AnyObject conundrum.
> 
> Regards,
> David.
> 
> https://github.com/hartbit/swift-evolution/blob/e6411d8a9e7924bbd8a48fc292bf08d58a8d1199/proposals/-subclass-existentials.md
>  
> 
> 
> Class and Subtype existentials
> 
> Proposal: SE- 
> 
> Authors: David Hart , Austin Zheng 
> 
> Review Manager: TBD
> Status: TBD
>  
> Introduction
> 
> This proposal brings more expressive power to the type system by allowing 
> Swift to represent existentials of classes and subtypes which conform to 
> protocols.
> 
>  
> Motivation
> 
> Currently, the only existentials which can be represented in Swift are 
> conformances to a set of protocols, using the &protocol composition syntax:
> 
> Protocol1 & Protocol2
> On the other hand, Objective-C is capable of expressing existentials of 
> classes and subclasses conforming to protocols with the following syntax:
> 
> id
> Base*
> We propose to provide similar expressive power to Swift, which will also 
> improve the bridging of those types from Objective-C.
> 
>  
> Proposed
>  solution
> 
> The proposal keeps the existing & syntax but allows the first element, and 
> only the first, to be either the class keyword or of class type. The 
> equivalent to the above Objective-C types would look like this:
> 
> class & Protocol1 & Protocol2
> Base & Protocol
> As in Objective-C, the first line is an existential of classes which conform 
> to Protocol1 and Protocol2, and the second line is an existential of subtypes 
> of Base which conform to Protocol.
> 
> Here are the new proposed rules for what is valid in a existential 
> conjunction syntax:
> 
>  
> 1.
>  The first element in the protocol composition syntax can be the class 
> keyword to enforce a class constraint:
> 
> protocol P {}
> struct S : P {}
> class C : P {}
> let t: P & class // Compiler error: class requirement must be in first 
> position
> let u: class & P = S() // Compiler error: S is not of class type
> let v: class & P = C() // Compiles successfully
>  
> 2.
>  The first element in the protocol composition syntax can be a class type to 
> enforce the existential to be a subtype of the class:
> 
> protocol P {}
> struct S {}
> class C {}
> class D : P {}
> class E : C, P {}
> let t: P & C // Compiler error: subclass contraint must be in first position
> let u: S & P // Compiler error: S is not of class type
> let v: C & P = D() // Compiler error: D is not a subtype of C
> let w: C & P = E() // Compiles successfully
>  
> 3.
>  When a protocol composition type contains a typealias, the validity of the 
> type is determined using the following steps:
> 
> Expand the typealias
> Normalize the type by removing duplicate constraints and replacing less 
> specific constraints by more specific constraints (a class constraint is less 
> specific than a class type constraint, which is less specific than a 
> constraint of a subclass of that cla

Re: [swift-evolution] Subclass Existentials

2017-02-06 Thread Matthew Johnson via swift-evolution

> On Feb 6, 2017, at 11:30 AM, Douglas Gregor via swift-evolution 
>  wrote:
> 
> 
>> On Feb 5, 2017, at 3:20 PM, David Hart > > wrote:
>> 
>> As they are heavily linked, should a change like this be included in the 
>> superclass + class proposal or separately?
>> 
>> I'm heavily tending towards (1), and redefining:
>> 
>> typealias Any = Any<>
>> typealias AnyObject = Any
>> 
>> Does that sound reasonable to you? Just checking before I rewrite this 
>> proposal sometime in the next couple of days.
> 
> Tricky business; you have a proposal that’s very likely to get universal 
> support (adding class constraints to existentials) and one that’s likely to 
> be controversial (changing existential syntax away from what we just adopted 
> in Swift 3). My inclination is to separate the two, because I worry that the 
> first proposal could get swallowed up in the discussion of the second… and it 
> gets more messy if we have to detangle one proposal into two after running 
> the review.

+1 

> 
>   - Doug
> 
>> 
>> David
>> 
>> On 3 Feb 2017, at 18:12, Douglas Gregor > > wrote:
>> 
>>> 
 On Feb 2, 2017, at 3:24 PM, David Hart >>> > wrote:
 
> 
> On 3 Feb 2017, at 00:04, Douglas Gregor via swift-evolution 
> mailto:swift-evolution@swift.org>> wrote:
> 
> 
>> On Feb 2, 2017, at 2:54 PM, David Smith > > wrote:
>> 
>>> 
>>> On Feb 2, 2017, at 11:20 AM, Douglas Gregor via swift-evolution 
>>> mailto:swift-evolution@swift.org>> wrote:
>>> 
>>> 
 On Feb 1, 2017, at 11:44 PM, Adrian Zubarev 
 >>> > wrote:
 
 typealias AnyObject = … is nice to have, but how about if we fully 
 drop the class constraint-keyword and generalize AnyObject instead?
 
>>> That’s a good point. My *technical* goal is for AnyObject to cease to 
>>> be a protocol, because it’s really describing something more 
>>> fundamental (“it’s a class!”). Whether we spell that constraint as 
>>> “class” or “AnyObject” doesn’t affect that technical goal.
>>> 
>>> I’d gravitated toward the “class” spelling because the idea of a class 
>>> constraint seems most naturally described by “class”, and it’s 
>>> precedented in C#.
>>> 
>>> However, the changes in SE-0095 
>>> 
>>>  to make “Any” a more fundamental type (and not just a typealias) 
>>> definitely open the door to doing the same thing with “AnyObject”—just 
>>> make it a built-in notion in the language, and the spelling for a class 
>>> constraint. It *certainly* works better with existentials.
>>> 
 In the future we might want to add AnyValue with value (semantics) 
 constraint, would that mean that we’d need another keyword there like 
 value?
 
>>> “value” would be a terrible keyword, as you know. Point taken :)
>>> 
>>> If we did something like this, we would probably want it to be akin to 
>>> ValueSemantics—not just “it’s a struct or enum”, but “it provides value 
>>> semantics”, because not all structs/enums provide value semantics (but 
>>> immutable classes do).
>>> 
 Speaking of the future directions:
 
 Now that we’re no longer supporting the idea of Any<…> syntax and any 
 type prefixed with Any seems to be special for its particular usage, 
 could we safely bring the empty Any protocol back (is this somehow ABI 
 related?)?
 
>>> From an implementation standpoint, the choice to make AnyObject a magic 
>>> protocol was a *horrible* decision. We have hacks throughout 
>>> everything—the compiler, optimizers, runtime, and so on—that 
>>> specifically check for the magic AnyObject protocol. So, rather than 
>>> make Any a magic protocol, we need to make AnyObject *not* magic.
>>> 
 One day after this proposal is accepted, implemented and released, we 
 probably will talk about the where clause for existentials. But since 
 a lot of the existentials will have the form typealias Abc = …, this 
 talk will also include the ability to constrain generic typealiases.
 
>>> By “one day” I suspect you mean “some day” rather than “the day after” 
>>> :)
>>> 
>>> Yes, I feel like this is a natural direction for existentials to go.
>> 
>> Looking ahead to when this is on the table, I'm a little worried about 
>> the syntactic implications of constrained existentials now that the 
>> Any<> syntax doesn't seem to be as popular. The obvious way to go would 
>> be
>> 
>> 'X & Y where …'
>> 
>> But that leads to ambiguity in function declarations
>> 
>> func doTh

Re: [swift-evolution] [swift-build-dev] Package manager support for versioning (both language and tools)

2017-02-04 Thread Matthew Johnson via swift-evolution
It’s clear that a lot of work has gone into identifying and evaluating several 
different approaches.  Thank you for doing the hard work here!

I think I might have one additional alternative to consider.  I like the idea 
of using Package.swift to specify the tools version, but I think the 
disadvantages of using a DSL in a comment is less than ideal.  Is there a way 
we can design this to rely on normal Swift syntax?  For example, what if we 
required Package.swift to include a line whose first non-whitespace character 
is the following (possibly allowing trailing comments):

let toolsVersion = ToolsVersion._3_1

This would be supported by a ToolsVersion enum to which we add a new case with 
each new version of the tools.  If no such declaration is found it will be it 
would be considered to be 3.0.0 just as with the comment approach.

Is there any reason why using a comment DSL is preferable to something like 
this?



> On Feb 3, 2017, at 3:03 PM, Rick Ballard via swift-build-dev 
>  wrote:
> 
> As part of Swift source compatibility, the Swift compiler added a new flag 
> for controlling what Swift language version should be used to compile with. 
> Currently there is no good way to specify this for Swift packages. We've got 
> a proposal ready that provides a mechanism for controlling this. I'd 
> appreciate any feedback the community would like addressed before this goes 
> through evolution review.
> 
> The Swift language version support proposal can be viewed and commented on at 
> https://github.com/rballard/swift-evolution/pull/2/files
> 
> Additionally, we are proposing to introduce a "Swift minimum tools version" 
> mechanism for Swift packages. This mechanism will allow us to evolve the 
> package manager – adding new API, and doing a one-time revision of our 
> existing API for Swift 4 – without breaking the package ecosystem. It will 
> also manage the Swift 3–>4 language transition for Package.swift files 
> themselves. This is a pretty lengthy proposal, but I'd appreciate any 
> important feedback before this goes to evolution review. There is also one 
> decision left to make before this proposal is final; I lay out several 
> possibilities for how we could store the "Swift tools version". I'd 
> appreciate feedback on which of the possibilities we should pick before I 
> bring this to review.
> 
> The Swift tools version support proposal can be viewed and commented on at 
> https://github.com/rballard/swift-evolution/pull/1/files
> 
> Absent any serious feedback which requires us to make major revisions, I'm 
> expecting to bring both of these to Swift evolution review early next week.
> 
> Thank you,
> 
>   - Rick
> 
> ___
> swift-build-dev mailing list
> swift-build-...@swift.org
> https://lists.swift.org/mailman/listinfo/swift-build-dev

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


Re: [swift-evolution] Removing enumerated?

2017-02-03 Thread Matthew Johnson via swift-evolution

> On Feb 3, 2017, at 3:41 PM, Ben Cohen via swift-evolution 
>  wrote:
> 
> 
>> On Feb 2, 2017, at 8:46 PM, Chris Lattner > > wrote:
>> 
>> It seems that you are leaning towards removing enumerated(). 
> 
> I’m actually kind of conflicted.
> 
> Replacing enumerated() with indexed() feels replacing one problem for 
> another. Sometimes people want to number things, and might assume indexed() 
> will be zero-based for slices.
> 
> Adding indexed() while keeping enumerated() seems too much clutter on the API 
> though. Once we have 0… both can be expressed simply with zip, and in my view 
> is zip(a, 0…), zip(a, a.indices), zip(1…, a) just as clear, maybe clearer in 
> some cases as they will encourage code to show intent more (i.e. are you 
> counting or indexing? even when they are the same, it’s better to say which). 
> Encouraging learning about zip will also help introduce people to better ways 
> of expressing other similar-but-different loops.
> 
> The trouble with zip is it isn’t discoverable – another entry that probably 
> belongs on that list of criteria. Unlike enumerated, users aren’t going to 
> stumble over it.
> 
> Maybe moving zip to be a method on Sequence rather than a free function would 
> help with this? e.g. something like a.zipped(with: 0…), a.zipped(with: 
> a.indices). The documentation for it could even explicitly mention the 
> counting and index use cases. The main downside is it pushes the order of the 
> lhs/rhs to be self first.

I think the downside is significant.  I think the visual relationship of 
`zip(a, 0…)` with the tuples it produces is pretty important.  It also scales 
well if (when?) it becomes variadic.

Discoverability is a problem, but no more so than with any other top level 
operator somebody might not be familiar with (Swift has a few of those 
depending on somebody’s background)

I think the discoverability problem is best addressed by identifying and 
raising awareness of common use cases for zip rather than just moving it so it 
appears in autocomplete.  When people learn how it can make their code better 
they will use it.

> 
> 
> 
> ___
> 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] Either protocol syntax

2017-02-02 Thread Matthew Johnson via swift-evolution

> On Feb 2, 2017, at 4:02 PM, Rex Fenley  wrote:
> 
> But then any time as user of the pipeline I'm writing would like a new type 
> of collection they will be forced to inherit this new protocol vs one they're 
> already familiar with and which the collection may already conform too.

Yes, that is true.  But if you design your new protocol such that it’s 
requirements all match a requirement in `RangeReplaceableCollection` then 
conformance will be a one-line extension.  This may not be ideal, but it’s 
really not too bad and you can do it today.

> 
> On Thu, Feb 2, 2017 at 1:53 PM, Matthew Johnson  > wrote:
> 
>> On Feb 2, 2017, at 3:46 PM, Rex Fenley > > wrote:
>> 
>> My use case is RLMArray and it can't implement RangeReplaceableCollection 
>> though because `init` is unavailable, additionally, there's a lot of parts 
>> to the protocol that would take some time to implement correctly if I could. 
>> They offer a Swift type List that wraps RLMArray and does a bunch of stuff 
>> to implement RangeReplaceableCollection, but they discourage using their 
>> Swift library in mixed Obj-C/Swift projects and certain model objects simply 
>> couldn't use the List type anyway because they're also used in Obj-C and 
>> List is not @objc compliant.
>> 
>> So this leaves me in situations where when I need to use Array or RLMArray I 
>> have to duplicate my code, not just in one place, but all the way down a 
>> pipeline in order to have my generics work with either 
>> RangeReplaceableCollection or RLMArray.
>> 
>> If I could abstract the commonalities required by my application, I could 
>> just have a RLMArrayProtocol that has RLMArray's exposed function signatures 
>> and a new protocol Appendable = RangeReplaceableCollection | 
>> RLMArrayProtocol and this will type check all the way through the pipeline.
>> 
>> tl;dr - if a function signature required by a protocol is marked unavailable 
>> on a class, then disjunction is necessary in order to bridge the two (or 
>> more) types without duplicating code.
> 
> You should be able to solve this problem today by creating a custom protocol 
> that you use as a constraint in your generic code and providing conformances 
> for both Array and RLMArray.
> 
>> 
>> On Thu, Feb 2, 2017 at 1:35 PM, Matthew Johnson > > wrote:
>>> 
>>> On Feb 2, 2017, at 3:26 PM, Rex Fenley via swift-evolution 
>>> mailto:swift-evolution@swift.org>> wrote:
>>> 
>>> Hello, I believe there was some discussion about this quite awhile ago. I 
>>> was wondering if there's any interest in including a protocol 'or' type 
>>> that would be the intersection of two protocols. This could be really 
>>> useful in situations where a framework that the user has no control over 
>>> implements a portion of some often used protocol. Such as specialized 
>>> collections from an Database framework that don't implement 
>>> RangeReplaceableCollection but have a set of methods that are equivalent. 
>>> The user can then implement a protocol that is the intersection of those 
>>> set of methods and not duplicate code.
>> 
>> If the specialized collection in the database framework already provides 
>> functionality equivalent to `RangeReplaceableCollection` what you really 
>> want to do is just provide the conformance you’re looking for in an 
>> extension:
>> 
>> extension SpecializedDatabaseCollection: RangeReplaceableCollection {
>>// if necessary, provide forwarding wrappers where the member names don’t 
>> match up.
>> }
>> 
>> But in a case like this the framework itself really should provide this 
>> conformance out of the box.  If they didn’t, maybe there is a good reason so 
>> you would want to find out why it wasn’t provided.
>> 
>> Is there something you’re hoping to do that you can’t solve by simply 
>> extending the framework types?
>> 
>>> 
>>> Simplified example:
>>> 
>>> protocol Animal {
>>> var hasEars: Bool { get }
>>> func grow()
>>> }
>>> 
>>> protocol Plant {
>>> var isGreen: Bool { get }
>>> func grow()
>>> }
>>> 
>>> protocol LivingThing = Plant | Animal // or a different syntax
>>> 
>>> LivingThing's is as follows
>>> {
>>> func grow()
>>> }
>>> 
>>> -- 
>>> Rex Fenley  |  IOS DEVELOPER
>>> 
>>> 
>>> Remind.com  |  BLOG   |  
>>> FOLLOW US   |  LIKE US 
>>> ___
>>> swift-evolution mailing list
>>> swift-evolution@swift.org 
>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>> 
>> 
>> 
>> 
>> 
>> -- 
>> Rex Fenley  |  IOS DEVELOPER
>> 
>> 
>> Remind.com  |  BLOG   |  
>> FOLLOW US   |  LIKE US 
>> 
> 
> 

Re: [swift-evolution] Either protocol syntax

2017-02-02 Thread Matthew Johnson via swift-evolution

> On Feb 2, 2017, at 3:46 PM, Rex Fenley  wrote:
> 
> My use case is RLMArray and it can't implement RangeReplaceableCollection 
> though because `init` is unavailable, additionally, there's a lot of parts to 
> the protocol that would take some time to implement correctly if I could. 
> They offer a Swift type List that wraps RLMArray and does a bunch of stuff to 
> implement RangeReplaceableCollection, but they discourage using their Swift 
> library in mixed Obj-C/Swift projects and certain model objects simply 
> couldn't use the List type anyway because they're also used in Obj-C and List 
> is not @objc compliant.
> 
> So this leaves me in situations where when I need to use Array or RLMArray I 
> have to duplicate my code, not just in one place, but all the way down a 
> pipeline in order to have my generics work with either 
> RangeReplaceableCollection or RLMArray.
> 
> If I could abstract the commonalities required by my application, I could 
> just have a RLMArrayProtocol that has RLMArray's exposed function signatures 
> and a new protocol Appendable = RangeReplaceableCollection | RLMArrayProtocol 
> and this will type check all the way through the pipeline.
> 
> tl;dr - if a function signature required by a protocol is marked unavailable 
> on a class, then disjunction is necessary in order to bridge the two (or 
> more) types without duplicating code.

You should be able to solve this problem today by creating a custom protocol 
that you use as a constraint in your generic code and providing conformances 
for both Array and RLMArray.

> 
> On Thu, Feb 2, 2017 at 1:35 PM, Matthew Johnson  > wrote:
>> 
>> On Feb 2, 2017, at 3:26 PM, Rex Fenley via swift-evolution 
>> mailto:swift-evolution@swift.org>> wrote:
>> 
>> Hello, I believe there was some discussion about this quite awhile ago. I 
>> was wondering if there's any interest in including a protocol 'or' type that 
>> would be the intersection of two protocols. This could be really useful in 
>> situations where a framework that the user has no control over implements a 
>> portion of some often used protocol. Such as specialized collections from an 
>> Database framework that don't implement RangeReplaceableCollection but have 
>> a set of methods that are equivalent. The user can then implement a protocol 
>> that is the intersection of those set of methods and not duplicate code.
> 
> If the specialized collection in the database framework already provides 
> functionality equivalent to `RangeReplaceableCollection` what you really want 
> to do is just provide the conformance you’re looking for in an extension:
> 
> extension SpecializedDatabaseCollection: RangeReplaceableCollection {
>// if necessary, provide forwarding wrappers where the member names don’t 
> match up.
> }
> 
> But in a case like this the framework itself really should provide this 
> conformance out of the box.  If they didn’t, maybe there is a good reason so 
> you would want to find out why it wasn’t provided.
> 
> Is there something you’re hoping to do that you can’t solve by simply 
> extending the framework types?
> 
>> 
>> Simplified example:
>> 
>> protocol Animal {
>> var hasEars: Bool { get }
>> func grow()
>> }
>> 
>> protocol Plant {
>> var isGreen: Bool { get }
>> func grow()
>> }
>> 
>> protocol LivingThing = Plant | Animal // or a different syntax
>> 
>> LivingThing's is as follows
>> {
>> func grow()
>> }
>> 
>> -- 
>> Rex Fenley  |  IOS DEVELOPER
>> 
>> 
>> Remind.com  |  BLOG   |  
>> FOLLOW US   |  LIKE US 
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org 
>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> 
> 
> 
> 
> 
> -- 
> Rex Fenley  |  IOS DEVELOPER
> 
> 
> Remind.com  |  BLOG   |  
> FOLLOW US   |  LIKE US 
> 
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Either protocol syntax

2017-02-02 Thread Matthew Johnson via swift-evolution
> 
> On Feb 2, 2017, at 3:26 PM, Rex Fenley via swift-evolution 
>  wrote:
> 
> Hello, I believe there was some discussion about this quite awhile ago. I was 
> wondering if there's any interest in including a protocol 'or' type that 
> would be the intersection of two protocols. This could be really useful in 
> situations where a framework that the user has no control over implements a 
> portion of some often used protocol. Such as specialized collections from an 
> Database framework that don't implement RangeReplaceableCollection but have a 
> set of methods that are equivalent. The user can then implement a protocol 
> that is the intersection of those set of methods and not duplicate code.

If the specialized collection in the database framework already provides 
functionality equivalent to `RangeReplaceableCollection` what you really want 
to do is just provide the conformance you’re looking for in an extension:

extension SpecializedDatabaseCollection: RangeReplaceableCollection {
   // if necessary, provide forwarding wrappers where the member names don’t 
match up.
}

But in a case like this the framework itself really should provide this 
conformance out of the box.  If they didn’t, maybe there is a good reason so 
you would want to find out why it wasn’t provided.

Is there something you’re hoping to do that you can’t solve by simply extending 
the framework types?

> 
> Simplified example:
> 
> protocol Animal {
> var hasEars: Bool { get }
> func grow()
> }
> 
> protocol Plant {
> var isGreen: Bool { get }
> func grow()
> }
> 
> protocol LivingThing = Plant | Animal // or a different syntax
> 
> LivingThing's is as follows
> {
> func grow()
> }
> 
> -- 
> Rex Fenley  |  IOS DEVELOPER
> 
> 
> Remind.com  |  BLOG   |  
> FOLLOW US   |  LIKE US 
> ___
> 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] Strings in Swift 4

2017-02-02 Thread Matthew Johnson via swift-evolution

> On Feb 2, 2017, at 1:19 PM, Dave Abrahams via swift-evolution 
>  wrote:
> 
> 
> on Thu Feb 02 2017, Matthew Johnson  wrote:
> 
>>> On Feb 2, 2017, at 9:45 AM, Dave Abrahams 
>> wrote:
>>> 
>>> 
>>> 
>>> 
>> 
>>> 
>>> On Feb 2, 2017, at 7:11 AM, Matthew Johnson >> > wrote:
>>> 
> 
>> 
>> Furthermore, we emphatically do *not* need to make the
>> distinction you claim between “infinite” and “incomplete” ranges,
>> which *is* needless hairsplitting.
> 
> Strongly disagree, unless you can describe the semantics of the type 
> WITHOUT giving it different semantics depending on how it is used.
 
 This is the point that convinced me.  I’m going to take a closer
 look at Brent’s `RangeExpression` design which I must admit I only
 skimmed in the earlier discussion.
>>> 
>>> We already have exactly this situation with CountableRange (which
>>> will merge with Range when conditional conformances land).  When
>>> used as a Collection, it means "every index value starting with the
>>> lowerBound and ending just before the upperBound".  When used for
>>> slicing, it means, roughly, "take every one of the collection's
>>> indices that are in bounds.”
>> 
>> I don’t see how the behavior of the following code means roughly “take
>> every one of the collection’s indices that are in bounds”.  Can you
>> elaborate?
>> 
>> let range = 0..<20
>> let array = [1, 2, 3]
>> let slice = array[range] // trap on index out of bounds
> 
> “Roughly” means “I'm leaving out the part that it's a precondition that
> any (explicit) bound must be a valid index in the collection.”  
> 
>>> These are not the same thing.  A collection's indices need not
>>> include every expressible value of the Index type between startIndex
>>> and endIndex.
>> 
>> Sure, but it does appear as if the behavior of slicing assumes that
>> the upper and lower bounds of the range provided are valid indices.
> 
> Properly stated, it's a precondition.  This is a design decision.  We could
> have made slicing lenient, like Python's:
> 
 [1, 2][50]
> 
 [1, 2][5:10]
> []
> 
> We thought that in Swift it was more important to catch potential errors
> than to silently accept
> 
>[1, 2][5..<10]
> 
> we still have the option to loosen slicing so it works that way, but I
> am not at all convinced it would be an improvement.

I agree with the current behavior as it’s consistent with indexing.

Lenient slicing is in the same space as lenient indexing.  It’s easy enough to 
add lenient wrappers around the standard library’s trapping implementation.

If we ever decided to have both variants one would have to include a label and 
I don’t think anybody would support labeling the trapping variant (for many 
reasons).

> 
>> Xiaodi had convinced me that a one-sided range must take a position on
>> whether or not it has an infinite upper bound in order to make sense,
>> but now you’ve changed my mind back.
> 
> Phew!  To be clear:
> 
>  A one-sided range is *partial*.  It *has no* upper bound.

Ha!  I actually used the term “partial range" earlier.  :)

The distinction between having an infinite upper bound and having no upper 
bound, but still conforming to `Sequence` is pretty subtle.  

Ultimately I think having a really good name (`RangeExpression`) that implies 
that the usage site determines the meaning is super important to making this 
work.  Kudos to whoever came up with that name!

> 
>>> The whole point of the name RangeExpression is to acknowledge this
>>> truth: ranges in Swift bits of syntax whose meaning is given partly
>>> by how they are used.
>> 
>> This makes sense and is roughly the position I started with.  I should
>> have read through the archives of this thread more before jumping into
>> the middle of the discussion - I was missing some important context.
>> I apologize for not doing so.
> 
> No apology needed.  I really appreciate how everyone on this list works
> hard to discover the underlying truth in Swift's design.  Without that
> kind of engagement, Swift would be far worse off.
> 
> Thanks, everybody

Agree.  And I really appreciate the willingness of the core team to spend 
valuable time engaging with the community and helping to illuminate the design. 
 You have all spent significantly more time thinking about the “underlying 
truth” of the design than the rest of us!  

> 
> -- 
> -Dave
> 
> ___
> 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] Strings in Swift 4

2017-02-02 Thread Matthew Johnson via swift-evolution

> On Feb 2, 2017, at 9:45 AM, Dave Abrahams  wrote:
> 
> 
> 
> Sent from my iPad
> 
> On Feb 2, 2017, at 7:11 AM, Matthew Johnson  > wrote:
> 
>>> 
 
 Furthermore, we emphatically do *not* need to make the distinction you 
 claim between “infinite” and “incomplete” ranges, which *is* needless 
 hairsplitting.
>>> 
>>> Strongly disagree, unless you can describe the semantics of the type 
>>> WITHOUT giving it different semantics depending on how it is used.
>> 
>> This is the point that convinced me.  I’m going to take a closer look at 
>> Brent’s `RangeExpression` design which I must admit I only skimmed in the 
>> earlier discussion.
> 
> We already have exactly this situation with CountableRange (which will merge 
> with Range when conditional conformances land).  When used as a Collection, 
> it means "every index value starting with the lowerBound and ending just 
> before the upperBound".  When used for slicing, it means, roughly, "take 
> every one of the collection's indices that are in bounds.”  

I don’t see how the behavior of the following code means roughly “take every 
one of the collection’s indices that are in bounds”.  Can you elaborate?

let range = 0..<20
let array = [1, 2, 3]
let slice = array[range] // trap on index out of bounds

> These are not the same thing.  A collection's indices need not include every 
> expressible value of the Index type between startIndex and endIndex.

Sure, but it does appear as if the behavior of slicing assumes that the upper 
and lower bounds of the range provided are valid indices.  

Xiaodi had convinced me that a one-sided range must take a position on whether 
or not it has an infinite upper bound in order to make sense, but now you’ve 
changed my mind back.

> 
> The whole point of the name RangeExpression is to acknowledge this truth: 
> ranges in Swift bits of syntax whose meaning is given partly by how they are 
> used.  

This makes sense and is roughly the position I started with.  I should have 
read through the archives of this thread more before jumping into the middle of 
the discussion - I was missing some important context.  I apologize for not 
doing so.

The name `RangeExpression` does a good job of indicating why it’s ok for 
instances to sometimes behave as if they have an infinite upper bound and other 
times not depending on context.


> In fact, now that I say it, in that respect ranges are not all that different 
> any other type: the meaning of a Double or an Array or a Bool is also 
> interpreted by the methods to which it is passed, and can have completely 
> different results depending on that context.
> 
> chillaxing-ly y'rs,
> 
> Dave

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


Re: [swift-evolution] Strings in Swift 4

2017-02-02 Thread Matthew Johnson via swift-evolution

> On Feb 2, 2017, at 6:07 AM, Brent Royal-Gordon via swift-evolution 
>  wrote:
> 
>> On Feb 2, 2017, at 3:06 AM, Jaden Geller via swift-evolution 
>>  wrote:
>> 
>> It's not infinite (else subscript would trap)
> 
> I'm not necessarily a fan of the idea of allowing you to iterate over an 
> `IncompleteRange`, but I have to ask: What do you imagine an infinite 
> sequence of integers would do when it tried to go past the `max` value? As 
> far as I can tell, trapping is the *only* sensible possibility.

I don’t think anyone is disputing this right now.  The discussion is whether 
`IncompleteRange` and `InfiniteRange` are distinct concepts which should be 
modeled or whether they can be adequately represented by a single type.

In order to iterate a range you must know both bounds (even if one is 
infinite).  When we have a one-sided range with a bound that is countable and 
we allow it to conform to Sequence we are implicitly acknowledging it is an 
infinite range rather than an “incomplete” range.

If you have a range with an infinite upper bound (i.e. a one-sided range with a 
countable Bound) and apply the usual semantics of a collection subscript 
operation the result would necessarily trap because the upper bound is out of 
bounds.

We obviously don’t want this behavior.  Instead we want the upper bound to be 
clamped to the index preceding `endIndex` as a part of the subscript operation. 
For an infinite range this is equivalent to a very special case clamping 
behavior.  Special case clamping behavior like this is questionable on its own, 
and especially questionable if we ever add `InfiniteCollection` (which Ben 
mentioned in a footnote to his post) where subscripting with an infinite range 
would be a perfectly valid operation that produces an infinite slice.

If instead, we have a distinct type for `IncompleteRange` we don’t need a 
subscript overload with this kind of special case behavior.  There would not be 
a subscript that accepts `InfiniteRange` at all (for now - if we add 
`InfiniteCollection` later it probably *would* have one).  Instead, we would 
have a subscript that accepts `IncompleteRange` with the obvious semantics of 
filling in the missing bound with the last valid index (or `startIndex` if we 
also support incomplete ranges that only specify an upper bound).

> 
> (If you used a `BigInt` type, the sequence could of course then be infinite, 
> or as infinite as memory allows.)
> 
> -- 
> Brent Royal-Gordon
> Architechies
> 
> ___
> 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] Strings in Swift 4

2017-02-02 Thread Matthew Johnson via swift-evolution

> On Feb 2, 2017, at 5:06 AM, jaden.gel...@gmail.com wrote:
> 
> 
> On Feb 1, 2017, at 9:01 AM, Nevin Brackett-Rozinsky via swift-evolution 
> mailto:swift-evolution@swift.org>> wrote:
> 
>> I had read the discussion live as it happened. And just now I went back to 
>> see Jaden’s posts again: there are only a handful, and all are quite brief. 
>> To the extent that they “sketched a direction”, I would say no. We should 
>> instead base the proposal on ideas laid out by Dave Abrahams, Brent 
>> Royal-Gordon, Ben Cohen and several others.
> 
> Agree, I definitely didn't set the direction here; I just pointed out a 
> semantic inconsistency. I rather liked Brent's `RangeExpression` idea. It's 
> pretty elegant.
> 
>> 
>> Furthermore, we emphatically do *not* need to make the distinction you claim 
>> between “infinite” and “incomplete” ranges, which *is* needless 
>> hairsplitting.
> 
> Strongly disagree, unless you can describe the semantics of the type WITHOUT 
> giving it different semantics depending on how it is used.

This is the point that convinced me.  I’m going to take a closer look at 
Brent’s `RangeExpression` design which I must admit I only skimmed in the 
earlier discussion.

> 
>> 
>> We (meaning Swift Evolution) can define any semantics we like for any 
>> operator we like. The simple, elegant, intuitive behavior for one-sided 
>> ranges is exactly the “do what I mean” approach as described by many people 
>> including Dave Abrahams.
>> 
>> Want to subscript a collection using a one-sided range? Great! If the fixed 
>> bound is inside the collection then go as far as possible (ie. from start or 
>> to end), and if it is outside then trap for index out of bounds.
>> 
>> Want to zip together integers and sequence elements? Great! If the sequence 
>> eventually ends then stop when it does, and if not then trap when the 
>> integer overflows.
>> 
> 
> It seems really weird to describe the semantics of the type based on how it 
> is used rather than in isolation. What would the docs for this range even 
> say? It's not infinite (else subscript would trap), but it's not incomplete 
> (else we couldn't iterate over).

Agree.  We can implement this and it would work as users expect (at least most 
of the time), but it is also a little bit hand wavy and lacking in precision.  
This feels counter to the general direction of Swift.

> 
>> Want to iterate over a one-sided range? Well if the upper end is open then 
>> great! “for i in 20...” will loop until it hits a “break” or trap on 
>> overflow. We could probably even make “for i in (...20).reversed” work and 
>> count down, though we don’t have to.
> 
> This made me realize that `x...` and `...x` probably ought to be different 
> types (rather than an enum) if we're going to make the former iterable. (For 
> the record, I still think postfix `...` should be overloaded to return 2 
> different types so we don't have this semantic issue…)
> 
>> 
>> In any case, the point remains: if we do add one-sided ranges, we can define 
>> any behavior we want for them. And given the opinionated nature of Swift, it 
>> follows that we should choose to make them expressive, useful, and enjoyable.
>> 
> 
> I definitely agree that these ranges are much more lightweight and 
> approachable than the labeled subscript syntax, semantic issues aside.

+1

> 
>> Nevin
>> 
>> 
>> On Wed, Feb 1, 2017 at 10:58 AM, Matthew Johnson > > wrote:
>> 
>> > On Feb 1, 2017, at 9:52 AM, Nevin Brackett-Rozinsky 
>> > > > > wrote:
>> >
>> > Drafting a proposal sounds like a good idea, to establish all the relevant 
>> > information in one place. I don’t recall off the top of my head what 
>> > directions Jaden sketched out, but as long as the proposal hits the high 
>> > points of the uses and benefits, and summarizes the discussion and 
>> > alternatives, it should be fine.
>> >
>> > I might suggest using Chris’s terminology of “one-sided range”, because 
>> > that is both more precise and it renders moot all the “incomplete” vs 
>> > “infinite” hairsplitting.
>> 
>> I recommend reading through the discussion Xiaodi and I had yesterday, which 
>> Jaden chimed in on.  We really do need to make a distinction between 
>> incomplete and infinite ranges if we want to support all of the use cases 
>> with clean semantics.  This isn’t hair splitting.
>> 
>> >
>> > Nevin
>> 
>> 
>> ___
>> 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] Subclass Existentials

2017-02-01 Thread Matthew Johnson via swift-evolution


Sent from my iPad

> On Feb 1, 2017, at 5:11 PM, David Sweeris via swift-evolution 
>  wrote:
> 
> 
>> On Feb 1, 2017, at 3:01 PM, David Hart via swift-evolution 
>>  wrote:
>> 
>> 
>> On 1 Feb 2017, at 22:54, Douglas Gregor  wrote:
>> 
>>> 
 On Jan 29, 2017, at 8:44 PM, Slava Pestov via swift-evolution 
  wrote:
 
 This is a nice generalization of the existing protocol composition syntax. 
 Implementation might get a little tricky — this touches a lot of things, 
 such as inheritance clauses, constraints in generic signatures, and casts. 
 It would require thorough testing.
 
 There are also a few odd corner cases to sort out:
 
 typealias T = SomeClass & SomeProtocol
 
 class C : T { // should we allow this? probably yes
 }
 
 protocol P : T { // should we allow this? probably no
 }
>>> 
>>> IIRC, we already allow the latter where T is a typealias for SomeProtocol1 
>>> & SomeProtocol2. Why not allow it generally?
>> 
>> Well what would it mean? A protocol can't inherit or conform to a class.
> 
> That anything which conforms to that protocol must subclass SomeClass?

Yes, this is exactly what I would expect.  I was calling it a supertype 
requirement earlier in the thread.

> 
> - Dave Sweeris
> ___
> 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] Strings in Swift 4

2017-02-01 Thread Matthew Johnson via swift-evolution

> On Feb 1, 2017, at 9:52 AM, Nevin Brackett-Rozinsky 
>  wrote:
> 
> Drafting a proposal sounds like a good idea, to establish all the relevant 
> information in one place. I don’t recall off the top of my head what 
> directions Jaden sketched out, but as long as the proposal hits the high 
> points of the uses and benefits, and summarizes the discussion and 
> alternatives, it should be fine.
> 
> I might suggest using Chris’s terminology of “one-sided range”, because that 
> is both more precise and it renders moot all the “incomplete” vs “infinite” 
> hairsplitting.

I recommend reading through the discussion Xiaodi and I had yesterday, which 
Jaden chimed in on.  We really do need to make a distinction between incomplete 
and infinite ranges if we want to support all of the use cases with clean 
semantics.  This isn’t hair splitting.

> 
> Nevin

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


Re: [swift-evolution] Strings in Swift 4

2017-02-01 Thread Matthew Johnson via swift-evolution

> On Feb 1, 2017, at 9:15 AM, Nevin Brackett-Rozinsky 
>  wrote:
> 
> I am also +1.
> 
> 
> On Wed, Feb 1, 2017 at 9:29 AM, Matthew Johnson via swift-evolution 
> mailto:swift-evolution@swift.org>> wrote:
> 
> I’m still curious how postfix `…` would impact our options for variadic 
> generics and tuple unpacking in the future.
> 
> 
> Somebody who happens to have originally created Swift addressed this point 
> last week:
> 
> 
> On Wed, Jan 25, 2017 at 8:49 PM, Chris Lattner via swift-evolution 
> mailto:swift-evolution@swift.org>> wrote:
> 
> In any case, it seems like an obviously good tradeoff to make the syntax for 
> variadic generics more complicated if it makes one sided ranges more 
> beautiful.
> 
> -Chris

Thanks for reminding me of this.  I generally agree with Chris, but have no 
idea what the more complicated syntax for variadic generics might look like.  I 
guess what I’m looking for is some indication of what ideas (if any) there are 
about what this might look like.  A sketch of possible directions would be 
sufficient to answer the questions lurking in the back of my mind.

> 
> 
> I think we should start a new thread for the discussion of incomplete ranges 
> though.

Yes, I agree.  They have been discussed in two different threads now and it 
really feels like incomplete (and infinite) ranges deserve discussion in their 
own right.  Would it make sense to draft a proposal based on the direction 
Jaden sketched as a point of focus for the thread (especially to help newcomers 
get up to speed)?

> 
> Nevin
> 
> 
> On Wed, Feb 1, 2017 at 9:29 AM, Matthew Johnson via swift-evolution 
> mailto:swift-evolution@swift.org>> wrote:
> 
> > On Feb 1, 2017, at 6:58 AM, Brent Royal-Gordon via swift-evolution 
> > mailto:swift-evolution@swift.org>> wrote:
> >
> >> On Jan 31, 2017, at 2:04 PM, Xiaodi Wu via swift-evolution 
> >> mailto:swift-evolution@swift.org>> wrote:
> >>
> >> Therefore I'd conclude that `arr[upTo: i]` is the most consistent 
> >> spelling. It also yields the sensible result that `arr[from: i][upTo: j] 
> >> == arr[upTo: j][from: i] == arr[i.. >
> > There's a lot I dislike about `subscript(upTo/through/from:)`:
> >
> > 1. We have not previously been very satisfied with how understandable these 
> > labels are—for instance, we fiddled around with them a lot when we were 
> > looking at `stride(from:to/through:by:)` in Swift 3, and eventually settled 
> > on the originals because we couldn't find anything better. I don't think 
> > entrenching them further makes very much sense.
> >
> > 2. The fact that you *can* write `arr[from: i][upTo: j]`, and that this is 
> > equivalent to both `arr[upTo: j][from: i]` and `arr[i.. > weird. We aren't typically in the habit of providing redundant APIs like 
> > this.
> >
> > 3. Neither Stdlib nor the Apple frameworks currently contain *any* labeled 
> > subscripts, so this design would be unprecedented in the core language.
> >
> > 4. After a new programmer learns about subscripting with two-sided ranges, 
> > removing one of the bounds is a straightforward extension of what they 
> > already know. The argument label solution is more ad-hoc.
> >
> > 5. The argument label solution solves the immediate problem, but doesn't 
> > give us anything else.
> >
> > To understand what I mean by #5, consider the implementation. The plan is 
> > to introduce a `RangeExpression` protocol:
> >
> >   protocol RangeExpression {
> >   associatedtype Bound: Comparable
> >   func relative > == Bound -> Range
> >   }
> >
> > And then reduce the many manually-generated variants of `subscript(_: 
> > Range)` in `Collection` to just two:
> >
> >   protocol Collection {
> >   ...
> >   subscript(bounds: Range) -> SubSequence { get }
> >   ...
> >   }
> >
> >   extension Collection {
> >   ...
> >   subscript(bounds: Bounds) where 
> > Bounds.Bound == Index -> SubSequence {
> >   return self[bounds.relative(to: self)]
> >   }
> >   ...
> >   }
> >
> > This design would automatically, source-compatibly, handle several 
> > different existing types you can slice with:
> >
> > * ClosedRange
> > * CountableRange
> > * CountableClosedRange
> >
> > Plus the new types associated with incomplete ranges:
> >
> > * IncompleteRange
&g

Re: [swift-evolution] Strings in Swift 4

2017-02-01 Thread Matthew Johnson via swift-evolution

> On Feb 1, 2017, at 6:58 AM, Brent Royal-Gordon via swift-evolution 
>  wrote:
> 
>> On Jan 31, 2017, at 2:04 PM, Xiaodi Wu via swift-evolution 
>>  wrote:
>> 
>> Therefore I'd conclude that `arr[upTo: i]` is the most consistent spelling. 
>> It also yields the sensible result that `arr[from: i][upTo: j] == arr[upTo: 
>> j][from: i] == arr[i.. 
> There's a lot I dislike about `subscript(upTo/through/from:)`:
> 
> 1. We have not previously been very satisfied with how understandable these 
> labels are—for instance, we fiddled around with them a lot when we were 
> looking at `stride(from:to/through:by:)` in Swift 3, and eventually settled 
> on the originals because we couldn't find anything better. I don't think 
> entrenching them further makes very much sense.
> 
> 2. The fact that you *can* write `arr[from: i][upTo: j]`, and that this is 
> equivalent to both `arr[upTo: j][from: i]` and `arr[i.. weird. We aren't typically in the habit of providing redundant APIs like this.
> 
> 3. Neither Stdlib nor the Apple frameworks currently contain *any* labeled 
> subscripts, so this design would be unprecedented in the core language.
> 
> 4. After a new programmer learns about subscripting with two-sided ranges, 
> removing one of the bounds is a straightforward extension of what they 
> already know. The argument label solution is more ad-hoc.
> 
> 5. The argument label solution solves the immediate problem, but doesn't give 
> us anything else.
> 
> To understand what I mean by #5, consider the implementation. The plan is to 
> introduce a `RangeExpression` protocol:
> 
>   protocol RangeExpression {
>   associatedtype Bound: Comparable
>   func relative Bound -> Range
>   }
> 
> And then reduce the many manually-generated variants of `subscript(_: 
> Range)` in `Collection` to just two:
> 
>   protocol Collection {
>   ...
>   subscript(bounds: Range) -> SubSequence { get }
>   ...
>   }
>   
>   extension Collection {
>   ...
>   subscript(bounds: Bounds) where 
> Bounds.Bound == Index -> SubSequence {
>   return self[bounds.relative(to: self)]
>   }
>   ...
>   }
> 
> This design would automatically, source-compatibly, handle several different 
> existing types you can slice with:
> 
> * ClosedRange
> * CountableRange
> * CountableClosedRange
> 
> Plus the new types associated with incomplete ranges:
> 
> * IncompleteRange
> * IncompleteClosedRange
> 
> Plus anything else we, or users, might want to add. For instance, I have a 
> prototype built on `RangeExpression` which lets you write things like:
> 
>   myString[.startIndex + 1 ..< .endIndex - 1]
> 
> This strikes me as a pretty cool thing that some people might want. 
> 
> Similarly, IncompleteRange and IncompleteClosedRange can most likely be put 
> to other uses. They could easily fill a gap in `switch` statements, which 
> don't have a good way to express open-ended comparisons except with a `where` 
> clause. As some have mentioned, when applied to a `Strideable` type they 
> *could* be treated as infinite sequences, although it's not clear if we 
> really want to do that. And, you know, sometimes you really *do* have a case 
> where one or both bounds of a range may be missing in some cases; incomplete 
> ranges are a built-in, batteries-included way to model that.
> 
> To put it simply, slicing with incomplete ranges gives us several valuable 
> tools we can apply to other problems. Labeled subscripts, on the other hand, 
> are just another weird little thing that you have to memorize, and probably 
> won’t.

+1 in general.  But I’m still curious how postfix `…` would impact our options 
for variadic generics and tuple unpacking in the future.  

> 
> -- 
> Brent Royal-Gordon
> Architechies
> 
> ___
> 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] Strings in Swift 4

2017-01-31 Thread Matthew Johnson via swift-evolution


Sent from my iPad

> On Jan 31, 2017, at 7:28 PM, Xiaodi Wu  wrote:
> 
>> On Tue, Jan 31, 2017 at 7:08 PM, Matthew Johnson  
>> wrote:
>> 
>>> On Jan 31, 2017, at 6:54 PM, Xiaodi Wu  wrote:
>>> 
 On Tue, Jan 31, 2017 at 6:40 PM, Matthew Johnson  
 wrote:
 
> On Jan 31, 2017, at 6:15 PM, Xiaodi Wu  wrote:
> 
>> On Tue, Jan 31, 2017 at 6:09 PM, Matthew Johnson 
>>  wrote:
>> 
>>> On Jan 31, 2017, at 5:35 PM, Xiaodi Wu via swift-evolution 
>>>  wrote:
>>> 
 On Tue, Jan 31, 2017 at 5:28 PM, David Sweeris  
 wrote:
 
> On Jan 31, 2017, at 2:04 PM, Xiaodi Wu  wrote:
> 
>> On Tue, Jan 31, 2017 at 3:36 PM, David Sweeris via swift-evolution 
>>  wrote:
>> 
>>> On Jan 31, 2017, at 11:32, Jaden Geller via swift-evolution 
>>>  wrote:
>>> 
>>> I think that is perfectly reasonable, but then it seems weird to be 
>>> able to iterate over it (with no upper bound) independently of a 
>>> collection). It would surprise me if
>>> ```
>>> for x in arr[arr.startIndex…] { print(x) }
>>> ```
>>> yielded different results than
>>> ```
>>> for i in arr.startIndex… { print(arr[i]) } // CRASH
>>> ```
>>> which it does under this model.
>> 
>> (I think this how it works... semantically, anyway) Since the upper 
>> bound isn't specified, it's inferred from the context.
>> 
>> In the first case, the context is as an index into an array, so the 
>> upper bound is inferred to be the last valid index.
>> 
>> In the second case, there is no context, so it goes to Int.max. 
>> Then, after the "wrong" context has been established, you try to 
>> index an array with numbers from the too-large range.
>> 
>> Semantically speaking, they're pretty different operations. Why is 
>> it surprising that they have different results?
> 
> I must say, I was originally rather fond of `0...` as a spelling, but 
> IMO, Jaden and others have pointed out a real semantic issue.
> 
> A range is, to put it simply, the "stuff" between two end points. A 
> "range with no upper bound" _has to be_ one that continues forever. 
> The upper bound _must_ be infinity.
 
 Depends… Swift doesn’t allow partial initializations, and neither the 
 `.endIndex` nor the `.upperBound` properties of a `Range` are 
 optional. From a strictly syntactic PoV, a "Range without an 
 upperBound” can’t exist without getting into undefined behavior 
 territory.
 
 Plus, mathematically speaking, an infinite range would be written "[x, 
 ∞)", with an open upper bracket. If you write “[x, ∞]”, with a closed 
 upper bracket, that’s kind of a meaningless statement. I would argue 
 that if we’re going to represent that “infinite” range, the closest 
 Swift spelling would be “x..<“. That leaves the mathematically 
 undefined notation of “[x, ∞]”, spelled as "x…” in Swift, free to let 
 us have “x…” or “…x” (which by similar reasoning can’t mean "(∞, x]”) 
 return one of these:
 enum IncompleteRange {
 case upperValue(T)
 case lowerValue(T)
 }
 which we could then pass to the subscript function of a collection to 
 create the actual Range like this:
 extension Collection {
 subscript(_ ir: IncompleteRange) -> SubSequence {
 switch ir {
 case .lowerValue(let lower): return self[lower ..< 
 self.endIndex]
 case .upperValue(let upper): return self[self.startIndex ..< 
 upper]
 }
 }
 }
>>> 
>>> I understand that you can do this from a technical perspective. But I'm 
>>> arguing it's devoid of semantics.  That is, it's a spelling to dress up 
>>> a number.
>> 
>> It’s not any more devoid of semantics than a partially applied function.
> 
> Yes, but this here is not a partially applied type.
> 
> Nor does it square with your proposal that you should be able to use `for 
> i in 0...` to mean something different from `array[0...]`. We don't have 
> partially applied functions doubling as function calls with default 
> arguments.
 
 I’m not trying to say it’s *exactly* like a partially applied function.
>>> 
>>> I'm not saying you're arguing that point. I'm saying that there is a 
>>> semantic distinction between (1) a range with two bounds where you've only 
>>> specified the one, and (2) a range with one bound. There must be an answer 
>>> to the question: what is the nature of the upper bound of `0...`? Either it 
>>> exists but is not yet known, or it is known that it does not e

Re: [swift-evolution] Strings in Swift 4

2017-01-31 Thread Matthew Johnson via swift-evolution

> On Jan 31, 2017, at 6:54 PM, Xiaodi Wu  wrote:
> 
> On Tue, Jan 31, 2017 at 6:40 PM, Matthew Johnson  > wrote:
> 
>> On Jan 31, 2017, at 6:15 PM, Xiaodi Wu > > wrote:
>> 
>> On Tue, Jan 31, 2017 at 6:09 PM, Matthew Johnson > > wrote:
>> 
>>> On Jan 31, 2017, at 5:35 PM, Xiaodi Wu via swift-evolution 
>>> mailto:swift-evolution@swift.org>> wrote:
>>> 
>>> On Tue, Jan 31, 2017 at 5:28 PM, David Sweeris >> > wrote:
>>> 
 On Jan 31, 2017, at 2:04 PM, Xiaodi Wu >>> > wrote:
 
 On Tue, Jan 31, 2017 at 3:36 PM, David Sweeris via swift-evolution 
 mailto:swift-evolution@swift.org>> wrote:
 
 On Jan 31, 2017, at 11:32, Jaden Geller via swift-evolution 
 mailto:swift-evolution@swift.org>> wrote:
 
> I think that is perfectly reasonable, but then it seems weird to be able 
> to iterate over it (with no upper bound) independently of a collection). 
> It would surprise me if
> ```
> for x in arr[arr.startIndex…] { print(x) }
> ```
> yielded different results than
> ```
> for i in arr.startIndex… { print(arr[i]) } // CRASH
> ```
> which it does under this model.
 
 (I think this how it works... semantically, anyway) Since the upper bound 
 isn't specified, it's inferred from the context.
 
 In the first case, the context is as an index into an array, so the upper 
 bound is inferred to be the last valid index.
 
 In the second case, there is no context, so it goes to Int.max. Then, 
 after the "wrong" context has been established, you try to index an array 
 with numbers from the too-large range.
 
 Semantically speaking, they're pretty different operations. Why is it 
 surprising that they have different results?
 
 I must say, I was originally rather fond of `0...` as a spelling, but IMO, 
 Jaden and others have pointed out a real semantic issue.
 
 A range is, to put it simply, the "stuff" between two end points. A "range 
 with no upper bound" _has to be_ one that continues forever. The upper 
 bound _must_ be infinity.
>>> 
>>> Depends… Swift doesn’t allow partial initializations, and neither the 
>>> `.endIndex` nor the `.upperBound` properties of a `Range` are optional. 
>>> From a strictly syntactic PoV, a "Range without an upperBound” can’t exist 
>>> without getting into undefined behavior territory.
>>> 
>>> Plus, mathematically speaking, an infinite range would be written "[x, ∞)", 
>>> with an open upper bracket. If you write “[x, ∞]”, with a closed upper 
>>> bracket, that’s kind of a meaningless statement. I would argue that if 
>>> we’re going to represent that “infinite” range, the closest Swift spelling 
>>> would be “x..<“. That leaves the mathematically undefined notation of “[x, 
>>> ∞]”, spelled as "x…” in Swift, free to let us have “x…” or “…x” (which by 
>>> similar reasoning can’t mean "(∞, x]”) return one of these:
>>> enum IncompleteRange {
>>> case upperValue(T)
>>> case lowerValue(T)
>>> }
>>> which we could then pass to the subscript function of a collection to 
>>> create the actual Range like this:
>>> extension Collection {
>>> subscript(_ ir: IncompleteRange) -> SubSequence {
>>> switch ir {
>>> case .lowerValue(let lower): return self[lower ..< self.endIndex]
>>> case .upperValue(let upper): return self[self.startIndex ..< upper]
>>> }
>>> }
>>> }
>>> 
>>> I understand that you can do this from a technical perspective. But I'm 
>>> arguing it's devoid of semantics.  That is, it's a spelling to dress up a 
>>> number.
>> 
>> It’s not any more devoid of semantics than a partially applied function.
>> 
>> Yes, but this here is not a partially applied type.
>> 
>> Nor does it square with your proposal that you should be able to use `for i 
>> in 0...` to mean something different from `array[0...]`. We don't have 
>> partially applied functions doubling as function calls with default 
>> arguments.
> 
> I’m not trying to say it’s *exactly* like a partially applied function.
> 
> I'm not saying you're arguing that point. I'm saying that there is a semantic 
> distinction between (1) a range with two bounds where you've only specified 
> the one, and (2) a range with one bound. There must be an answer to the 
> question: what is the nature of the upper bound of `0...`? Either it exists 
> but is not yet known, or it is known that it does not exist (or, it is not 
> yet known whether or not it exists). But these are not the same thing!
> 
>> It is a number or index with added semantics that it provides a lower (or 
>> upper) bound on the possible value specified by its type.
>> 
>>> 
>>> What is such an `IncompleteRange` other than a value of type T? It's not 
>>> an upper bound or lower bound of anything until it's used to index a 
>>> collection

Re: [swift-evolution] Strings in Swift 4

2017-01-31 Thread Matthew Johnson via swift-evolution

> On Jan 31, 2017, at 6:15 PM, Jaden Geller  wrote:
> 
> 
>> On Jan 31, 2017, at 4:09 PM, Matthew Johnson via swift-evolution 
>> mailto:swift-evolution@swift.org>> wrote:
>> 
>> 
>>> On Jan 31, 2017, at 5:35 PM, Xiaodi Wu via swift-evolution 
>>> mailto:swift-evolution@swift.org>> wrote:
>>> 
>>> On Tue, Jan 31, 2017 at 5:28 PM, David Sweeris >> <mailto:daveswee...@mac.com>> wrote:
>>> 
>>>> On Jan 31, 2017, at 2:04 PM, Xiaodi Wu >>> <mailto:xiaodi...@gmail.com>> wrote:
>>>> 
>>>> On Tue, Jan 31, 2017 at 3:36 PM, David Sweeris via swift-evolution 
>>>> mailto:swift-evolution@swift.org>> wrote:
>>>> 
>>>> On Jan 31, 2017, at 11:32, Jaden Geller via swift-evolution 
>>>> mailto:swift-evolution@swift.org>> wrote:
>>>> 
>>>>> I think that is perfectly reasonable, but then it seems weird to be able 
>>>>> to iterate over it (with no upper bound) independently of a collection). 
>>>>> It would surprise me if
>>>>> ```
>>>>> for x in arr[arr.startIndex…] { print(x) }
>>>>> ```
>>>>> yielded different results than
>>>>> ```
>>>>> for i in arr.startIndex… { print(arr[i]) } // CRASH
>>>>> ```
>>>>> which it does under this model.
>>>> 
>>>> (I think this how it works... semantically, anyway) Since the upper bound 
>>>> isn't specified, it's inferred from the context.
>>>> 
>>>> In the first case, the context is as an index into an array, so the upper 
>>>> bound is inferred to be the last valid index.
>>>> 
>>>> In the second case, there is no context, so it goes to Int.max. Then, 
>>>> after the "wrong" context has been established, you try to index an array 
>>>> with numbers from the too-large range.
>>>> 
>>>> Semantically speaking, they're pretty different operations. Why is it 
>>>> surprising that they have different results?
>>>> 
>>>> I must say, I was originally rather fond of `0...` as a spelling, but IMO, 
>>>> Jaden and others have pointed out a real semantic issue.
>>>> 
>>>> A range is, to put it simply, the "stuff" between two end points. A "range 
>>>> with no upper bound" _has to be_ one that continues forever. The upper 
>>>> bound _must_ be infinity.
>>> 
>>> Depends… Swift doesn’t allow partial initializations, and neither the 
>>> `.endIndex` nor the `.upperBound` properties of a `Range` are optional. 
>>> From a strictly syntactic PoV, a "Range without an upperBound” can’t exist 
>>> without getting into undefined behavior territory.
>>> 
>>> Plus, mathematically speaking, an infinite range would be written "[x, ∞)", 
>>> with an open upper bracket. If you write “[x, ∞]”, with a closed upper 
>>> bracket, that’s kind of a meaningless statement. I would argue that if 
>>> we’re going to represent that “infinite” range, the closest Swift spelling 
>>> would be “x..<“. That leaves the mathematically undefined notation of “[x, 
>>> ∞]”, spelled as "x…” in Swift, free to let us have “x…” or “…x” (which by 
>>> similar reasoning can’t mean "(∞, x]”) return one of these:
>>> enum IncompleteRange {
>>> case upperValue(T)
>>> case lowerValue(T)
>>> }
>>> which we could then pass to the subscript function of a collection to 
>>> create the actual Range like this:
>>> extension Collection {
>>> subscript(_ ir: IncompleteRange) -> SubSequence {
>>> switch ir {
>>> case .lowerValue(let lower): return self[lower ..< self.endIndex]
>>> case .upperValue(let upper): return self[self.startIndex ..< upper]
>>> }
>>> }
>>> }
>>> 
>>> I understand that you can do this from a technical perspective. But I'm 
>>> arguing it's devoid of semantics.  That is, it's a spelling to dress up a 
>>> number.
>> 
>> It’s not any more devoid of semantics than a partially applied function.  It 
>> is a number or index with added semantics that it provides a lower (or 
>> upper) bound on the possible value specified by its type.
> 
> If we treat it as such, we shouldn’t allow users to iterate over it directly:
> ```
> for x in 0… { // <- doesn’t mak

Re: [swift-evolution] Strings in Swift 4

2017-01-31 Thread Matthew Johnson via swift-evolution

> On Jan 31, 2017, at 6:15 PM, Xiaodi Wu  wrote:
> 
> On Tue, Jan 31, 2017 at 6:09 PM, Matthew Johnson  > wrote:
> 
>> On Jan 31, 2017, at 5:35 PM, Xiaodi Wu via swift-evolution 
>> mailto:swift-evolution@swift.org>> wrote:
>> 
>> On Tue, Jan 31, 2017 at 5:28 PM, David Sweeris > > wrote:
>> 
>>> On Jan 31, 2017, at 2:04 PM, Xiaodi Wu >> > wrote:
>>> 
>>> On Tue, Jan 31, 2017 at 3:36 PM, David Sweeris via swift-evolution 
>>> mailto:swift-evolution@swift.org>> wrote:
>>> 
>>> On Jan 31, 2017, at 11:32, Jaden Geller via swift-evolution 
>>> mailto:swift-evolution@swift.org>> wrote:
>>> 
 I think that is perfectly reasonable, but then it seems weird to be able 
 to iterate over it (with no upper bound) independently of a collection). 
 It would surprise me if
 ```
 for x in arr[arr.startIndex…] { print(x) }
 ```
 yielded different results than
 ```
 for i in arr.startIndex… { print(arr[i]) } // CRASH
 ```
 which it does under this model.
>>> 
>>> (I think this how it works... semantically, anyway) Since the upper bound 
>>> isn't specified, it's inferred from the context.
>>> 
>>> In the first case, the context is as an index into an array, so the upper 
>>> bound is inferred to be the last valid index.
>>> 
>>> In the second case, there is no context, so it goes to Int.max. Then, after 
>>> the "wrong" context has been established, you try to index an array with 
>>> numbers from the too-large range.
>>> 
>>> Semantically speaking, they're pretty different operations. Why is it 
>>> surprising that they have different results?
>>> 
>>> I must say, I was originally rather fond of `0...` as a spelling, but IMO, 
>>> Jaden and others have pointed out a real semantic issue.
>>> 
>>> A range is, to put it simply, the "stuff" between two end points. A "range 
>>> with no upper bound" _has to be_ one that continues forever. The upper 
>>> bound _must_ be infinity.
>> 
>> Depends… Swift doesn’t allow partial initializations, and neither the 
>> `.endIndex` nor the `.upperBound` properties of a `Range` are optional. From 
>> a strictly syntactic PoV, a "Range without an upperBound” can’t exist 
>> without getting into undefined behavior territory.
>> 
>> Plus, mathematically speaking, an infinite range would be written "[x, ∞)", 
>> with an open upper bracket. If you write “[x, ∞]”, with a closed upper 
>> bracket, that’s kind of a meaningless statement. I would argue that if we’re 
>> going to represent that “infinite” range, the closest Swift spelling would 
>> be “x..<“. That leaves the mathematically undefined notation of “[x, ∞]”, 
>> spelled as "x…” in Swift, free to let us have “x…” or “…x” (which by similar 
>> reasoning can’t mean "(∞, x]”) return one of these:
>> enum IncompleteRange {
>> case upperValue(T)
>> case lowerValue(T)
>> }
>> which we could then pass to the subscript function of a collection to create 
>> the actual Range like this:
>> extension Collection {
>> subscript(_ ir: IncompleteRange) -> SubSequence {
>> switch ir {
>> case .lowerValue(let lower): return self[lower ..< self.endIndex]
>> case .upperValue(let upper): return self[self.startIndex ..< upper]
>> }
>> }
>> }
>> 
>> I understand that you can do this from a technical perspective. But I'm 
>> arguing it's devoid of semantics.  That is, it's a spelling to dress up a 
>> number.
> 
> It’s not any more devoid of semantics than a partially applied function.
> 
> Yes, but this here is not a partially applied type.
> 
> Nor does it square with your proposal that you should be able to use `for i 
> in 0...` to mean something different from `array[0...]`. We don't have 
> partially applied functions doubling as function calls with default arguments.

I’m not trying to say it’s *exactly* like a partially applied function.

>  
> It is a number or index with added semantics that it provides a lower (or 
> upper) bound on the possible value specified by its type.
> 
>> 
>> What is such an `IncompleteRange` other than a value of type T? It's not 
>> an upper bound or lower bound of anything until it's used to index a 
>> collection. Why have a new type (IncompleteRange), a new set of operators 
>> (prefix and postfix range operators), and these muddied semantics for 
>> something that can be written `subscript(upTo upperBound: Index) -> 
>> SubSequence { ... }`? _That_ has unmistakable semantics and requires no new 
>> syntax.
> 
> Arguing that it adds too much complexity relative to the value it provides is 
> reasonable.  The value in this use case is mostly syntactic sugar so it’s 
> relatively easy to make the case that it doesn’t cary its weight here.
> 
> The value in Ben’s use case is a more composable alternative to `enumerated`. 
>  I find this to be a reasonably compelling example of the kind of thing a 
> partial range might enable.
> 
> Ben's use case is

Re: [swift-evolution] Strings in Swift 4

2017-01-31 Thread Matthew Johnson via swift-evolution

> On Jan 31, 2017, at 5:35 PM, Xiaodi Wu via swift-evolution 
>  wrote:
> 
> On Tue, Jan 31, 2017 at 5:28 PM, David Sweeris  > wrote:
> 
>> On Jan 31, 2017, at 2:04 PM, Xiaodi Wu > > wrote:
>> 
>> On Tue, Jan 31, 2017 at 3:36 PM, David Sweeris via swift-evolution 
>> mailto:swift-evolution@swift.org>> wrote:
>> 
>> On Jan 31, 2017, at 11:32, Jaden Geller via swift-evolution 
>> mailto:swift-evolution@swift.org>> wrote:
>> 
>>> I think that is perfectly reasonable, but then it seems weird to be able to 
>>> iterate over it (with no upper bound) independently of a collection). It 
>>> would surprise me if
>>> ```
>>> for x in arr[arr.startIndex…] { print(x) }
>>> ```
>>> yielded different results than
>>> ```
>>> for i in arr.startIndex… { print(arr[i]) } // CRASH
>>> ```
>>> which it does under this model.
>> 
>> (I think this how it works... semantically, anyway) Since the upper bound 
>> isn't specified, it's inferred from the context.
>> 
>> In the first case, the context is as an index into an array, so the upper 
>> bound is inferred to be the last valid index.
>> 
>> In the second case, there is no context, so it goes to Int.max. Then, after 
>> the "wrong" context has been established, you try to index an array with 
>> numbers from the too-large range.
>> 
>> Semantically speaking, they're pretty different operations. Why is it 
>> surprising that they have different results?
>> 
>> I must say, I was originally rather fond of `0...` as a spelling, but IMO, 
>> Jaden and others have pointed out a real semantic issue.
>> 
>> A range is, to put it simply, the "stuff" between two end points. A "range 
>> with no upper bound" _has to be_ one that continues forever. The upper bound 
>> _must_ be infinity.
> 
> Depends… Swift doesn’t allow partial initializations, and neither the 
> `.endIndex` nor the `.upperBound` properties of a `Range` are optional. From 
> a strictly syntactic PoV, a "Range without an upperBound” can’t exist without 
> getting into undefined behavior territory.
> 
> Plus, mathematically speaking, an infinite range would be written "[x, ∞)", 
> with an open upper bracket. If you write “[x, ∞]”, with a closed upper 
> bracket, that’s kind of a meaningless statement. I would argue that if we’re 
> going to represent that “infinite” range, the closest Swift spelling would be 
> “x..<“. That leaves the mathematically undefined notation of “[x, ∞]”, 
> spelled as "x…” in Swift, free to let us have “x…” or “…x” (which by similar 
> reasoning can’t mean "(∞, x]”) return one of these:
> enum IncompleteRange {
> case upperValue(T)
> case lowerValue(T)
> }
> which we could then pass to the subscript function of a collection to create 
> the actual Range like this:
> extension Collection {
> subscript(_ ir: IncompleteRange) -> SubSequence {
> switch ir {
> case .lowerValue(let lower): return self[lower ..< self.endIndex]
> case .upperValue(let upper): return self[self.startIndex ..< upper]
> }
> }
> }
> 
> I understand that you can do this from a technical perspective. But I'm 
> arguing it's devoid of semantics.  That is, it's a spelling to dress up a 
> number.

It’s not any more devoid of semantics than a partially applied function.  It is 
a number or index with added semantics that it provides a lower (or upper) 
bound on the possible value specified by its type.

> 
> What is such an `IncompleteRange` other than a value of type T? It's not 
> an upper bound or lower bound of anything until it's used to index a 
> collection. Why have a new type (IncompleteRange), a new set of operators 
> (prefix and postfix range operators), and these muddied semantics for 
> something that can be written `subscript(upTo upperBound: Index) -> 
> SubSequence { ... }`? _That_ has unmistakable semantics and requires no new 
> syntax.

Arguing that it adds too much complexity relative to the value it provides is 
reasonable.  The value in this use case is mostly syntactic sugar so it’s 
relatively easy to make the case that it doesn’t cary its weight here.

The value in Ben’s use case is a more composable alternative to `enumerated`.  
I find this to be a reasonably compelling example of the kind of thing a 
partial range might enable.

I also tend to find concise notation important for clarity as long as it isn’t 
obscure or idiosyncratic.  With that in mind, I think I lean in favor of `…` so 
long as we’re confident we won’t regret it if / when we take up variadic 
generics and / or tuple unpacking.

> 
> 
> ___
> 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] Strings in Swift 4

2017-01-31 Thread Matthew Johnson via swift-evolution

> On Jan 31, 2017, at 5:20 PM, Xiaodi Wu  wrote:
> 
> On Tue, Jan 31, 2017 at 5:04 PM, Matthew Johnson  > wrote:
> 
> I think it’s fair to say that we get to decide on the semantics of postfix 
> `…`.  “a range with no upper bound” is very reasonable, but wouldn’t another 
> reasonable semantics be “all the rest”, meaning that there *is* an upper 
> bound (the greatest possible value).  
> 
> "All the rest" is by itself insufficient so far as semantics: all the rest 
> _of what_? Supposing that our supplied lower bound is an integer, it must be 
> all the rest of the integers. It cannot be all the rest of whatever, where 
> whatever might be a collection that you try to subset with `0...`. (Recall 
> that collections move indices, but indices know nothing about the 
> collections.) It would be exceeding fuzzy for postfix `...` to mean "all the 
> rest of whatever I want it to mean"--that, almost tautologically, has no 
> semantics at all.
> 
> Under the latter semantics, a `for i in 0…` loop would terminate after 
> reaching Int.max.  This is probably not what the user intended and would 
> still crash when used in David’s example, but it’s worth considering.
> 
> OK, I'm borderline fine with `0... == 0...Int.max`. It at least provides some 
> semantics (i.e., we're saying `...` refers to all the rest of the values 
> representable by the type used for the lower bound) [**]. But Jaden's point 
> still stands, since it would only be consistent if `for i in arr[0...]` then 
> traps after `arr.count` just like `for i in arr[0...Int.max]` would do. 
> Otherwise, we really are fudging the semantics.

If we really want to be honest about the information a value produced using 
postfix `…` carries, it is a partial range with only the lower bound specified. 
 This allows us to assign meaning to that partial range using additional 
context: 

* When it is possible to increment Bound directly could be interpreted as an 
(near?) infinite sequence that either terminates or traps when it reaches an 
unrepresentable value.
* When Bound is an index and the partial range is used as a subscript argument 
it can be interpreted to mean “to the end of the collection”.

This still leaves us with an out of bounds crash in David’s example that 
iterates over a partial range.  This is an artifact of `Array` using Int as 
it’s `Index` rather than an opaque type that does not allow users to increment 
it directly rather than using a collection.  

Is the problem in David’s example really that different than the ability to 
directly index an array with any `Int` we want?  It’s not the kind of thing 
that developers would do frequently.  The first time they try it they will get 
a crash and will learn not to do it again.

I’m not necessarily arguing one way or the other.  I’m simply pointing out that 
“partial range” is a perfectly reasonable semantics to consider.

> 
> [**] It is not perfectly consistent semantically because, as was discussed in 
> threads about our numeric protocols, our integer types are supposed to model 
> all integers, not just the ones that happen to be representable. Our model is 
> imperfect because not all integers fit into finite memory, but that's a 
> modeling artifact and not intentional semantics. IIUC, it would be otherwise 
> difficult to give a good accounting of, say, the semantics of addition if 
> arithmetic overflow were an intentional part of the semantics and not an 
> artifact.

I haven’t followed all of the details of the numeric protocol discussions.  
With this in mind, I agree with your proposed semantics of trapping after 
`Int.max` as it sounds more consistent with this intent.

> 
> I’m not sure if you read Ben’s post regarding `enumerated` or not, but he 
> gave the example of `zip(0…, sequence)` as a more general replacement for 
> `enumerated`.  IMO, he makes a pretty strong case for this.
> 
>> 
>> 
>> - Dave Sweeris 
>> 
>> ___
>> 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] Strings in Swift 4

2017-01-31 Thread Matthew Johnson via swift-evolution

> On Jan 31, 2017, at 4:04 PM, Xiaodi Wu via swift-evolution 
>  wrote:
> 
> On Tue, Jan 31, 2017 at 3:36 PM, David Sweeris via swift-evolution 
> mailto:swift-evolution@swift.org>> wrote:
> 
> On Jan 31, 2017, at 11:32, Jaden Geller via swift-evolution 
> mailto:swift-evolution@swift.org>> wrote:
> 
>> I think that is perfectly reasonable, but then it seems weird to be able to 
>> iterate over it (with no upper bound) independently of a collection). It 
>> would surprise me if
>> ```
>> for x in arr[arr.startIndex…] { print(x) }
>> ```
>> yielded different results than
>> ```
>> for i in arr.startIndex… { print(arr[i]) } // CRASH
>> ```
>> which it does under this model.
> 
> (I think this how it works... semantically, anyway) Since the upper bound 
> isn't specified, it's inferred from the context.
> 
> In the first case, the context is as an index into an array, so the upper 
> bound is inferred to be the last valid index.
> 
> In the second case, there is no context, so it goes to Int.max. Then, after 
> the "wrong" context has been established, you try to index an array with 
> numbers from the too-large range.
> 
> Semantically speaking, they're pretty different operations. Why is it 
> surprising that they have different results?
> 
> I must say, I was originally rather fond of `0...` as a spelling, but IMO, 
> Jaden and others have pointed out a real semantic issue.
> 
> A range is, to put it simply, the "stuff" between two end points. A "range 
> with no upper bound" _has to be_ one that continues forever.
> The upper bound _must_ be infinity. What Dave Abrahams has described does not 
> have the semantics of a range with no upper bound. He's describing a 
> standalone lower bound with no "stuff." It stands to reason that such a type 
> should not be a sequence at all. But we already use particular types for 
> upper and lower bounds that aren't sequences, and they're plain numeric 
> types. Therefore I'd conclude that `arr[upTo: i]` is the most consistent 
> spelling. It also yields the sensible result that `arr[from: i][upTo: j] == 
> arr[upTo: j][from: i] == arr[i.. 
> If `0...` is to have the semantics of a range with no upper bound, I would 
> expect `for i in 0...` to be an infinite loop, equivalent to `for i in 
> stride(from: 0, through: Int.max, by: 1)` for Int.max+1 iterations and then 
> trapping. Which is, well, silly. I'm coming around to thinking that `0...` is 
> a sexy notation for something we don't need and a poor notation for something 
> that's more cleanly expressed by plain numbers.


I think it’s fair to say that we get to decide on the semantics of postfix `…`. 
 “a range with no upper bound” is very reasonable, but wouldn’t another 
reasonable semantics be “all the rest”, meaning that there *is* an upper bound 
(the greatest possible value).  

Under the latter semantics, a `for i in 0…` loop would terminate after reaching 
Int.max.  This is probably not what the user intended and would still crash 
when used in David’s example, but it’s worth considering.

I’m not sure if you read Ben’s post regarding `enumerated` or not, but he gave 
the example of `zip(0…, sequence)` as a more general replacement for 
`enumerated`.  IMO, he makes a pretty strong case for this.

> 
> 
> - Dave Sweeris 
> 
> ___
> 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] Removing enumerated?

2017-01-31 Thread Matthew Johnson via swift-evolution

> On Jan 31, 2017, at 2:46 PM, Ben Cohen  wrote:
> 
>> 
>> On Jan 31, 2017, at 12:18 PM, Matthew Johnson > > wrote:
>> 
>>> 
>>> On Jan 31, 2017, at 1:16 PM, Ben Cohen via swift-evolution 
>>> mailto:swift-evolution@swift.org>> wrote:
>>> 
>>> I think whether enumerated() is justified as a method on Sequence is one 
>>> example of a wider question which definitely needs some discussion, which 
>>> is: where should the standard library draw the line in providing 
>>> convenience functions that can easily be composed from other functions in 
>>> the std lib? Here’s another example: 
>>> 
>>> SE-100 
>>> 
>>>  is a proposal to add an init to Dictionary from a sequence of key/value 
>>> pairs. It’s a commonly requested feature, and IMO much needed and should be 
>>> added as soon as we move to the appropriate phase in Swift’s evolution. 
>>> 
>>> Another commonly requested Dictionary feature is similar: add a 
>>> Dictionary.init that takes a sequence, and a closure that maps that 
>>> sequence to keys. This is useful, for example, when you have a sequence of 
>>> objects that you frequently need to index into via one property on those 
>>> objects, so you want to build a fast lookup cache using that property.
>>> 
>>> Now, if we implement SE-100, that second request can be easily composed. It 
>>> would be something like Dictionary(sequence.lazy.map { (key: 
>>> $0.someProperty, value: $0) } )
>>> 
>>> Some people look at that line of code and think sure, that’s what I’d do 
>>> and it’s easy enough that the second helper shouldn’t be added as it’s 
>>> superfluous. Others look at it and say that it is unreadable clever-code FP 
>>> nonsense, and we should just add the helper method because most programmers 
>>> wouldn’t be able to read or write that easily.
>>> 
>>> As we expand (and maybe contract :) the standard library, this kind of 
>>> question comes up a lot, so it is worth setting out some criteria for 
>>> judging these
>>> “helper” methods. Here’s my take on such a list (warning: objectivity and 
>>> subjectivity blended together in the below).
>> 
>> This is a great analysis and list of criteria.  Thanks for putting this 
>> together Ben!
>> 
>>> 
>>> 1. Is it truly a frequent operation?
>>> 
>>> The operation needs to carry its weight. Even once we have ABI stability, 
>>> so the size of the std lib becomes less of a concern as it could ship as 
>>> part of the OS, we still need to keep helper method growth under control. 
>>> APIs bristling with methods like an over-decorated Xmas tree are bad for 
>>> usability. As mentioned in the String manifesto, String+Foundation 
>>> currently has over 200 methods/properties. Helpers are no good if you can’t 
>>> find them to use them.
>>> 
>>> Someone mentioned that they actually don’t find themselves using 
>>> enumerated() all that often. I suspect enumerated in its current form isn’t 
>>> all that useful. In a quick (and non-scientific) review of search results 
>>> for its use on GitHub, nearly all the examples I see of it are either 1) 
>>> misuse – see more below, or 2) use of it to perform the equivalent of 
>>> in-place map where the index is used to subscript into the array and 
>>> replace it with a transformed element.
>>> 
>>> I think the std lib needs an in-place map, and if enumerated() is removed, 
>>> this one most-common use case should be added at the same time.
>> 
>> I just did a quick search in a couple of projects and found a handful of 
>> good examples of valid uses of `enumerated`.  I have simplified the examples 
>> from real world code, but I think they demonstrate the kinds of things this 
>> is good for.
>> 
>> // only show the first 5 views
>> for (i, view) in views.enumerated() {
>> view.hidden = i >= 5
>> }
>> 
> 
> Interesting that several of these rely on reference types as elements. This 
> does make the loops a lot simpler. In-place amendment of an array would be 
> messier, and the combination with zip definitely pushes back against my 
> notion that an in-place map would be a useful alternative (since you couldn’t 
> mutate the mutable half of the zipped collection in-place without us jumping 
> through some hoops).
> 
> 
>> // apply alternating view background colors
>> for (i, view) in views.enumerated() {
>> view.backgroundColor = i % 2 ? bgColor1 : bgColor2
>> }
>> 
> 
> This is an interesting one because it highlights something else I think is 
> missing from the std lib: Sequence.cycle, which would make an infinite 
> sequence by repeating a sequence, enabling what I think is probably a 
> readability win in some cases:
> 
> let colors = [bgColor1, bgColor2].cycle
> for (color, view) in zip(colors, views) {
>   view.backgroundColor = color
> }
> 
> Also i%2 used as a boolean – what language is this? :)

Oops!  :)

> 
>> // linear layout
>> for (i, view

Re: [swift-evolution] Removing enumerated?

2017-01-31 Thread Matthew Johnson via swift-evolution

> On Jan 31, 2017, at 1:16 PM, Ben Cohen via swift-evolution 
>  wrote:
> 
> I think whether enumerated() is justified as a method on Sequence is one 
> example of a wider question which definitely needs some discussion, which is: 
> where should the standard library draw the line in providing convenience 
> functions that can easily be composed from other functions in the std lib? 
> Here’s another example: 
> 
> SE-100 
> 
>  is a proposal to add an init to Dictionary from a sequence of key/value 
> pairs. It’s a commonly requested feature, and IMO much needed and should be 
> added as soon as we move to the appropriate phase in Swift’s evolution. 
> 
> Another commonly requested Dictionary feature is similar: add a 
> Dictionary.init that takes a sequence, and a closure that maps that sequence 
> to keys. This is useful, for example, when you have a sequence of objects 
> that you frequently need to index into via one property on those objects, so 
> you want to build a fast lookup cache using that property.
> 
> Now, if we implement SE-100, that second request can be easily composed. It 
> would be something like Dictionary(sequence.lazy.map { (key: $0.someProperty, 
> value: $0) } )
> 
> Some people look at that line of code and think sure, that’s what I’d do and 
> it’s easy enough that the second helper shouldn’t be added as it’s 
> superfluous. Others look at it and say that it is unreadable clever-code FP 
> nonsense, and we should just add the helper method because most programmers 
> wouldn’t be able to read or write that easily.
> 
> As we expand (and maybe contract :) the standard library, this kind of 
> question comes up a lot, so it is worth setting out some criteria for judging 
> these
> “helper” methods. Here’s my take on such a list (warning: objectivity and 
> subjectivity blended together in the below).

This is a great analysis and list of criteria.  Thanks for putting this 
together Ben!

> 
> 1. Is it truly a frequent operation?
> 
> The operation needs to carry its weight. Even once we have ABI stability, so 
> the size of the std lib becomes less of a concern as it could ship as part of 
> the OS, we still need to keep helper method growth under control. APIs 
> bristling with methods like an over-decorated Xmas tree are bad for 
> usability. As mentioned in the String manifesto, String+Foundation currently 
> has over 200 methods/properties. Helpers are no good if you can’t find them 
> to use them.
> 
> Someone mentioned that they actually don’t find themselves using enumerated() 
> all that often. I suspect enumerated in its current form isn’t all that 
> useful. In a quick (and non-scientific) review of search results for its use 
> on GitHub, nearly all the examples I see of it are either 1) misuse – see 
> more below, or 2) use of it to perform the equivalent of in-place map where 
> the index is used to subscript into the array and replace it with a 
> transformed element.
> 
> I think the std lib needs an in-place map, and if enumerated() is removed, 
> this one most-common use case should be added at the same time.

I just did a quick search in a couple of projects and found a handful of good 
examples of valid uses of `enumerated`.  I have simplified the examples from 
real world code, but I think they demonstrate the kinds of things this is good 
for.

// only show the first 5 views
for (i, view) in views.enumerated() {
view.hidden = i >= 5
}

// apply alternating view background colors
for (i, view) in views.enumerated() {
view.backgroundColor = i % 2 ? bgColor1 : bgColor2
}

// linear layout
for (i, view) in views.enumerated() {
   let x = width * CGFloat(i)
   view.frame = CGRect(x: x, y: 0, width: width, height: height)
}

// deriving locations for an equally spaced gradient
let locations = colors.enumerated.map { CGFloat($0.0) / CGFloat(colors.count - 
1) }

There are other ways to accomplish similar things (use `prefix` and `dropFirst` 
comes to mind), but many reasonable people would argue that using `enumerated` 
is a very straightforward way to do a lot of things.

> 
> 2. Is the helper more readable? Is the composed equivalent obvious at a 
> glance?
> 
> When an operation is very common, the big win with a helper method is it 
> creates a readable vocabulary. If enumerated() is very common, and everyone 
> sees it everywhere, it makes that code easier to read at a glance.
> 
> That said, I think that the alternative – zip(0…, sequence) – is just as 
> readable once you are familiar with zip and ranges, two concepts that, IMO at 
> least, it is important that every Swift programmer learn about early on. I 
> would even go so far as to say that enumerated is harmful if it discourages 
> new users from discovering zip.

This is a very good point.  Requiring programmers to zip with a range could 
help them to learn to think a little bi

Re: [swift-evolution] Removing enumerated?

2017-01-31 Thread Matthew Johnson via swift-evolution

> On Jan 31, 2017, at 10:46 AM, Chris Eidhof  wrote:
> 
> I agree that it's very useful. I use it regularly. The documentation isn't 
> that unclear, imo. To me, the underlying problem isn't enumerated. I think 
> the underlying cause is that collections aren't indexed with zero based 
> indices.if you don't understand this (which is the case for many experienced 
> programmers new to Swift) it's hard to understand, and (too) easy to make a 
> mistake.

This indicates that the underlying problem is *not* enumerated at all.  The 
underlying problem is that Swift is still a relatively new language and it does 
some things differently than other languages (for very good reasons).

You’re making a great case for the need to continue spreading knowledge about 
Swift’s collection model through the community.

I don’t think it’s problematic for an experienced programmer who is new to the 
language to bump up against this when the reach for `enumerated`.  They’re 
going to need to learn the collection model sooner or later.  

> 
> On Tue, 31 Jan 2017 at 17:41, Matthew Johnson via swift-evolution 
> mailto:swift-evolution@swift.org>> wrote:
>> On Jan 31, 2017, at 10:36 AM, Xiaodi Wu via swift-evolution 
>> mailto:swift-evolution@swift.org>> wrote:
>> 
>> I totally sympathize with users being confused. It's an interesting idea to 
>> move it to Array only.
>> 
>> The thing is, it does make sense (and wouldn't be confusing) to enumerate a 
>> dictionary or set. Moreover, the behavior is _exactly_ what it says on the 
>> tin: when you enumerate something in real life, there is no sense in which 
>> the number is related to some sort of index. Can we fix this by 
>> documentation? Like, a big blaring "don't use this when you want the index”?
> 
> +1.  A similar method on collection that provides indices might be useful but 
> that doesn’t mean we should remove `enumerated`.  User confusion should be 
> addressed by documentation.
> 
>> On Tue, Jan 31, 2017 at 09:35 Ole Begemann via swift-evolution 
>> mailto:swift-evolution@swift.org>> wrote:
>> On 31/01/2017 16:19, Ole Begemann via swift-evolution wrote:
>> > Here are three previous discussion about this topic:
>> >
>> > 1) December 2015: [Idea] Add an (Index,Element) sequence to
>> > CollectionType
>> > https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151221/004561.html
>> >  
>> > <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151221/004561.html>
>> > and
>> > https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151228/004626.html
>> >  
>> > <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151228/004626.html>
>> >
>> >
>> > 2) April 2016: [Idea] Replace enumerate() with something more explicit
>> > https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160411/015074.html
>> >  
>> > <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160411/015074.html>
>> >
>> >
>> > 3) September 2016: [Proposal draft] Introducing `indexed()`collections
>> > https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160926/027355.html
>> >  
>> > <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160926/027355.html>
>> 
>> To clarify, the discussions I linked to don't all propose to remove or
>> replace `enumerated()`, but they all talk about the potential confusion
>> about what `enumerated()` does and does not do.
>> 
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
> ___
> swift-evolution mailing list
> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
> https://lists.swift.org/mailman/listinfo/swift-evolution 
> <https://lists.swift.org/mailman/listinfo/swift-evolution>
> -- 
> Sent from my phone

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


Re: [swift-evolution] Removing enumerated?

2017-01-31 Thread Matthew Johnson via swift-evolution

> On Jan 31, 2017, at 10:36 AM, Xiaodi Wu via swift-evolution 
>  wrote:
> 
> I totally sympathize with users being confused. It's an interesting idea to 
> move it to Array only.
> 
> The thing is, it does make sense (and wouldn't be confusing) to enumerate a 
> dictionary or set. Moreover, the behavior is _exactly_ what it says on the 
> tin: when you enumerate something in real life, there is no sense in which 
> the number is related to some sort of index. Can we fix this by 
> documentation? Like, a big blaring "don't use this when you want the index”?

+1.  A similar method on collection that provides indices might be useful but 
that doesn’t mean we should remove `enumerated`.  User confusion should be 
addressed by documentation.

> On Tue, Jan 31, 2017 at 09:35 Ole Begemann via swift-evolution 
> mailto:swift-evolution@swift.org>> wrote:
> On 31/01/2017 16:19, Ole Begemann via swift-evolution wrote:
> > Here are three previous discussion about this topic:
> >
> > 1) December 2015: [Idea] Add an (Index,Element) sequence to
> > CollectionType
> > https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151221/004561.html
> >  
> > 
> > and
> > https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151228/004626.html
> >  
> > 
> >
> >
> > 2) April 2016: [Idea] Replace enumerate() with something more explicit
> > https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160411/015074.html
> >  
> > 
> >
> >
> > 3) September 2016: [Proposal draft] Introducing `indexed()`collections
> > https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160926/027355.html
> >  
> > 
> 
> To clarify, the discussions I linked to don't all propose to remove or
> replace `enumerated()`, but they all talk about the potential confusion
> about what `enumerated()` does and does not do.
> 
> ___
> 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] Warn about unused Optional.some(())

2017-01-30 Thread Matthew Johnson via swift-evolution


Sent from my iPad

> On Jan 30, 2017, at 5:25 PM, Slava Pestov via swift-evolution 
>  wrote:
> 
> 
>> On Jan 30, 2017, at 2:58 PM, Daniel Duan via swift-evolution 
>>  wrote:
>> 
>> Hi all,
>> 
>> Right now, expressions that evaluates to Optional<()>, 
>> Optional>… gets special treatment when it’s unused. For example:
>> 
>> func f(s: String) {}
>> let s: String = “”
>> s.map(f) // no warning here, even tho the resulting type is `Optional<()>` 
>> and unused.
>> 
>> func g() throws {}
>> try? g() // no warnings here neither.
>> 
>> This is convenient, but encourages composing map/filter/reduce, etc with 
>> side-effect-ful functions, which we have found a few cases of in our 
>> production code recently. Granted, these cases could’ve been caught with 
>> more careful code reviews. But we wouldn’t have missed them if this 
>> “feature” didn’t exist.
>> 
>> I think we should remove the special treatment so that code in the example 
>> above would generate a warning about `()?` being unused. Users can silence 
>> it manually by assigning the result to `_`. 
>> 
>> OTOH, this would undermine the convenience of `try?` when the throwing 
>> function don’t return anything.
> 
> IMHO, using ‘try?’ to ignore an error result, instead of just turning it into 
> an optional, is an anti-pattern, and forcing users to write ‘_ = try? foo()’ 
> might not be so bad…

+1

> 
>> 
>> What do y’all think?
>> 
>> Daniel Duan
>> ___
>> 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] Public struct init is unexpectedly internal

2017-01-30 Thread Matthew Johnson via swift-evolution

> On Jan 30, 2017, at 3:32 AM, Slava Pestov via swift-evolution 
>  wrote:
> 
> 
>> On Jan 30, 2017, at 1:30 AM, David Sweeris > > wrote:
>> 
>> 
>>> On Jan 30, 2017, at 1:21 AM, Slava Pestov >> > wrote:
>>> 
 
 On Jan 30, 2017, at 1:12 AM, David Sweeris via swift-evolution 
 mailto:swift-evolution@swift.org>> wrote:
 
 So I’ve got this code in a package called “SomeLib":
 public struct SomeType {
 public var text = "SomeText"
 }
 and then, in another package, write this:
 import SomeLib
 print(SomeType().text)
 and then run swift build, I get this error:
 error: 'SomeType' initializer is inaccessible due to 'internal' protection 
 level
 
 "Well that’s odd… there isn’t even an initializer to be internal or 
 public”, I said to myself. Then I proceeded to futz around with it for a 
 while before having a lightbulb moment:
 public struct SomeType {
 public var text = "SomeText"
 public init() {} //this fixes it
 }
 
 
 In cases like this where the struct is public and all its stored 
 properties are both public and already have values, should we make the 
 implicit init() function also be public? Seems like the “least surprising” 
 thing to do.
>>> 
>>> This is intentional. I believe the core team’s rationale is that public 
>>> APIs should always be explicitly written down in source. So your example 
>>> above defining a public init() is correct.
>> 
>> Oh, I knew (well, suspected) it was intentional… I just didn't recall if 
>> we’d discussed this specific scenario before. If we did, then I don’t want 
>> to rehash it.
> 
> I think there was a proposal floating around for ‘flexible member-wise 
> initialization’. This would allow explicitly defining an initializer (to make 
> it public or @_inlineable or whatever) without writing out the boilerplate to 
> initialize all members.
> 
> I don’t have the link offhand, and I don’t remember what the conclusion was, 
> but if you’re interested you might want to look into it and revive it. ;-)

I was the author of this proposal.  It was deferred.  The review brought a lot 
of good ideas to light so it will look somewhat different when it gets revived. 
 I have been assuming it is out of scope for Phase 1 but plan to revive it when 
the time comes.  

If this *is* in scope right now please let me know and I’ll find some time to 
start a new discussion thread outlining two possible directions we could take.

> 
> Slava
> 
>> 
>> - Dave Sweeris
> 
> ___
> 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] Subclass Existentials

2017-01-30 Thread Matthew Johnson via swift-evolution

> On Jan 29, 2017, at 10:47 PM, Slava Pestov  wrote:
> 
> 
>> On Jan 29, 2017, at 2:05 PM, Matthew Johnson via swift-evolution 
>> mailto:swift-evolution@swift.org>> wrote:
>> 
>>> 
>>> On Jan 29, 2017, at 3:52 PM, Xiaodi Wu >> <mailto:xiaodi...@gmail.com>> wrote:
>>> 
>>> On Sun, Jan 29, 2017 at 3:35 PM, Matthew Johnson >> <mailto:matt...@anandabits.com>> wrote:
>>> 
>>>> On Jan 29, 2017, at 3:24 PM, Xiaodi Wu >>> <mailto:xiaodi...@gmail.com>> wrote:
>>>> 
>>>> On Sun, Jan 29, 2017 at 3:11 PM, Matthew Johnson >>> <mailto:matt...@anandabits.com>> wrote:
>>>> 
>>>>> On Jan 29, 2017, at 3:05 PM, Xiaodi Wu >>>> <mailto:xiaodi...@gmail.com>> wrote:
>>>>> 
>>>>> On Sun, Jan 29, 2017 at 2:40 PM, Matthew Johnson >>>> <mailto:matt...@anandabits.com>> wrote:
>>>>> 
>>>>>> On Jan 29, 2017, at 2:25 PM, Xiaodi Wu >>>>> <mailto:xiaodi...@gmail.com>> wrote:
>>>>>> 
>>>>>> On Sun, Jan 29, 2017 at 2:16 PM, Matthew Johnson >>>>> <mailto:matt...@anandabits.com>> wrote:
>>>>>> 
>>>>>>> On Jan 29, 2017, at 2:01 PM, Xiaodi Wu >>>>>> <mailto:xiaodi...@gmail.com>> wrote:
>>>>>>> 
>>>>>>> On Sun, Jan 29, 2017 at 1:37 PM, Matthew Johnson 
>>>>>>> mailto:matt...@anandabits.com>> wrote:
>>>>>>> 
>>>>>>> 
>>>>>>> Sent from my iPad
>>>>>>> 
>>>>>>> On Jan 29, 2017, at 12:58 PM, Xiaodi Wu via swift-evolution 
>>>>>>> mailto:swift-evolution@swift.org>> wrote:
>>>>>>> 
>>>>>>>> Cool. Another avenue of improvement here is relaxing the single-class 
>>>>>>>> spelling rule for the sake of composing typealiases.
>>>>>>>> 
>>>>>>>> As Matthew mentioned, if I have class Base and typealiases Foo = Base 
>>>>>>>> & Protocol1 and Bar = Base & Protocol2, it'd be nice to allow Foo & 
>>>>>>>> Bar.
>>>>>>>> 
>>>>>>>> It'd be nice to go one step further: given class Derived : Base, if I 
>>>>>>>> have typealiases Foo2 = Base & Protocol1 and Bar2 = Derived & 
>>>>>>>> Protocol2, then it could be permitted to write Foo2 & Bar2, since 
>>>>>>>> there is effectively only one subclass requirement (Derived).
>>>>>>>> 
>>>>>>>> As I understand it, the rationale for allowing only one subclass 
>>>>>>>> requirement is that Swift supports only single inheritance. Thus, two 
>>>>>>>> disparate subclass requirements Base1 & Base2 would make your 
>>>>>>>> existential type essentially equivalent to Never. But Base1 & Base1 & 
>>>>>>>> Base1 is fine for the type system, the implementation burden (though 
>>>>>>>> greater) shouldn't be too awful, and you would measurably improve 
>>>>>>>> composition of typealiases.
>>>>>>> 
>>>>>>> Yes, this is what I was indicating in my post as well.
>>>>>>> 
>>>>>>> Are you suggesting that Base1 & Base2 compose to a type that is treated 
>>>>>>> identically to Never do you think it should be an immediate compiler 
>>>>>>> error?  I remember having some discussion about this last year and 
>>>>>>> think somebody came up with a very interesting example of where the 
>>>>>>> former might be useful.
>>>>>>> 
>>>>>>> Last year's discussion totally eludes me for some reason. But sure, if 
>>>>>>> deferring the error until runtime is actually useful then why not? In 
>>>>>>> the absence of an interesting use case, though, I think it'd be nice 
>>>>>>> for the compiler to warn you that Base1 & Base2 is not going to be what 
>>>>>>> you want.
>>>>>> 
>>>>>> Deferring to runtime isn’t what I mean.  If you try to actually *do* 
>>>>>> anything that requires an instance of `Base1 & Based` (wh

Re: [swift-evolution] Subclass Existentials

2017-01-29 Thread Matthew Johnson via swift-evolution

> On Jan 29, 2017, at 4:48 PM, Xiaodi Wu  wrote:
> 
> On Sun, Jan 29, 2017 at 4:19 PM, Matthew Johnson via swift-evolution 
> mailto:swift-evolution@swift.org>> wrote:
> 
>> On Jan 29, 2017, at 4:01 PM, David Hart > <mailto:da...@hartbit.com>> wrote:
>> 
>> Hi Matthew,
>> 
>> I’ll reply to this post, because it allows me to discuss a few of the points 
>> in the discussion, but I’ve read the whole discussion.
>> 
>>> On 29 Jan 2017, at 18:30, Matthew Johnson >> <mailto:matt...@anandabits.com>> wrote:
>>> 
>>> Hi David,
>>> 
>>> This looks like a great start.
>>> 
>>> One thing we should consider is whether we tie this proposal so tightly to 
>>> classes or whether it might be better to call these supertype constraints.  
>>> The feature might also be useful for value types if / when Swift gets value 
>>> subtyping.
>> 
>> This makes sense, especially with the Substring : String discussions going 
>> on. When I rework the proposal, I’ll try to make it more general.
>> 
>>> One enhancement that might be worth considering.  Specifically, allowing 
>>> protocols to declare a specific supertype requirement in the place where a 
>>> `class` constraint would usually be found.  After this proposal we could 
>>> already do something similar using a `class` constraint to define a 
>>> protocol and a typealias to bind it to the supertype requirement.  It seems 
>>> like allowing users to state this more directly would be a good idea.
>> 
>> You lost me there. Can you give examples?
> 
> Sure.  In an iOS app you might want to create a protocol that should only be 
> conformed to by `UIViewController` subclasses:
> 
> protocol TrackedViewController: UIViewController {
> var analyticsTitle: String { get }
> }
> 
> This is roughly equivalent to under your proposal:
> 
> protocol TrackedObject: class {
> var analyticsTitle: String { get }
> }
> typealias TrackedViewController = UIViewController & TrackedObject
> 
> But in this case we would be able to avoid the TrackedObject protocol which 
> we didn’t care about or want, but were required to create in the process of 
> creating our typealias.
> 
> Since we allow only one subclass, this gets a little tricky, right? If 
> TrackedViewController refines UIViewController, then should it count as a 
> subclass requirement when it comes to further composition and be required 
> first?

It would be treated the same as the typealias as far as the syntax of composing 
existential types with `&` is concerned.  I imagine the sensible thing, if we 
have the “class comes first requirement" is:

protocol P {}
typealias Foo = TrackedViewController & P // allowed
typealias Foo = P & TrackedViewController // not allowed

class MyViewController: UIVIewController, TrackedViewController {}


> 
> The syntax also implies that everything on UIViewController is a requirement 
> for a TrackedViewController. Would a class that conforms to 
> TrackedViewController automatically be a subclass of UIViewController, or 
> would only subclasses of UIViewController be allowed to conform to 
> TrackedViewController (i.e. is _being_ a UIViewController a requirement for 
> conforming to TrackedViewController)? The former seems surprising, at least 
> to me. Yet in the latter case, this would behave very differently from 
> protocols you put on the right side of the colon.

I hadn’t considered this and it’s a good question.  Conforming classes should 
still have to declare their immediate superclass.  What it adds is a 
requirement that conforming types *eventually* have the constraining type as a 
supertype.  A class can pick up implementation of other requirements from it’s 
superclass so why shouldn’t it’s superclass also be able to meet a supertype 
requirement.

> Would it make sense to allow a protocol to refine a struct, too?

Eventually, yes.  Immediately, maybe.  I think this makes sense as soon as we 
get value subtyping and / or we adopt the intersection types view and allow 
uninhabited existentials.  Until then we probably don’t gain anything from it.  

Adding it immediately would reduce the need to make a future change and / or 
remember to add it when we add the other features and it probably wouldn’t 
cause any significant issues for users.  On the other hand, it’s easy to make a 
case that adding it now is unnecessary and speculative complexity and we should 
wait until we have a real use for it.

> 
> IMO this idea might be best considered separately. Could be nice to have, but 
> it touches on a little more than existentials.

Are we going to be allowed to use these existential typ

Re: [swift-evolution] Subclass Existentials

2017-01-29 Thread Matthew Johnson via swift-evolution

> On Jan 29, 2017, at 4:01 PM, David Hart  wrote:
> 
> Hi Matthew,
> 
> I’ll reply to this post, because it allows me to discuss a few of the points 
> in the discussion, but I’ve read the whole discussion.
> 
>> On 29 Jan 2017, at 18:30, Matthew Johnson > > wrote:
>> 
>> Hi David,
>> 
>> This looks like a great start.
>> 
>> One thing we should consider is whether we tie this proposal so tightly to 
>> classes or whether it might be better to call these supertype constraints.  
>> The feature might also be useful for value types if / when Swift gets value 
>> subtyping.
> 
> This makes sense, especially with the Substring : String discussions going 
> on. When I rework the proposal, I’ll try to make it more general.
> 
>> One enhancement that might be worth considering.  Specifically, allowing 
>> protocols to declare a specific supertype requirement in the place where a 
>> `class` constraint would usually be found.  After this proposal we could 
>> already do something similar using a `class` constraint to define a protocol 
>> and a typealias to bind it to the supertype requirement.  It seems like 
>> allowing users to state this more directly would be a good idea.
> 
> You lost me there. Can you give examples?

Sure.  In an iOS app you might want to create a protocol that should only be 
conformed to by `UIViewController` subclasses:

protocol TrackedViewController: UIViewController {
var analyticsTitle: String { get }
}

This is roughly equivalent to under your proposal:

protocol TrackedObject: class {
var analyticsTitle: String { get }
}
typealias TrackedViewController = UIViewController & TrackedObject

But in this case we would be able to avoid the TrackedObject protocol which we 
didn’t care about or want, but were required to create in the process of 
creating our typealias.


> 
>> As only the first element in the existential composition syntax can be a 
>> class type, and by extending this rule to typealias expansions, we can make 
>> sure that we only need to read the first element to know if it contains a 
>> class requirement.
>> 
>> I think this is unnecessarily limiting in a couple of ways.  I agree that a 
>> class should come first if it is mentioned explicitly***.  I am less sure we 
>> should require this when the type is part of a typealias combined with other 
>> protocol requirements.
> 
> I agree with Chris that I think it’s important to require the class be 
> mentioned first when the class is mentioned explicitly. Even if we lost the 
> Any syntax, there is still enough similarity to a class’s 
> inheritance/conformance clause to keep the consistency and readability.
> 
>> For example, one use case I remember discussing with Austin is refining 
>> supertype requirements.  If I have a typealias which requires a superclass 
>> `Base` I should be able to form an existential using that typealias that 
>> *refines* that requirement to some type *Derived* which is a non-final 
>> subtype of `Base`.  This would require syntax that allows us to put a class 
>> name in the first position, but also mention a typealias with a supertype 
>> requirement in a subsequent position.
> 
> I’ve read the examples in the thread and I think I agree that those cases 
> should be accepted. But just to make sure we are on the same page, what does 
> everyone think of the validity of the following cases? For shorthand, I use 
> parentheses to represent typealias expansion. For example, when I write:
> 
> Protocol1 & (Protocol2 & Protocol3)
> I mean:
> 
> typealias Something = Protocol2 & Protocol3
> Protocol1 & Something
> Questions
> 
> Should class requirements be fixed to first position? I.e., should Protocol & 
> Base be valid and equivalent to Base & Protocol?
> Should repetition of class requirements in the same declaration be allowed? 
> I.e., should Base & Base be valid and equivalent to Base?
> Should repetition of class requirements through typealias expansion be 
> allowed? I.e., should Base & (Base & Protocol) be valid and equivalent to 
> Base & Protocol?
> Should type and sub-type requirements in the same declaration be allowed? 
> I.e., should Base & Derived or Derived & Base be valid and equivalent to 
> Derived?
> Should type and sub-type requirements through typealias expansion be allowed? 
> I.e., should Base & (Derived & Protocol) or Derived & (Base & Protocol) be 
> valid and equivalent to Derived & Protocol?
> My Answers
> 
> No, for the reasons stated above.
> No, because it doesn’t make sense to repeat it in the same declaration.
> Yes, I’m gonna start agreeing with you and think will ease typealias 
> composition.
> No, for the same reasons as 2.
> Yes, for the same reasons as 3.
My answer depends on whether we adopt the perspective of intersection types and 
allow things like `Base1 & Base2` or not.  If we’re not going to do that (at 
least not yet) I think your answers are the right ones.  

However, if we decide to allow uninhabiatable 

Re: [swift-evolution] Subclass Existentials

2017-01-29 Thread Matthew Johnson via swift-evolution

> On Jan 29, 2017, at 3:52 PM, Xiaodi Wu  wrote:
> 
> On Sun, Jan 29, 2017 at 3:35 PM, Matthew Johnson  > wrote:
> 
>> On Jan 29, 2017, at 3:24 PM, Xiaodi Wu > > wrote:
>> 
>> On Sun, Jan 29, 2017 at 3:11 PM, Matthew Johnson > > wrote:
>> 
>>> On Jan 29, 2017, at 3:05 PM, Xiaodi Wu >> > wrote:
>>> 
>>> On Sun, Jan 29, 2017 at 2:40 PM, Matthew Johnson >> > wrote:
>>> 
 On Jan 29, 2017, at 2:25 PM, Xiaodi Wu >>> > wrote:
 
 On Sun, Jan 29, 2017 at 2:16 PM, Matthew Johnson >>> > wrote:
 
> On Jan 29, 2017, at 2:01 PM, Xiaodi Wu  > wrote:
> 
> On Sun, Jan 29, 2017 at 1:37 PM, Matthew Johnson  > wrote:
> 
> 
> Sent from my iPad
> 
> On Jan 29, 2017, at 12:58 PM, Xiaodi Wu via swift-evolution 
> mailto:swift-evolution@swift.org>> wrote:
> 
>> Cool. Another avenue of improvement here is relaxing the single-class 
>> spelling rule for the sake of composing typealiases.
>> 
>> As Matthew mentioned, if I have class Base and typealiases Foo = Base & 
>> Protocol1 and Bar = Base & Protocol2, it'd be nice to allow Foo & Bar.
>> 
>> It'd be nice to go one step further: given class Derived : Base, if I 
>> have typealiases Foo2 = Base & Protocol1 and Bar2 = Derived & Protocol2, 
>> then it could be permitted to write Foo2 & Bar2, since there is 
>> effectively only one subclass requirement (Derived).
>> 
>> As I understand it, the rationale for allowing only one subclass 
>> requirement is that Swift supports only single inheritance. Thus, two 
>> disparate subclass requirements Base1 & Base2 would make your 
>> existential type essentially equivalent to Never. But Base1 & Base1 & 
>> Base1 is fine for the type system, the implementation burden (though 
>> greater) shouldn't be too awful, and you would measurably improve 
>> composition of typealiases.
> 
> Yes, this is what I was indicating in my post as well.
> 
> Are you suggesting that Base1 & Base2 compose to a type that is treated 
> identically to Never do you think it should be an immediate compiler 
> error?  I remember having some discussion about this last year and think 
> somebody came up with a very interesting example of where the former 
> might be useful.
> 
> Last year's discussion totally eludes me for some reason. But sure, if 
> deferring the error until runtime is actually useful then why not? In the 
> absence of an interesting use case, though, I think it'd be nice for the 
> compiler to warn you that Base1 & Base2 is not going to be what you want.
 
 Deferring to runtime isn’t what I mean.  If you try to actually *do* 
 anything that requires an instance of `Base1 & Based` (which you almost 
 always would) you would still get a compile time error.
 
 I managed to dig up the example from last year’s thread and it is 
 definitely a good one:
 
 func intersection(ts; Set, us: Set) -> Set
 
 The desire is that we are always able to produce a result set.  When T & U 
 is uninhabitable it will simply be an empty set just like Set has a 
 single value which is the empty set.
 
 Currently, Set is impossible because Never is not Hashable :)
>>> 
>>> Ahh, good point.  I hadn’t tried it.  It can easily be made Hashable with a 
>>> simple extension though - this code compiles today:
>>> 
>>> extension Never: Hashable {
>>> public var hashValue: Int { return 0 }
>>> }
>>> public func ==(lhs: Never, rhs: Never) -> Bool { return false }
>>> let s = Set()
>>> 
 Since concrete types *can't* be used, this example seems like it'd be of 
 little use currently. How widely useful would it be to have an 
 intersection facility such as this when T != U even if that restriction 
 were lifted, though? Seems like the only real useful thing you can do with 
 generic Set is based on the fact that it'd be Set. Other 
 than those immediate thoughts, I'll have to think harder on this.
>>> 
>>> Sure, it’s possible that this is the only interesting example and may not 
>>> have enough value to be worthwhile.  But I found it interesting enough that 
>>> it stuck around in the back of my mind for 8 months! :) 
>>>  
>>> Hmm, it had not occurred to me: instantiating a Set is not 
>>> supported (and you can substitute for Hashable any protocol you want). 
>>> Thus, for any Set and Set that you can actually instantiate, unless T 
>>> and U are both classes and one inherits from the other (in which case the 
>>> generic `intersection(a: Set, b: Set) -> Set` already 
>>> suffices), Set must be the empty set. This is not a very interesting 
>>> result.
>

Re: [swift-evolution] Subclass Existentials

2017-01-29 Thread Matthew Johnson via swift-evolution

> On Jan 29, 2017, at 3:24 PM, Xiaodi Wu  wrote:
> 
> On Sun, Jan 29, 2017 at 3:11 PM, Matthew Johnson  > wrote:
> 
>> On Jan 29, 2017, at 3:05 PM, Xiaodi Wu > > wrote:
>> 
>> On Sun, Jan 29, 2017 at 2:40 PM, Matthew Johnson > > wrote:
>> 
>>> On Jan 29, 2017, at 2:25 PM, Xiaodi Wu >> > wrote:
>>> 
>>> On Sun, Jan 29, 2017 at 2:16 PM, Matthew Johnson >> > wrote:
>>> 
 On Jan 29, 2017, at 2:01 PM, Xiaodi Wu >>> > wrote:
 
 On Sun, Jan 29, 2017 at 1:37 PM, Matthew Johnson >>> > wrote:
 
 
 Sent from my iPad
 
 On Jan 29, 2017, at 12:58 PM, Xiaodi Wu via swift-evolution 
 mailto:swift-evolution@swift.org>> wrote:
 
> Cool. Another avenue of improvement here is relaxing the single-class 
> spelling rule for the sake of composing typealiases.
> 
> As Matthew mentioned, if I have class Base and typealiases Foo = Base & 
> Protocol1 and Bar = Base & Protocol2, it'd be nice to allow Foo & Bar.
> 
> It'd be nice to go one step further: given class Derived : Base, if I 
> have typealiases Foo2 = Base & Protocol1 and Bar2 = Derived & Protocol2, 
> then it could be permitted to write Foo2 & Bar2, since there is 
> effectively only one subclass requirement (Derived).
> 
> As I understand it, the rationale for allowing only one subclass 
> requirement is that Swift supports only single inheritance. Thus, two 
> disparate subclass requirements Base1 & Base2 would make your existential 
> type essentially equivalent to Never. But Base1 & Base1 & Base1 is fine 
> for the type system, the implementation burden (though greater) shouldn't 
> be too awful, and you would measurably improve composition of typealiases.
 
 Yes, this is what I was indicating in my post as well.
 
 Are you suggesting that Base1 & Base2 compose to a type that is treated 
 identically to Never do you think it should be an immediate compiler 
 error?  I remember having some discussion about this last year and think 
 somebody came up with a very interesting example of where the former might 
 be useful.
 
 Last year's discussion totally eludes me for some reason. But sure, if 
 deferring the error until runtime is actually useful then why not? In the 
 absence of an interesting use case, though, I think it'd be nice for the 
 compiler to warn you that Base1 & Base2 is not going to be what you want.
>>> 
>>> Deferring to runtime isn’t what I mean.  If you try to actually *do* 
>>> anything that requires an instance of `Base1 & Based` (which you almost 
>>> always would) you would still get a compile time error.
>>> 
>>> I managed to dig up the example from last year’s thread and it is 
>>> definitely a good one:
>>> 
>>> func intersection(ts; Set, us: Set) -> Set
>>> 
>>> The desire is that we are always able to produce a result set.  When T & U 
>>> is uninhabitable it will simply be an empty set just like Set has a 
>>> single value which is the empty set.
>>> 
>>> Currently, Set is impossible because Never is not Hashable :)
>> 
>> Ahh, good point.  I hadn’t tried it.  It can easily be made Hashable with a 
>> simple extension though - this code compiles today:
>> 
>> extension Never: Hashable {
>> public var hashValue: Int { return 0 }
>> }
>> public func ==(lhs: Never, rhs: Never) -> Bool { return false }
>> let s = Set()
>> 
>>> Since concrete types *can't* be used, this example seems like it'd be of 
>>> little use currently. How widely useful would it be to have an intersection 
>>> facility such as this when T != U even if that restriction were lifted, 
>>> though? Seems like the only real useful thing you can do with generic Set>> & U> is based on the fact that it'd be Set. Other than those 
>>> immediate thoughts, I'll have to think harder on this.
>> 
>> Sure, it’s possible that this is the only interesting example and may not 
>> have enough value to be worthwhile.  But I found it interesting enough that 
>> it stuck around in the back of my mind for 8 months! :) 
>>  
>> Hmm, it had not occurred to me: instantiating a Set is not 
>> supported (and you can substitute for Hashable any protocol you want). Thus, 
>> for any Set and Set that you can actually instantiate, unless T and U 
>> are both classes and one inherits from the other (in which case the generic 
>> `intersection(a: Set, b: Set) -> Set` already suffices), Set> U> must be the empty set. This is not a very interesting result.
> 
> Yes, but this is a limitation due to the fact the existentials for a protocol 
> do not conform to the protocol.  In some cases the existential *cannot* 
> conform to the protocol but in many cases (especially common cases) it *can*. 
>  It just doesn’t today.  There is widespread desi

Re: [swift-evolution] Subclass Existentials

2017-01-29 Thread Matthew Johnson via swift-evolution

> On Jan 29, 2017, at 3:05 PM, Xiaodi Wu  wrote:
> 
> On Sun, Jan 29, 2017 at 2:40 PM, Matthew Johnson  > wrote:
> 
>> On Jan 29, 2017, at 2:25 PM, Xiaodi Wu > > wrote:
>> 
>> On Sun, Jan 29, 2017 at 2:16 PM, Matthew Johnson > > wrote:
>> 
>>> On Jan 29, 2017, at 2:01 PM, Xiaodi Wu >> > wrote:
>>> 
>>> On Sun, Jan 29, 2017 at 1:37 PM, Matthew Johnson >> > wrote:
>>> 
>>> 
>>> Sent from my iPad
>>> 
>>> On Jan 29, 2017, at 12:58 PM, Xiaodi Wu via swift-evolution 
>>> mailto:swift-evolution@swift.org>> wrote:
>>> 
 Cool. Another avenue of improvement here is relaxing the single-class 
 spelling rule for the sake of composing typealiases.
 
 As Matthew mentioned, if I have class Base and typealiases Foo = Base & 
 Protocol1 and Bar = Base & Protocol2, it'd be nice to allow Foo & Bar.
 
 It'd be nice to go one step further: given class Derived : Base, if I have 
 typealiases Foo2 = Base & Protocol1 and Bar2 = Derived & Protocol2, then 
 it could be permitted to write Foo2 & Bar2, since there is effectively 
 only one subclass requirement (Derived).
 
 As I understand it, the rationale for allowing only one subclass 
 requirement is that Swift supports only single inheritance. Thus, two 
 disparate subclass requirements Base1 & Base2 would make your existential 
 type essentially equivalent to Never. But Base1 & Base1 & Base1 is fine 
 for the type system, the implementation burden (though greater) shouldn't 
 be too awful, and you would measurably improve composition of typealiases.
>>> 
>>> Yes, this is what I was indicating in my post as well.
>>> 
>>> Are you suggesting that Base1 & Base2 compose to a type that is treated 
>>> identically to Never do you think it should be an immediate compiler error? 
>>>  I remember having some discussion about this last year and think somebody 
>>> came up with a very interesting example of where the former might be useful.
>>> 
>>> Last year's discussion totally eludes me for some reason. But sure, if 
>>> deferring the error until runtime is actually useful then why not? In the 
>>> absence of an interesting use case, though, I think it'd be nice for the 
>>> compiler to warn you that Base1 & Base2 is not going to be what you want.
>> 
>> Deferring to runtime isn’t what I mean.  If you try to actually *do* 
>> anything that requires an instance of `Base1 & Based` (which you almost 
>> always would) you would still get a compile time error.
>> 
>> I managed to dig up the example from last year’s thread and it is definitely 
>> a good one:
>> 
>> func intersection(ts; Set, us: Set) -> Set
>> 
>> The desire is that we are always able to produce a result set.  When T & U 
>> is uninhabitable it will simply be an empty set just like Set has a 
>> single value which is the empty set.
>> 
>> Currently, Set is impossible because Never is not Hashable :)
> 
> Ahh, good point.  I hadn’t tried it.  It can easily be made Hashable with a 
> simple extension though - this code compiles today:
> 
> extension Never: Hashable {
> public var hashValue: Int { return 0 }
> }
> public func ==(lhs: Never, rhs: Never) -> Bool { return false }
> let s = Set()
> 
>> Since concrete types *can't* be used, this example seems like it'd be of 
>> little use currently. How widely useful would it be to have an intersection 
>> facility such as this when T != U even if that restriction were lifted, 
>> though? Seems like the only real useful thing you can do with generic Set> & U> is based on the fact that it'd be Set. Other than those 
>> immediate thoughts, I'll have to think harder on this.
> 
> Sure, it’s possible that this is the only interesting example and may not 
> have enough value to be worthwhile.  But I found it interesting enough that 
> it stuck around in the back of my mind for 8 months! :) 
>  
> Hmm, it had not occurred to me: instantiating a Set is not 
> supported (and you can substitute for Hashable any protocol you want). Thus, 
> for any Set and Set that you can actually instantiate, unless T and U 
> are both classes and one inherits from the other (in which case the generic 
> `intersection(a: Set, b: Set) -> Set` already suffices), Set U> must be the empty set. This is not a very interesting result.

Yes, but this is a limitation due to the fact the existentials for a protocol 
do not conform to the protocol.  In some cases the existential *cannot* conform 
to the protocol but in many cases (especially common cases) it *can*.  It just 
doesn’t today.  There is widespread desire to see this situation improve.

> 
> It generalizes easily to any cases where you have a generic type that is 
> useful despite not necessarily having access to instances of the 
> parameterized type.
> 
> If we allow this, I *think* all uninhabitable types could be unified 
> semanti

Re: [swift-evolution] Subclass Existentials

2017-01-29 Thread Matthew Johnson via swift-evolution

> On Jan 29, 2017, at 2:25 PM, Xiaodi Wu  wrote:
> 
> On Sun, Jan 29, 2017 at 2:16 PM, Matthew Johnson  > wrote:
> 
>> On Jan 29, 2017, at 2:01 PM, Xiaodi Wu > > wrote:
>> 
>> On Sun, Jan 29, 2017 at 1:37 PM, Matthew Johnson > > wrote:
>> 
>> 
>> Sent from my iPad
>> 
>> On Jan 29, 2017, at 12:58 PM, Xiaodi Wu via swift-evolution 
>> mailto:swift-evolution@swift.org>> wrote:
>> 
>>> Cool. Another avenue of improvement here is relaxing the single-class 
>>> spelling rule for the sake of composing typealiases.
>>> 
>>> As Matthew mentioned, if I have class Base and typealiases Foo = Base & 
>>> Protocol1 and Bar = Base & Protocol2, it'd be nice to allow Foo & Bar.
>>> 
>>> It'd be nice to go one step further: given class Derived : Base, if I have 
>>> typealiases Foo2 = Base & Protocol1 and Bar2 = Derived & Protocol2, then it 
>>> could be permitted to write Foo2 & Bar2, since there is effectively only 
>>> one subclass requirement (Derived).
>>> 
>>> As I understand it, the rationale for allowing only one subclass 
>>> requirement is that Swift supports only single inheritance. Thus, two 
>>> disparate subclass requirements Base1 & Base2 would make your existential 
>>> type essentially equivalent to Never. But Base1 & Base1 & Base1 is fine for 
>>> the type system, the implementation burden (though greater) shouldn't be 
>>> too awful, and you would measurably improve composition of typealiases.
>> 
>> Yes, this is what I was indicating in my post as well.
>> 
>> Are you suggesting that Base1 & Base2 compose to a type that is treated 
>> identically to Never do you think it should be an immediate compiler error?  
>> I remember having some discussion about this last year and think somebody 
>> came up with a very interesting example of where the former might be useful.
>> 
>> Last year's discussion totally eludes me for some reason. But sure, if 
>> deferring the error until runtime is actually useful then why not? In the 
>> absence of an interesting use case, though, I think it'd be nice for the 
>> compiler to warn you that Base1 & Base2 is not going to be what you want.
> 
> Deferring to runtime isn’t what I mean.  If you try to actually *do* anything 
> that requires an instance of `Base1 & Based` (which you almost always would) 
> you would still get a compile time error.
> 
> I managed to dig up the example from last year’s thread and it is definitely 
> a good one:
> 
> func intersection(ts; Set, us: Set) -> Set
> 
> The desire is that we are always able to produce a result set.  When T & U is 
> uninhabitable it will simply be an empty set just like Set has a 
> single value which is the empty set.
> 
> Currently, Set is impossible because Never is not Hashable :)

Ahh, good point.  I hadn’t tried it.  It can easily be made Hashable with a 
simple extension though - this code compiles today:

extension Never: Hashable {
public var hashValue: Int { return 0 }
}
public func ==(lhs: Never, rhs: Never) -> Bool { return false }
let s = Set()

> Since concrete types *can't* be used, this example seems like it'd be of 
> little use currently. How widely useful would it be to have an intersection 
> facility such as this when T != U even if that restriction were lifted, 
> though? Seems like the only real useful thing you can do with generic Set U> is based on the fact that it'd be Set. Other than those 
> immediate thoughts, I'll have to think harder on this.

Sure, it’s possible that this is the only interesting example and may not have 
enough value to be worthwhile.  But I found it interesting enough that it stuck 
around in the back of my mind for 8 months! :)  

It generalizes easily to any cases where you have a generic type that is useful 
despite not necessarily having access to instances of the parameterized type.

If we allow this, I *think* all uninhabitable types could be unified 
semantically by making `Never` a protocol and giving them implicit conformance.

> 
> This example points even more strongly in the direction of allowing *any* 
> concrete type to be used, not just classes - even today we could produce 
> uninhabitable existentials like this using value types.
> 
> Here’s the link to the thread: 
> https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160523/019463.html
>  
> 
>> 
>> 
>>> On Sun, Jan 29, 2017 at 12:41 Austin Zheng >> > wrote:
>>> The "class comes first" requirement made more sense when the proposed 
>>> syntax was still "Any", intentionally mirroring how the superclass 
>>> and conformances are declared on a class declaration (the archives contain 
>>> more detailed arguments, both pro and con). Now that the syntax is "T & U & 
>>> V", I agree that privileging the class requirement is counterintuitive and 
>>> probably unhelpful.
>>> 
>>> Austin
>>> 

Re: [swift-evolution] Subclass Existentials

2017-01-29 Thread Matthew Johnson via swift-evolution

> On Jan 29, 2017, at 2:01 PM, Xiaodi Wu  wrote:
> 
> On Sun, Jan 29, 2017 at 1:37 PM, Matthew Johnson  > wrote:
> 
> 
> Sent from my iPad
> 
> On Jan 29, 2017, at 12:58 PM, Xiaodi Wu via swift-evolution 
> mailto:swift-evolution@swift.org>> wrote:
> 
>> Cool. Another avenue of improvement here is relaxing the single-class 
>> spelling rule for the sake of composing typealiases.
>> 
>> As Matthew mentioned, if I have class Base and typealiases Foo = Base & 
>> Protocol1 and Bar = Base & Protocol2, it'd be nice to allow Foo & Bar.
>> 
>> It'd be nice to go one step further: given class Derived : Base, if I have 
>> typealiases Foo2 = Base & Protocol1 and Bar2 = Derived & Protocol2, then it 
>> could be permitted to write Foo2 & Bar2, since there is effectively only one 
>> subclass requirement (Derived).
>> 
>> As I understand it, the rationale for allowing only one subclass requirement 
>> is that Swift supports only single inheritance. Thus, two disparate subclass 
>> requirements Base1 & Base2 would make your existential type essentially 
>> equivalent to Never. But Base1 & Base1 & Base1 is fine for the type system, 
>> the implementation burden (though greater) shouldn't be too awful, and you 
>> would measurably improve composition of typealiases.
> 
> Yes, this is what I was indicating in my post as well.
> 
> Are you suggesting that Base1 & Base2 compose to a type that is treated 
> identically to Never do you think it should be an immediate compiler error?  
> I remember having some discussion about this last year and think somebody 
> came up with a very interesting example of where the former might be useful.
> 
> Last year's discussion totally eludes me for some reason. But sure, if 
> deferring the error until runtime is actually useful then why not? In the 
> absence of an interesting use case, though, I think it'd be nice for the 
> compiler to warn you that Base1 & Base2 is not going to be what you want.

Deferring to runtime isn’t what I mean.  If you try to actually *do* anything 
that requires an instance of `Base1 & Based` (which you almost always would) 
you would still get a compile time error.

I managed to dig up the example from last year’s thread and it is definitely a 
good one:

func intersection(ts; Set, us: Set) -> Set

The desire is that we are always able to produce a result set.  When T & U is 
uninhabitable it will simply be an empty set just like Set has a single 
value which is the empty set.  

This example points even more strongly in the direction of allowing *any* 
concrete type to be used, not just classes - even today we could produce 
uninhabitable existentials like this using value types.

Here’s the link to the thread: 
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160523/019463.html

> 
> 
>> On Sun, Jan 29, 2017 at 12:41 Austin Zheng > > wrote:
>> The "class comes first" requirement made more sense when the proposed syntax 
>> was still "Any", intentionally mirroring how the superclass and 
>> conformances are declared on a class declaration (the archives contain more 
>> detailed arguments, both pro and con). Now that the syntax is "T & U & V", I 
>> agree that privileging the class requirement is counterintuitive and 
>> probably unhelpful.
>> 
>> Austin
>> 
>> > On Jan 29, 2017, at 10:37 AM, Matt Whiteside via swift-evolution 
>> > mailto:swift-evolution@swift.org>> wrote:
>> >
>> > Thanks for writing this proposal David.
>> >
>> >> On Jan 29, 2017, at 10:13, Xiaodi Wu via swift-evolution 
>> >> mailto:swift-evolution@swift.org>> wrote:
>> >>
>> >> As Matthew mentioned, the rules can certainly later be relaxed, but given 
>> >> that this proposal has the compiler generating fix-its for subclasses in 
>> >> second position, is there a reason other than stylistic for demanding 
>> >> MyClass & MyProtocol instead of MyProtocol & MyClass?
>> >>
>> >> From a naive perspective, it seems that if the compiler understands my 
>> >> meaning perfectly, it should just accept that spelling rather than 
>> >> complain.
>> >
>> > I had that thought too.  Since ‘and’ is a symmetric operation, requiring 
>> > the class to be in the first position seems counter-intuitive.
>> >
>> > -Matt
>> >
>> > ___
>> > 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] Subclass Existentials

2017-01-29 Thread Matthew Johnson via swift-evolution


Sent from my iPad

> On Jan 29, 2017, at 12:58 PM, Xiaodi Wu via swift-evolution 
>  wrote:
> 
> Cool. Another avenue of improvement here is relaxing the single-class 
> spelling rule for the sake of composing typealiases.
> 
> As Matthew mentioned, if I have class Base and typealiases Foo = Base & 
> Protocol1 and Bar = Base & Protocol2, it'd be nice to allow Foo & Bar.
> 
> It'd be nice to go one step further: given class Derived : Base, if I have 
> typealiases Foo2 = Base & Protocol1 and Bar2 = Derived & Protocol2, then it 
> could be permitted to write Foo2 & Bar2, since there is effectively only one 
> subclass requirement (Derived).
> 
> As I understand it, the rationale for allowing only one subclass requirement 
> is that Swift supports only single inheritance. Thus, two disparate subclass 
> requirements Base1 & Base2 would make your existential type essentially 
> equivalent to Never. But Base1 & Base1 & Base1 is fine for the type system, 
> the implementation burden (though greater) shouldn't be too awful, and you 
> would measurably improve composition of typealiases.

Yes, this is what I was indicating in my post as well.

Are you suggesting that Base1 & Base2 compose to a type that is treated 
identically to Never do you think it should be an immediate compiler error?  I 
remember having some discussion about this last year and think somebody came up 
with a very interesting example of where the former might be useful.

>> On Sun, Jan 29, 2017 at 12:41 Austin Zheng  wrote:
>> The "class comes first" requirement made more sense when the proposed syntax 
>> was still "Any", intentionally mirroring how the superclass and 
>> conformances are declared on a class declaration (the archives contain more 
>> detailed arguments, both pro and con). Now that the syntax is "T & U & V", I 
>> agree that privileging the class requirement is counterintuitive and 
>> probably unhelpful.
>> 
>> Austin
>> 
>> > On Jan 29, 2017, at 10:37 AM, Matt Whiteside via swift-evolution 
>> >  wrote:
>> >
>> > Thanks for writing this proposal David.
>> >
>> >> On Jan 29, 2017, at 10:13, Xiaodi Wu via swift-evolution 
>> >>  wrote:
>> >>
>> >> As Matthew mentioned, the rules can certainly later be relaxed, but given 
>> >> that this proposal has the compiler generating fix-its for subclasses in 
>> >> second position, is there a reason other than stylistic for demanding 
>> >> MyClass & MyProtocol instead of MyProtocol & MyClass?
>> >>
>> >> From a naive perspective, it seems that if the compiler understands my 
>> >> meaning perfectly, it should just accept that spelling rather than 
>> >> complain.
>> >
>> > I had that thought too.  Since ‘and’ is a symmetric operation, requiring 
>> > the class to be in the first position seems counter-intuitive.
>> >
>> > -Matt
>> >
>> > ___
>> > 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] Subclass Existentials

2017-01-29 Thread Matthew Johnson via swift-evolution
Hi David,

This looks like a great start.

One thing we should consider is whether we tie this proposal so tightly to 
classes or whether it might be better to call these supertype constraints.  The 
feature might also be useful for value types if / when Swift gets value 
subtyping.

One enhancement that might be worth considering.  Specifically, allowing 
protocols to declare a specific supertype requirement in the place where a 
`class` constraint would usually be found.  After this proposal we could 
already do something similar using a `class` constraint to define a protocol 
and a typealias to bind it to the supertype requirement.  It seems like 
allowing users to state this more directly would be a good idea.

As only the first element in the existential composition syntax can be a class 
type, and by extending this rule to typealias expansions, we can make sure that 
we only need to read the first element to know if it contains a class 
requirement.

I think this is unnecessarily limiting in a couple of ways.  I agree that a 
class should come first if it is mentioned explicitly***.  I am less sure we 
should require this when the type is part of a typealias combined with other 
protocol requirements.  

For example, one use case I remember discussing with Austin is refining 
supertype requirements.  If I have a typealias which requires a superclass 
`Base` I should be able to form an existential using that typealias that 
*refines* that requirement to some type *Derived* which is a non-final subtype 
of `Base`.  This would require syntax that allows us to put a class name in the 
first position, but also mention a typealias with a supertype requirement in a 
subsequent position.

Matthew

*** One argument against requiring a class to come first is that we could 
conceptualize `&` as a type operator with a handful of overloads.  This would 
include both lhs and rhs are “protocol only kinds” as well as overloads with a 
“protocol only kind” in either lhs or rhs and a “supertype kind” in the other 
position.  The tricky part of pulling this off would be including an overload 
where both lhs and rhs have a “supertype kind”, but only when the operands have 
a subtype / supertype relationship with each other.  

I suspect this conceptualization isn’t worth the complexity it brings, but it 
is tempting to try and view `&` as a type operator.  As long as this only 
involves a loosening of restrictions it could probably be introduced as an 
additive change down the road.

> On Jan 29, 2017, at 10:39 AM, David Hart  wrote:
> 
> Hello,
> 
> As promised, I wrote the first draft of a proposal to add class requirements 
> to the existential syntax. Please let me know what you think.
> 
> https://github.com/hartbit/swift-evolution/blob/subclass-existentials/proposals/-subclass-existentials.md
>  
> 
> 
> Regards,
> David.
> 
> Existentials for classes conforming to protocols
> 
> Proposal: SE- 
> 
> Authors: David Hart , Austin Zheng 
> 
> Review Manager: TBD
> Status: TBD
>  
> Introduction
> 
> This proposal brings more expressive power to the type system by allowing 
> Swift to represent existentials of classes and subclasses which conform to 
> protocols.
> 
>  
> Motivation
> 
> Currently, the only existentials which can be represented in Swift are 
> conformances to a set of protocols, using the &syntax:
> 
> let existential: Hashable & CustomStringConvertible
> On the other hand, Objective-C is capable of expressing existentials of 
> subclasses conforming to protocols with the following syntax:
> 
> UIViewController* existential;
> We propose to provide similar expressive power to Swift, which will also 
> improve the bridging of those types from Objective-C.
> 
>  
> Proposed
>  solution
> 
> The proposal keeps the existing & syntax but allows the first element, and 
> only the first, to be of class type. The equivalent declaration to the above 
> Objective-C declaration would look like this:
> 
> let existential: UIViewController & UITableViewDataSource & 
> UITableViewDelegate
> As in Objective-C, this existential represents classes which have 
> UIViewController in their parent inheritance hierarchy and which also conform 
> to the UITableViewDataSource and UITableViewDelegate protocols.
> 
> As only the first element in the existential composition syntax can be a 
> class type, and by extending this rule to typealias expansions, we can m

Re: [swift-evolution] Strings in Swift 4

2017-01-27 Thread Matthew Johnson via swift-evolution

> 
> Right.  The standard approach we take in Swift has been to start with 
> something baked into the language, then generalize it out to the stdlib over 
> time if there is a reason to.  I’d love to see the various magic around 
> Optional be accessible to other types, for example.
> 
> -Chris
> 

+1.  I love how Swift takes this approach.  I would love to see Optional sugar 
expanded such that types like Result, for example, could take advantage of it.
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] A case for postponing ABI stability

2017-01-27 Thread Matthew Johnson via swift-evolution

> On Jan 26, 2017, at 9:48 PM, Dave Abrahams via swift-evolution 
>  wrote:
> 
> 
> on Thu Jan 26 2017, Matthew Johnson  wrote:
> 
>>> On Jan 26, 2017, at 3:10 PM, Dave Abrahams via swift-evolution 
>>>  wrote:
>>> 
>>> 
>>> on Thu Jan 26 2017, David Hart  wrote:
>>> 
>> 
 Thanks Michael for the manifesto. It definitely made quite a few things 
 clearer for me.
 
 Concerning the topic of when ABI stability should happen, I still have
 a strong feelings that Swift 4 might not be the best time for
 it. Concerning Data Layout, Type Metadata, Mangling, the Calling
 Convention and the Runtime, I don’t know enough about them to
 comment. I’m really centring my discussion on the Standard Library.
 
 If we look back at the evolution of the Standard Library for Swift 3,
 they were many changes. And I’m personally very happy with the
 thoughtful design that went into those. But they are still a few
 gotchas, which is to be expected when so many changes are made at
 once. But we only discover them once the thousands of Swift developers
 start using those APIs.
 
 I just worry that all the big changes that will come for Swift 4 won’t
 have time to mature. Furthermore, it seems like several extra compiler
 features which won’t happen in Swift 4 are really necessary to
 simplify the Standard Library surface area. I’m specifically thinking
 of type constraints on Existentials which would allow us to get rid of
 all the Any* structs and replace them with typedefs. But I’m sure
 there are more examples like those which are just waiting for the
 generics to become powerful enough to express APIs more elegantly.
 
 Perhaps someone from the Standard Library team can chime in to give us
 their opinion on this topic.
>>> 
>>> I have had exactly the same worry for quite some time.  We're still
>>> waiting for many basic components of the generics system, and, if our
>>> experience with protocol extensions is any guide, before we have those
>>> features in hand, it will be impossible to anticipate the design changes
>>> we'd want to make to the standard library... and that cuts against the
>>> grain of *source* (to say nothing of ABI) stability.
>>> 
>>> So far I've been unable to form a mental model for what source and/or
>>> ABI stability actually means for our ability to make changes to the
>>> standard library in the future.  It's possible that we discover a
>>> workable path forward, but it's equally possible that we find ourselves
>>> painted into a corner.
>> 
>> I hope we can all agree that the last thing we want to do is get
>> painted into a corner.  IMO we should be very sure that won’t happen
>> before making a firm commitment to lock down ABI stability.
> 
> Unfortunately, even source stability (which is generally a weaker
> constraint than ABI stability) can have the corner-painting effect, and
> you really have to weigh that downside off against the cost of breaking
> people's code when they upgrade their Swift version.  IIUC that has been
> a major pain point for many people.

Yes, for sure.  I just don’t want to see us end up with baggage in the long run 
because we made promises when foreseeable changes were still on the horizon.

Swift 3 migration has definitely caused some pain.  For a small to moderate 
sized app with a small team it is kind of annoying not really that bad (a 
couple days tops).  For larger apps with larger teams it is pretty disruptive.  
I’ll be part of the migration effort for a fairly large app in the near future. 
 I’m really interested to see how that migration plays out.

I imagine future source breaking changes will be much more modest and we will 
have a better story around dependencies so I expect the pain will be 
significantly less.  We will also have the experience of the Swift 3 migration 
which will help in weighing what the real world cost of specific proposed 
changes might be.

> 
> -- 
> -Dave
> 
> ___
> 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] A case for postponing ABI stability

2017-01-27 Thread Matthew Johnson via swift-evolution

> On Jan 26, 2017, at 8:22 PM, Michael Ilseman  wrote:
> 
> 
>> On Jan 26, 2017, at 5:48 PM, Matthew Johnson via swift-evolution 
>> mailto:swift-evolution@swift.org>> wrote:
>> 
>> 
>> 
>> Sent from my iPad
>> 
>> On Jan 26, 2017, at 7:29 PM, Ted Kremenek > <mailto:kreme...@apple.com>> wrote:
>> 
>>> 
>>>> On Jan 26, 2017, at 12:19 PM, Matthew Johnson via swift-evolution 
>>>> mailto:swift-evolution@swift.org>> wrote:
>>>> 
>>>> Locking down ABI when all foreseeable desirable changes are additive is 
>>>> one thing.  But doing so before we get there feels premature.
>>> 
>>> 
>>> I fully agree that locking down the ABI prematurely would be detrimental to 
>>> the long-term future of the language.
>>> 
>>> Part of the point of the ABI manifesto is to scope out what are the 
>>> desirable or critical changes needed before ABI gets locked down.  From 
>>> that we can have concrete discussions on what’s left to be done, how much 
>>> work it will take to get there, etc.
>> 
>> That makes perfect sense.  
>> 
>> One thing that isn't clear in the manifesto that I think a lot of us are 
>> wondering about is what language features are important to the long-term 
>> desired design of the standard library that aren't in place yet?  There has 
>> been some informal discussion of this on the list but nothing more and it 
>> hasn't been clear whether those features will be ready by the time ABI 
>> stability is locked down.   Maybe the manifesto is a good place to start 
>> documenting more formally the language features needed to realize the 
>> desired design of the standard library APIs that will be present when the 
>> ABI is declared stable.
> 
> There’s a bit of a chicken-and-the-egg problem here, where the stdlib will 
> discover better APIs after playing with new language features. This is one of 
> the reasons for the intense focus in Swift 4 phase 1.

Yes of course.  But I imagine we could come up with a reasonable list of 
language features that we *think* would have an impact on the library APIs that 
exist today.

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

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


Re: [swift-evolution] A case for postponing ABI stability

2017-01-26 Thread Matthew Johnson via swift-evolution


Sent from my iPad

> On Jan 26, 2017, at 7:29 PM, Ted Kremenek  wrote:
> 
> 
>> On Jan 26, 2017, at 12:19 PM, Matthew Johnson via swift-evolution 
>>  wrote:
>> 
>> Locking down ABI when all foreseeable desirable changes are additive is one 
>> thing.  But doing so before we get there feels premature.
> 
> 
> I fully agree that locking down the ABI prematurely would be detrimental to 
> the long-term future of the language.
> 
> Part of the point of the ABI manifesto is to scope out what are the desirable 
> or critical changes needed before ABI gets locked down.  From that we can 
> have concrete discussions on what’s left to be done, how much work it will 
> take to get there, etc.

That makes perfect sense.  

One thing that isn't clear in the manifesto that I think a lot of us are 
wondering about is what language features are important to the long-term 
desired design of the standard library that aren't in place yet?  There has 
been some informal discussion of this on the list but nothing more and it 
hasn't been clear whether those features will be ready by the time ABI 
stability is locked down.   Maybe the manifesto is a good place to start 
documenting more formally the language features needed to realize the desired 
design of the standard library APIs that will be present when the ABI is 
declared stable.___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


<    1   2   3   4   5   6   7   8   9   10   >