Re: [swift-evolution] [Draft] open and public protocols

2017-02-19 Thread Zach Waldowski via swift-evolution
On Sun, Feb 19, 2017, at 10:57 PM, Xiaodi Wu via swift-evolution wrote:
> Left unsaid from my reply about enums is that implicit conversions
> should absolutely be added. We already have this magic for one
> particular enum, Optional.


I can only see a generalization of this being used for evil.
Perhaps that's best left to be discussed on some other knock-down,
drag-out thread.


> I'm not arguing with you that enums are currently unsuitable. In fact
> I entirely agree. But Chris Lattner and others have said (now I'm
> paraphrasing, but I believe accurately) that they *should* be. What
> will it take? At minimum, some way to opt into implicit conversions.
> It's a no-brainer in my mind.
> 

> Bottom line: the language needs one excellent way to model Foo | Bar |
> Baz, not two or three mediocre workarounds. The core team has said
> that they want that excellence to be built through enums. Let's do it.


I don't understand how extending protocols to parallel the changes we
already made to classes — and in line with what's planned for enums — is
a mediocre workaround.


I have low confidence in Evolution being able to produce a passable
union type design in a meaningful amount of time, particularly for Swift
4 Phase 2; I also question their need in the first place.


Sincerely,

  Zachary Waldowski

  z...@waldowski.me


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


Re: [swift-evolution] [Draft] open and public protocols

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


Sent from my iPad

> On Feb 19, 2017, at 9:57 PM, Xiaodi Wu via swift-evolution 
>  wrote:
> 
> Left unsaid from my reply about enums is that implicit conversions should 
> absolutely be added. We already have this magic for one particular enum, 
> Optional.

+1.  I cover a design to enable this in my value subtyping manifesto.

> 
> I'm not arguing with you that enums are currently unsuitable. In fact I 
> entirely agree. But Chris Lattner and others have said (now I'm paraphrasing, 
> but I believe accurately) that they *should* be. What will it take? At 
> minimum, some way to opt into implicit conversions. It's a no-brainer in my 
> mind.
> 
> Bottom line: the language needs one excellent way to model Foo | Bar | Baz, 
> not two or three mediocre workarounds. The core team has said that they want 
> that excellence to be built through enums. Let's do it.

I would love to hear your thoughts on my value subtyping manifesto which covers 
a plethora of enum enhancements, including everything relevant to and discussed 
in this thread.

That said, there are cases where enums are not appropriate and a closed 
protocol is more appropriate.  Specifically when the set of types is expected 
to evolve over time or is large enough that an enum is a bit unwieldy, but is 
still intended to be controlled by the library.  In these cases you may well 
prefer to use polymorphism rather than switch statements in the implementation. 
 

I see no reason to have "one true way".  Each approach has pros and cons.  An 
engineering tradeoff is required.  The fact that one solution may be the most 
appropriate in the majority of cases is no reason to preclude the alternative 
from being available.  It may be the better choice in a nontrivial minority of 
cases, which is plenty frequently enough to justify its availability.

> 
> 
>> On Sun, Feb 19, 2017 at 21:28 Zach Waldowski via swift-evolution 
>>  wrote:
>>> On Sun, Feb 19, 2017, at 06:40 PM, Xiaodi Wu via swift-evolution wrote:
>> 
>>> On Sun, Feb 19, 2017 at 5:15 PM, Brent Royal-Gordon via swift-evolution 
>>>  wrote:
>>> What is the harm of permitting an outside conformance to `SQLiteValue`?
>> 
>> 
>> I'll put words in Brent's mouth here as an attempt at an answer: you 
>> sometimes need to exclusively switch a downcast of an existential. Consider 
>> a serialization type - or SQLiteValue - where need to treat specific 
>> fundamental types ("primitives") in implementation-dependent ways. In a 
>> theoretical serialization design, all non-primitives would have an explicit 
>> protocol of semantics to conform to support serialization, much like the 
>> stdlib's "Custom" protocol pattern, and you compose from there.
>> 
>> Using an enum to represent this exclusivity remains unconvincing to me, 
>> unless we choose to add implicit conversions to the language. `.int(42)` is 
>> an overwhelming level of duplicate type information in any practical, 
>> non-trivial use case. Yes, (closed) enums model exclusivity. They are not 
>> the only things to do so.
>> 
>> The stdlib alone is reason enough for this feature to exist, even if not 
>> exposed publicly.
>> 
>> Zachary
>> 
>> ___
>> 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] [Draft] open and public protocols

2017-02-19 Thread Xiaodi Wu via swift-evolution
Left unsaid from my reply about enums is that implicit conversions should
absolutely be added. We already have this magic for one particular enum,
Optional.

I'm not arguing with you that enums are currently unsuitable. In fact I
entirely agree. But Chris Lattner and others have said (now I'm
paraphrasing, but I believe accurately) that they *should* be. What will it
take? At minimum, some way to opt into implicit conversions. It's a
no-brainer in my mind.

Bottom line: the language needs one excellent way to model Foo | Bar | Baz,
not two or three mediocre workarounds. The core team has said that they
want that excellence to be built through enums. Let's do it.


On Sun, Feb 19, 2017 at 21:28 Zach Waldowski via swift-evolution <
swift-evolution@swift.org> wrote:

> On Sun, Feb 19, 2017, at 06:40 PM, Xiaodi Wu via swift-evolution wrote:
>
> On Sun, Feb 19, 2017 at 5:15 PM, Brent Royal-Gordon via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> What is the harm of permitting an outside conformance to `SQLiteValue`?
>
>
> I'll put words in Brent's mouth here as an attempt at an answer: you
> sometimes need to exclusively switch a downcast of an existential. Consider
> a serialization type - or SQLiteValue - where need to treat specific
> fundamental types ("primitives") in implementation-dependent ways. In a
> theoretical serialization design, all non-primitives would have an explicit
> protocol of semantics to conform to support serialization, much like the
> stdlib's "Custom" protocol pattern, and you compose from there.
>
> Using an enum to represent this exclusivity remains unconvincing to me,
> unless we choose to add implicit conversions to the language. `.int(42)` is
> an overwhelming level of duplicate type information in any practical,
> non-trivial use case. Yes, (closed) enums model exclusivity. They are not
> the only things to do so.
>
> The stdlib alone is reason enough for this feature to exist, even if not
> exposed publicly.
>
> Zachary
>
> ___
> 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] [Draft] open and public protocols

2017-02-19 Thread David Waite via swift-evolution

> On Feb 19, 2017, at 1:14 AM, Adrian Zubarev  
> wrote:

> Here is a list of hidden and semi-hidden protocols from the standard library 
> that could be closed. Formatted version: 
> https://gist.github.com/DevAndArtist/168c800d784829be536c407311953ab7 
> The 
> majority of this list seems to more likely be non-resilient, appropriate to 
> be hidden rather than being closed. Several of these I believe only exist due 
> to features which are not yet in the Swift language, such as conditional 
> conformances and generalized existentials.

The types in the standard library which I think are relevant to a 
closed-protocol/union-type discussion would be:

CVarArg - interface of types appropriate to withVaList. “Closed” nature already 
enforced by compiler, e.g.;
class FooBar : CVarArg {} //error: type 'FooBar' does not conform to protocol 
‘CVarArg’

AFAICT, there is no reason that a third party type *couldn’t* implement 
CVarArg, other than the requirements of the protocol being considered private 
to the standard library (and possibly non-resilient). A valid protocol 
implementation returns the data (as an [Int] array) that is to be appended to 
the va_list.

MirrorPath - conceptually very similar to the SubscriptParameter, supporting 
String, Int and IntMax types. While the protocol is not closed, 
Mirror.descendent will preconditionFail if a different type other than String, 
Int, or IntMax is passed in.

-DW
 
> 
> 
> 
> 
> 
> -- 
> Adrian Zubarev
> Sent with Airmail
> 
> Am 19. Februar 2017 um 07:59:45, David Waite via swift-evolution 
> (swift-evolution@swift.org ) schrieb:
> 
>> I am unsure if this feature is a good idea. Does someone have a real-world 
>> use for this which isn’t just hiding strong implementation coupling behind a 
>> protocol?
>> 
>> When I consume a protocol, it is under the assumption that the protocol is 
>> documented such that I would be able to work against *any* implementation of 
>> the protocol. With a closed protocol, I would have to assume that there are 
>> significant side effects, either undocumented or difficult for a third party 
>> to duplicate. To my experience, that sounds brittle.
>> 
>> Assuming you aren’t switching on the implementing type of a protocol (which 
>> itself can be a sign that your design isn’t properly using polymorphism), 
>> one could get this design by creating a struct with the interface desired, 
>> and passing invocations through to an internal protocol reference.
>> 
>> -DW
>> 
>> > On Feb 18, 2017, at 1:41 PM, Matthew Johnson via swift-evolution 
>> >  wrote:
>> > 
>> > Now that we’re in phase 2 I’d like to officially propose we introduce 
>> > `open` protocols and require conformances to `public` protocols be inside 
>> > the declaring module. Let’s use this thread for feedback on the official 
>> > proposal. After a healthy round of discussion I’ll open a PR to submit it 
>> > for review.
>> > 
>> > 
>> > # Feature name
>> > 
>> > * Proposal: [SE-](-open-public-protocols.md)
>> > * Authors: [Matthew Johnson](https://github.com/anandabits)
>> > * Review Manager: TBD
>> > * Status: **Awaiting review**
>> > 
>> > ## Introduction
>> > 
>> > This proposal introduces `open protocol` and changes the meaning of 
>> > `public protocol` to match the meaning of `public class` (in this case, 
>> > conformances are only allowed inside the declaring module).
>> > 
>> > The pitch thread leading up to this proposal was: [consistent public 
>> > access 
>> > modifiers](https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170206/031653.html)
>> > 
>> > ## Motivation
>> > 
>> > A general principle the Swift community has adopted for access control is 
>> > that defaults should reserve maximum flexibility for a library. The 
>> > ensures that any capabilities beyond mere visibility are not available 
>> > unless the author of the library has explicitly declared their intent that 
>> > the capabilities be made available. Finally, when it is possible to switch 
>> > from one semantic to another without breaking clients (but not vice-versa) 
>> > we should prefer the more forgiving (i.e. fixable) semantic as the (soft) 
>> > default.
>> > 
>> > `public` is considered a "soft default" in the sense that it is the first 
>> > access modifier a user will reach for when exposing a declaration outside 
>> > of the module. In the case of protocols the current meaning of `public` 
>> > does not meet the principle of preserving maximum flexibility for the 
>> > author of the library. It allows users of the library to conform to the 
>> > protocol.
>> > 
>> > There are good reasons a library may not wish to allow users to add 
>> > conformances to a protocol. For example, it may not wish to expose the 
>> > conforming concrete types. While similar behavior could be accomplished 
>> > with 

Re: [swift-evolution] [Draft] open and public protocols

2017-02-19 Thread David Waite via swift-evolution

> On Feb 19, 2017, at 4:18 PM, Xiaodi Wu via swift-evolution 
>  wrote:
> 
> On Sun, Feb 19, 2017 at 5:10 PM, Adrian Zubarev 
> > 
> wrote:
> Because someInstance["key", .string("key1"), .integer(1), 
> .string(stringKeyInstance), .integer(intIndexInstance), 
> .integer(intIndexInstance), …] is simply ugly and should be hidden. Such API 
> looks horrible.
> 
> I agree. This cries out for improvements to enums. Indeed, I have run into 
> the same issue with this and have a proposal idea saved up regarding 
> anonymous enum cases and subtyping relationships. It would not have been 
> in-scope for phase 1, so I did not write to the list about it. I'm short on 
> time these days, but eventually I'll propose it unless someone else gets to 
> it first. However, this problem does not justify `open` vs. `public`.

Agreed, if the use case is meant for working around the lack of union types, we 
should be very careful in deciding whether the fix should be:
1. Making enums syntactically better for representing union types
2. Adding union types to the language proper, distinct from enums
3. Using a type (such as a closed protocol) to ‘tag’ members of a union type
4. Propose the SubscriptParameter pattern given before as ‘the’ way to solve 
this problem.

Are closed protocols a quick fix or the pattern going forward?

-DW

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


Re: [swift-evolution] [Draft] open and public protocols

2017-02-19 Thread Zach Waldowski via swift-evolution
On Sun, Feb 19, 2017, at 06:40 PM, Xiaodi Wu via swift-evolution wrote:
> On Sun, Feb 19, 2017 at 5:15 PM, Brent Royal-Gordon via swift-
> evolution  wrote:
>> What is the harm of permitting an outside conformance to
>> `SQLiteValue`?


I'll put words in Brent's mouth here as an attempt at an answer: you
sometimes need to exclusively switch a downcast of an existential.
Consider a serialization type - or SQLiteValue - where need to treat
specific fundamental types ("primitives") in implementation-dependent
ways. In a theoretical serialization design, all non-primitives would
have an explicit protocol of semantics to conform to support
serialization, much like the stdlib's "Custom" protocol pattern, and you
compose from there.


Using an enum to represent this exclusivity remains unconvincing to me,
unless we choose to add implicit conversions to the language. `.int(42)`
is an overwhelming level of duplicate type information in any practical,
non-trivial use case. Yes, (closed) enums model exclusivity. They are
not the only things to do so.


The stdlib alone is reason enough for this feature to exist, even if not
exposed publicly.


Zachary


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


Re: [swift-evolution] [Draft] open and public protocols

2017-02-19 Thread Xiaodi Wu via swift-evolution
The reason you should not conform to _ExpressibleByBuiltinIntegerLiteral is
that your type does not conform to the semantics of that protocol.

Every protocol guarantees both syntax and semantics. (Well, almost every
protocol; Error has no syntactic requirements at all, only semantic ones.)
However, the compiler (in general) checks only syntax. For instance, it can
ensure that your Equatable type implements ==, but it cannot check whether
that function actually adheres to the three semantic requirements for
equality.

So, in that light, you can offer an infinite list of examples where you
conform a type to a protocol that others might judge questionable. You
might implement == to check for inequality, and then conform that type to
Equatable. You might name a type Success and conform it to Error. It's a
non-goal for the compiler to stop you. I would imagine (although the core
team should correct me if I'm wrong) that a similar line of reasoning is
why the standard library authors are not extremely bothered that you are
not restrained by the compiler from conforming to
_ExpressibleByBuiltinIntegerLiteral.

It'd be quite the sledgehammer to bring down source-breaking syntax changes
in order to help the compiler enforce one particular semantic requirement,
no?

As to enums, I'm sure you're aware that it's a straw man argument you're
bringing up.
On Sun, Feb 19, 2017 at 18:02 Adrian Zubarev <
adrian.zuba...@devandartist.com> wrote:

> struct A : _ExpressibleByBuiltinIntegerLiteral {
> init() {}
> init(_builtinIntegerLiteral value: _MaxBuiltinIntegerType) {}
> }
>
> struct B : ExpressibleByIntegerLiteral {
> init(integerLiteral value: A) {}
> }
>
> B(integerLiteral: A())
>
> Here is another example. Am I supposed to do that? Definitely not. Your
> lovely question: *Why not?* Because the protocol starts with an
> underscore. So? Doesn’t prevent me from abusing all semi-hidden protocols.
>
> Where is the enum now to stop me from doing this?
>
> Enums are so heavily abused in Swift, just because they have a special
> ability not being extensible with a constructor.
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft] open and public protocols

2017-02-19 Thread Adrian Zubarev via swift-evolution
struct A : _ExpressibleByBuiltinIntegerLiteral {
init() {}
init(_builtinIntegerLiteral value: _MaxBuiltinIntegerType) {}
}

struct B : ExpressibleByIntegerLiteral {
init(integerLiteral value: A) {}
}

B(integerLiteral: A())
Here is another example. Am I supposed to do that? Definitely not. Your lovely 
question: Why not? Because the protocol starts with an underscore. So? Doesn’t 
prevent me from abusing all semi-hidden protocols.

Where is the enum now to stop me from doing this?

Enums are so heavily abused in Swift, just because they have a special ability 
not being extensible with a constructor.___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft] open and public protocols

2017-02-19 Thread Xiaodi Wu via swift-evolution
On Sun, Feb 19, 2017 at 5:55 PM, Adrian Zubarev <
adrian.zuba...@devandartist.com> wrote:

> I don’t see it, can you elaborate a whole proposal first, otherwise I’m
> not convinced. Why?
>

I'm sorry. I'm not sure what you mean. Can you clarify what you'd like to
be more convinced of?


> Am 20. Februar 2017 um 00:51:18, Xiaodi Wu (xiaodi...@gmail.com) schrieb:
>
> On Sun, Feb 19, 2017 at 5:26 PM, Adrian Zubarev <
> adrian.zuba...@devandartist.com> wrote:
>
>> Indeed, I have run into the same issue with this and have a proposal idea
>> saved up regarding anonymous enum cases and subtyping relationships. It
>> would not have been in-scope for phase 1, so I did not write to the list
>> about it. I’m short on time these days, but eventually I’ll propose it
>> unless someone else gets to it first. However, this problem does not
>> justify open vs. public.
>>
>> Why is an anonymous enum case justifying the problem over a closed
>> protocol?
>>
> It's justified because enums are (according to the Swift core team)
> Swift's sum type. That is, when you want something to be "either X or Y"
> (or "one of X, Y, Z, or A"), enums are intended to provide all the
> facilities necessary to express that concisely and with the greatest ease.
> As you recall from discussion about union types, the core team has said
> that in circumstances where that goal is not met (clearly, here), they
> welcome proposals to improve enums so that they serve that use case. That
> is why anonymous enum cases (or some other design to improve the experience
> of using enums as a type for "either X or Y") is justified.
>
> Can an anonymous enum case solve every problem a closed protocol can?
>>
> Perhaps, perhaps not. The point is that you proposed a use case
> purportedly to motivate closed protocols, and I am saying that it is
> insufficient to justify closed protocols because the core team has already
> stated that enums are intended to enable that use case. So it is up to you,
> if you wish to promote this idea, to come up with one or more compelling
> use cases and not for me or others to enumerate every use case for them.
>
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft] open and public protocols

2017-02-19 Thread Adrian Zubarev via swift-evolution
I don’t see it, can you elaborate a whole proposal first, otherwise I’m not 
convinced. Why?

-- 
Adrian Zubarev
Sent with Airmail

Am 20. Februar 2017 um 00:51:18, Xiaodi Wu (xiaodi...@gmail.com) schrieb:

On Sun, Feb 19, 2017 at 5:26 PM, Adrian Zubarev 
 wrote:
Indeed, I have run into the same issue with this and have a proposal idea saved 
up regarding anonymous enum cases and subtyping relationships. It would not 
have been in-scope for phase 1, so I did not write to the list about it. I’m 
short on time these days, but eventually I’ll propose it unless someone else 
gets to it first. However, this problem does not justify open vs. public.

Why is an anonymous enum case justifying the problem over a closed protocol?

It's justified because enums are (according to the Swift core team) Swift's sum 
type. That is, when you want something to be "either X or Y" (or "one of X, Y, 
Z, or A"), enums are intended to provide all the facilities necessary to 
express that concisely and with the greatest ease. As you recall from 
discussion about union types, the core team has said that in circumstances 
where that goal is not met (clearly, here), they welcome proposals to improve 
enums so that they serve that use case. That is why anonymous enum cases (or 
some other design to improve the experience of using enums as a type for 
"either X or Y") is justified.

Can an anonymous enum case solve every problem a closed protocol can?

Perhaps, perhaps not. The point is that you proposed a use case purportedly to 
motivate closed protocols, and I am saying that it is insufficient to justify 
closed protocols because the core team has already stated that enums are 
intended to enable that use case. So it is up to you, if you wish to promote 
this idea, to come up with one or more compelling use cases and not for me or 
others to enumerate every use case for them.___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft] open and public protocols

2017-02-19 Thread Xiaodi Wu via swift-evolution
On Sun, Feb 19, 2017 at 5:26 PM, Adrian Zubarev <
adrian.zuba...@devandartist.com> wrote:

> Indeed, I have run into the same issue with this and have a proposal idea
> saved up regarding anonymous enum cases and subtyping relationships. It
> would not have been in-scope for phase 1, so I did not write to the list
> about it. I’m short on time these days, but eventually I’ll propose it
> unless someone else gets to it first. However, this problem does not
> justify open vs. public.
>
> Why is an anonymous enum case justifying the problem over a closed
> protocol?
>
It's justified because enums are (according to the Swift core team) Swift's
sum type. That is, when you want something to be "either X or Y" (or "one
of X, Y, Z, or A"), enums are intended to provide all the facilities
necessary to express that concisely and with the greatest ease. As you
recall from discussion about union types, the core team has said that in
circumstances where that goal is not met (clearly, here), they welcome
proposals to improve enums so that they serve that use case. That is why
anonymous enum cases (or some other design to improve the experience of
using enums as a type for "either X or Y") is justified.

Can an anonymous enum case solve every problem a closed protocol can?
>
> Perhaps, perhaps not. The point is that you proposed a use case
purportedly to motivate closed protocols, and I am saying that it is
insufficient to justify closed protocols because the core team has already
stated that enums are intended to enable that use case. So it is up to you,
if you wish to promote this idea, to come up with one or more compelling
use cases and not for me or others to enumerate every use case for them.
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft] open and public protocols

2017-02-19 Thread Xiaodi Wu via swift-evolution
On Sun, Feb 19, 2017 at 5:15 PM, Brent Royal-Gordon via swift-evolution <
swift-evolution@swift.org> wrote:

> > On Feb 18, 2017, at 10:58 PM, David Waite via swift-evolution <
> swift-evolution@swift.org> wrote:
> >
> > I am unsure if this feature is a good idea. Does someone have a
> real-world use for this which isn’t just hiding strong implementation
> coupling behind a protocol?
>
> Strong coupling is sometimes inevitable.
>
> In a previous thread, I brought up an example of a place I would use this
> feature: Wrapping the SQLite APIs. For instance:
>
> public protocol SQLiteValue {
> init(statement: SQLiteStatement, columnAt index: Int)
> throws
> func bind(to statement: SQLiteStatement, at index: Int)
> throws
> }
> extension Int: SQLiteValue {
> public init(statement: SQLiteStatement, columnAt index:
> Int) throws {
> self = sqlite3_column_int(statement.stmt, index)
> }
> public func bind(to statement: SQLiteStatement, at index:
> Int) throws {
> try throwIfNotOK(
> sqlite3_bind_int64(statement.stmt, index,
> self)
> )
> }
> }
> extension Double: SQLiteValue {…}
> extension Data: SQLiteValue {…}
> extension String: SQLiteValue {…}
> extension Optional: SQLiteValue where Wrapped: SQLiteValue {…}
>
> This is a case of your hated "strong implementation coupling". But the
> coupling is to a library that ultimately writes data to disk in a portable
> format. Strong coupling here is inevitable.
>
> What is the purpose of permitting outside conformances to `SQLiteValue`?


Suppose you released this library and I used it for my SQLite needs. But my
application uses Float behind the scenes, which can be losslessly promoted
(as you must know) as Double. For convenience of interfacing with your
library, I conform Float to SQLiteValue. Likewise, let's say I implement a
new Rational type (not actually hypothetical, hehe), and I decide that I
want to store that as Double (it'd be precise enough once all the
calculations are done). For convenience, I conform Rational to
SQLiteValue. I could make good on these conformances by having `init()` and
`bind(to:at:)` do a numeric cast and then forward to the relevant methods
on Double. Now, I understand why your library wouldn't do this, since
willy-nilly conversions between types are worth at least careful thought,
but as a non-library client that uses Float pervasively, I'd have good
justification for that extension.

There is no useful way to conform to `SQLiteValue`; the underlying library
> supports certain types, and I've implemented support for those types.
> Allowing outside conformances can only mislead people into fruitlessly
> trying to conform their types, not realizing that the calls they need
> simply aren't exposed.
>

What is the harm of permitting an outside conformance to `SQLiteValue`?


> Moreover, exposing these details unnecessarily freezes the design of
> `SQLiteValue`. If I want to change the design of this parameter handling in
> a future version, well, too bad, the API is public, I'm stuck. *For an API
> I don't intend anyone to conform to publicly in the first place.* That kind
> of sucks, doesn't it?
>

But with `public` vs `open`, your API is still frozen whichever you choose.
Even if you can't conform to `SQLiteValue`, there is no guarantee that your
clients won't _invoke_ `SQLiteValue.bind(to:at:)`, so you can't redesign
the protocol anyway. What other flexibility are you looking for?


>
> --
> 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] [Draft] open and public protocols

2017-02-19 Thread David Hart via swift-evolution
It’s funny. My favourites SQLite library actually does it as I suggested :)

https://github.com/groue/GRDB.swift/blob/master/GRDB/Core/DatabaseValue.swift

> On 20 Feb 2017, at 00:34, David Hart  wrote:
> 
>> 
>> On 20 Feb 2017, at 00:15, Brent Royal-Gordon via swift-evolution 
>>  wrote:
>> 
>>> On Feb 18, 2017, at 10:58 PM, David Waite via swift-evolution 
>>>  wrote:
>>> 
>>> I am unsure if this feature is a good idea. Does someone have a real-world 
>>> use for this which isn’t just hiding strong implementation coupling behind 
>>> a protocol?
>> 
>> Strong coupling is sometimes inevitable.
>> 
>> In a previous thread, I brought up an example of a place I would use this 
>> feature: Wrapping the SQLite APIs. For instance:
>> 
>>  public protocol SQLiteValue {
>>  init(statement: SQLiteStatement, columnAt index: Int) throws
>>  func bind(to statement: SQLiteStatement, at index: Int) throws
>>  }
>>  extension Int: SQLiteValue {
>>  public init(statement: SQLiteStatement, columnAt index: Int) 
>> throws {
>>  self = sqlite3_column_int(statement.stmt, index)
>>  }
>>  public func bind(to statement: SQLiteStatement, at index: Int) 
>> throws {
>>  try throwIfNotOK(
>>  sqlite3_bind_int64(statement.stmt, index, self)
>>  )
>>  }
>>  }
>>  extension Double: SQLiteValue {…}
>>  extension Data: SQLiteValue {…}
>>  extension String: SQLiteValue {…}
>>  extension Optional: SQLiteValue where Wrapped: SQLiteValue {…}
> 
> That problem is that I don’t think the API should be written this way. This 
> cries for the use of enums instead:
> 
> enum SQLiteValue {
>case int(Int)
>case double(Double)
>case data(Data)
>case string(String)
> }
> 
> protocol SQLiteValueConvertible {
>var sqliteValue: SQLiteValue { get }
> }
> 
> extension Int : SQLiteValueConvertible {
>var sqliteValue: SQLiteValue { return .int(self) }
> }
> 
> And that API actually allows interesting extension points. For example, how 
> about automatic binding of dates:
> 
> extension Date : SQLiteValueConvertible {
>var sqliteValue: SQLiteValue { return .double(timeIntervalSince1970) }
> }
> 
> I keep getting the impression that the uses for the proposals are actually 
> cases where an enum is required.
> 
>> This is a case of your hated "strong implementation coupling". But the 
>> coupling is to a library that ultimately writes data to disk in a portable 
>> format. Strong coupling here is inevitable.
>> 
>> What is the purpose of permitting outside conformances to `SQLiteValue`? 
>> There is no useful way to conform to `SQLiteValue`; the underlying library 
>> supports certain types, and I've implemented support for those types. 
>> Allowing outside conformances can only mislead people into fruitlessly 
>> trying to conform their types, not realizing that the calls they need simply 
>> aren't exposed.
>> 
>> Moreover, exposing these details unnecessarily freezes the design of 
>> `SQLiteValue`. If I want to change the design of this parameter handling in 
>> a future version, well, too bad, the API is public, I'm stuck. *For an API I 
>> don't intend anyone to conform to publicly in the first place.* That kind of 
>> sucks, doesn't it?
>> 
>> -- 
>> 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] [Draft] open and public protocols

2017-02-19 Thread David Hart via swift-evolution

> On 20 Feb 2017, at 00:15, Brent Royal-Gordon via swift-evolution 
>  wrote:
> 
>> On Feb 18, 2017, at 10:58 PM, David Waite via swift-evolution 
>>  wrote:
>> 
>> I am unsure if this feature is a good idea. Does someone have a real-world 
>> use for this which isn’t just hiding strong implementation coupling behind a 
>> protocol?
> 
> Strong coupling is sometimes inevitable.
> 
> In a previous thread, I brought up an example of a place I would use this 
> feature: Wrapping the SQLite APIs. For instance:
> 
>   public protocol SQLiteValue {
>   init(statement: SQLiteStatement, columnAt index: Int) throws
>   func bind(to statement: SQLiteStatement, at index: Int) throws
>   }
>   extension Int: SQLiteValue {
>   public init(statement: SQLiteStatement, columnAt index: Int) 
> throws {
>   self = sqlite3_column_int(statement.stmt, index)
>   }
>   public func bind(to statement: SQLiteStatement, at index: Int) 
> throws {
>   try throwIfNotOK(
>   sqlite3_bind_int64(statement.stmt, index, self)
>   )
>   }
>   }
>   extension Double: SQLiteValue {…}
>   extension Data: SQLiteValue {…}
>   extension String: SQLiteValue {…}
>   extension Optional: SQLiteValue where Wrapped: SQLiteValue {…}

That problem is that I don’t think the API should be written this way. This 
cries for the use of enums instead:

enum SQLiteValue {
case int(Int)
case double(Double)
case data(Data)
case string(String)
}

protocol SQLiteValueConvertible {
var sqliteValue: SQLiteValue { get }
}

extension Int : SQLiteValueConvertible {
var sqliteValue: SQLiteValue { return .int(self) }
}

And that API actually allows interesting extension points. For example, how 
about automatic binding of dates:

extension Date : SQLiteValueConvertible {
var sqliteValue: SQLiteValue { return .double(timeIntervalSince1970) }
}

I keep getting the impression that the uses for the proposals are actually 
cases where an enum is required.

> This is a case of your hated "strong implementation coupling". But the 
> coupling is to a library that ultimately writes data to disk in a portable 
> format. Strong coupling here is inevitable.
> 
> What is the purpose of permitting outside conformances to `SQLiteValue`? 
> There is no useful way to conform to `SQLiteValue`; the underlying library 
> supports certain types, and I've implemented support for those types. 
> Allowing outside conformances can only mislead people into fruitlessly trying 
> to conform their types, not realizing that the calls they need simply aren't 
> exposed.
> 
> Moreover, exposing these details unnecessarily freezes the design of 
> `SQLiteValue`. If I want to change the design of this parameter handling in a 
> future version, well, too bad, the API is public, I'm stuck. *For an API I 
> don't intend anyone to conform to publicly in the first place.* That kind of 
> sucks, doesn't it?
> 
> -- 
> 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] [Draft] open and public protocols

2017-02-19 Thread Adrian Zubarev via swift-evolution
Because it’s not up to the client to decide how the design of the API supposed 
to work.

-- 
Adrian Zubarev
Sent with Airmail

Am 20. Februar 2017 um 00:28:38, David Hart (da...@hartbit.com) schrieb:


On 20 Feb 2017, at 00:19, Adrian Zubarev  
wrote:

I’m polite but I don’t see why every single piece is questioned with “why”.

Your example is exactly the workaround I presented in first place. Interesting 
right? But it still fails the challenge, because the set of types can be 
extended by the client, however at least with this there won’t be any runtime 
crashes in Swift 3.X

In this example, I don’t see why it’s a problem to have types be extended by 
the client:

struct Person {
    let firstName: String
    let lastName: String
    let id: String
}

extension Person : KeyConvertible {
    var key: Key {
        return .string(id)
    }
}

-- 
Adrian Zubarev
Sent with Airmail

Am 20. Februar 2017 um 00:14:28, David Hart (da...@hartbit.com) schrieb:


On 20 Feb 2017, at 00:10, Adrian Zubarev via swift-evolution 
 wrote:

Because someInstance["key", .string("key1"), .integer(1), 
.string(stringKeyInstance), .integer(intIndexInstance), 
.integer(intIndexInstance), …] is simply ugly and should be hidden. Such API 
looks horrible.

Is this discussion really going to end with every statement being questioned 
with “why”? Why is 42 the number that rules the universe?

Lets stay polite and keep things civil.

The "the client should not be able to extend the set of types you can pass to 
that subscript.” requirement seems totally arbitrary and an anti-pattern. I’m 
perfectly happy with:

enum Key {
    case string(String)
    case int(Int)
}

protocol KeyConvertible {
    var key: Key { get }
}

subscript(initial: String, others: KeyConvertible...) -> Foo

-- 
Adrian Zubarev
Sent with Airmail

Am 20. Februar 2017 um 00:03:44, Xiaodi Wu (xiaodi...@gmail.com) schrieb:

On Sun, Feb 19, 2017 at 4:51 PM, Adrian Zubarev 
 wrote:
Matthew has pretty much summed up everything with a single question in his last 
reply. It makes me tired of repeating myself over and over again.

Here’s the challenge for you:

Implement a subscript where the first parameter is a String (trivial), but the 
second to n are String’s and/or Int’s. There is no restriction of order for the 
Int’s and String’s and there could be as many as you’d like, so no overloads 
are allowed (a hint: variadics). You should be able to use variables in that 
subscript and literals. You’re not allowed to use enum constructors

Why not? You want a parameter that takes either String or Int. In another 
language, you might express this as `String | Int`, but Chris Lattner and 
others have said on this list that enums are the intended way of expressing 
this in Swift.
and the client should not be able to extend the set of types you can pass to 
that subscript. That said it can look like this: someInstance["key", "key1", 1, 
stringKeyInstance, intIndexInstance, intIndexInstance, …]

Creating hacks like unreachable types with hidden inits is prohibited.

Have fun!



-- 
Adrian Zubarev
Sent with Airmail

Am 19. Februar 2017 um 23:25:11, Xiaodi Wu (xiaodi...@gmail.com) schrieb:

Sorry, I have read through this thread twice and do not understand the point 
you are making. Can you explain your example once more?

Specifically, I do not understand why it is that your code should have problems 
with third-party types that conform to your protocol. If your protocol has 
requirements that third-party types cannot fulfill, then naturally those 
requirements will prevent a third-party from conforming new types to your 
protocol. OTOH, if your protocol does not have any requirements that 
third-party types cannot fulfill, then your code that accepts anything that 
conforms to your protocol should be indifferent to whether the conforming type 
is defined by you or someone else. After all, a conforming type would fulfill 
all the semantic and syntactic requirements of the protocol! If your protocol 
has requirements that you are unable to state in code, causing third-party 
types to conform that really shouldn't, then that is a case for additional 
features that allow you to express those requirements more accurately, not an 
argument for having protocols that can't be conformed to by a third-party. What 
am I missing?


On Sun, Feb 19, 2017 at 11:53 AM, Adrian Zubarev via swift-evolution 
 wrote:
That’s the whole point I was making. :) Thank you Matthew. That makes my 
example a real world example and not just some bike shedding.

-- 
Adrian Zubarev
Sent with Airmail

Am 19. Februar 2017 um 18:50:31, Matthew Johnson (matt...@anandabits.com) 
schrieb:



Sent from my iPad

On Feb 19, 2017, at 11:29 AM, David Waite via swift-evolution 
 wrote:

Just FYI, I solved this issue in my own library (which included a json jpointer 

Re: [swift-evolution] [Draft] open and public protocols

2017-02-19 Thread David Hart via swift-evolution

> On 20 Feb 2017, at 00:19, Adrian Zubarev  
> wrote:
> 
> I’m polite but I don’t see why every single piece is questioned with “why”.
> 
> Your example is exactly the workaround I presented in first place. 
> Interesting right? But it still fails the challenge, because the set of types 
> can be extended by the client, however at least with this there won’t be any 
> runtime crashes in Swift 3.X
> 
In this example, I don’t see why it’s a problem to have types be extended by 
the client:

struct Person {
let firstName: String
let lastName: String
let id: String
}

extension Person : KeyConvertible {
var key: Key {
return .string(id)
}
}

> -- 
> Adrian Zubarev
> Sent with Airmail
> 
> Am 20. Februar 2017 um 00:14:28, David Hart (da...@hartbit.com 
> ) schrieb:
> 
>> 
>>> On 20 Feb 2017, at 00:10, Adrian Zubarev via swift-evolution 
>>> > wrote:
>>> 
>>> Because someInstance["key", .string("key1"), .integer(1), 
>>> .string(stringKeyInstance), .integer(intIndexInstance), 
>>> .integer(intIndexInstance), …] is simply ugly and should be hidden. Such 
>>> API looks horrible.
>>> 
>>> Is this discussion really going to end with every statement being 
>>> questioned with “why”? Why is 42 the number that rules the universe?
>>> 
>> Lets stay polite and keep things civil.
>> 
>> The "the client should not be able to extend the set of types you can pass 
>> to that subscript.” requirement seems totally arbitrary and an anti-pattern. 
>> I’m perfectly happy with:
>> 
>> enum Key {
>> case string(String)
>> case int(Int)
>> }
>> 
>> protocol KeyConvertible {
>> var key: Key { get }
>> }
>> 
>> subscript(initial: String, others: KeyConvertible...) -> Foo
>> 
>>> -- 
>>> Adrian Zubarev
>>> Sent with Airmail
>>> 
>>> Am 20. Februar 2017 um 00:03:44, Xiaodi Wu (xiaodi...@gmail.com 
>>> ) schrieb:
>>> 
 On Sun, Feb 19, 2017 at 4:51 PM, Adrian Zubarev 
 > 
 wrote:
 Matthew has pretty much summed up everything with a single question in his 
 last reply. It makes me tired of repeating myself over and over again.
 
 Here’s the challenge for you:
 
 Implement a subscript where the first parameter is a String (trivial), but 
 the second to n are String’s and/or Int’s. There is no restriction of 
 order for the Int’s and String’s and there could be as many as you’d like, 
 so no overloads are allowed (a hint: variadics). You should be able to use 
 variables in that subscript and literals. You’re not allowed to use enum 
 constructors
 
 Why not? You want a parameter that takes either String or Int. In another 
 language, you might express this as `String | Int`, but Chris Lattner and 
 others have said on this list that enums are the intended way of 
 expressing this in Swift.
 and the client should not be able to extend the set of types you can pass 
 to that subscript. That said it can look like this: someInstance["key", 
 "key1", 1, stringKeyInstance, intIndexInstance, intIndexInstance, …]
 
 Creating hacks like unreachable types with hidden inits is prohibited.
 
 Have fun!
 
 
 
 -- 
 Adrian Zubarev
 Sent with Airmail
 
 Am 19. Februar 2017 um 23:25:11, Xiaodi Wu (xiaodi...@gmail.com 
 ) schrieb:
 
> Sorry, I have read through this thread twice and do not understand the 
> point you are making. Can you explain your example once more?
> 
> Specifically, I do not understand why it is that your code should have 
> problems with third-party types that conform to your protocol. If your 
> protocol has requirements that third-party types cannot fulfill, then 
> naturally those requirements will prevent a third-party from conforming 
> new types to your protocol. OTOH, if your protocol does not have any 
> requirements that third-party types cannot fulfill, then your code that 
> accepts anything that conforms to your protocol should be indifferent to 
> whether the conforming type is defined by you or someone else. After all, 
> a conforming type would fulfill all the semantic and syntactic 
> requirements of the protocol! If your protocol has requirements that you 
> are unable to state in code, causing third-party types to conform that 
> really shouldn't, then that is a case for additional features that allow 
> you to express those requirements more accurately, not an argument for 
> having protocols that can't be conformed to by a third-party. What am I 
> missing?
> 
> 
> On Sun, Feb 19, 2017 at 11:53 AM, Adrian Zubarev via swift-evolution 
> > 

Re: [swift-evolution] [Draft] open and public protocols

2017-02-19 Thread Adrian Zubarev via swift-evolution
Indeed, I have run into the same issue with this and have a proposal idea saved 
up regarding anonymous enum cases and subtyping relationships. It would not 
have been in-scope for phase 1, so I did not write to the list about it. I’m 
short on time these days, but eventually I’ll propose it unless someone else 
gets to it first. However, this problem does not justify open vs. public.
Why is an anonymous enum case justifying the problem over a closed protocol? 
Can an anonymous enum case solve every problem a closed protocol can?

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


Re: [swift-evolution] [Draft] open and public protocols

2017-02-19 Thread Adrian Zubarev via swift-evolution
Indeed, I have run into the same issue with this and have a proposal idea saved 
up regarding anonymous enum cases and subtyping relationships. It would not 
have been in-scope for phase 1, so I did not write to the list about it. I’m 
short on time these days, but eventually I’ll propose it unless someone else 
gets to it first. However, this problem does not justify open vs. public.
Why is an anonymous enum case justifying the problem over a closed protocol?

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


Re: [swift-evolution] [Draft] open and public protocols

2017-02-19 Thread Adrian Zubarev via swift-evolution
I’m polite but I don’t see why every single piece is questioned with “why”.

Your example is exactly the workaround I presented in first place. Interesting 
right? But it still fails the challenge, because the set of types can be 
extended by the client, however at least with this there won’t be any runtime 
crashes in Swift 3.X.



-- 
Adrian Zubarev
Sent with Airmail

Am 20. Februar 2017 um 00:14:28, David Hart (da...@hartbit.com) schrieb:


On 20 Feb 2017, at 00:10, Adrian Zubarev via swift-evolution 
 wrote:

Because someInstance["key", .string("key1"), .integer(1), 
.string(stringKeyInstance), .integer(intIndexInstance), 
.integer(intIndexInstance), …] is simply ugly and should be hidden. Such API 
looks horrible.

Is this discussion really going to end with every statement being questioned 
with “why”? Why is 42 the number that rules the universe?

Lets stay polite and keep things civil.

The "the client should not be able to extend the set of types you can pass to 
that subscript.” requirement seems totally arbitrary and an anti-pattern. I’m 
perfectly happy with:

enum Key {
    case string(String)
    case int(Int)
}

protocol KeyConvertible {
    var key: Key { get }
}

subscript(initial: String, others: KeyConvertible...) -> Foo

-- 
Adrian Zubarev
Sent with Airmail

Am 20. Februar 2017 um 00:03:44, Xiaodi Wu (xiaodi...@gmail.com) schrieb:

On Sun, Feb 19, 2017 at 4:51 PM, Adrian Zubarev 
 wrote:
Matthew has pretty much summed up everything with a single question in his last 
reply. It makes me tired of repeating myself over and over again.

Here’s the challenge for you:

Implement a subscript where the first parameter is a String (trivial), but the 
second to n are String’s and/or Int’s. There is no restriction of order for the 
Int’s and String’s and there could be as many as you’d like, so no overloads 
are allowed (a hint: variadics). You should be able to use variables in that 
subscript and literals. You’re not allowed to use enum constructors

Why not? You want a parameter that takes either String or Int. In another 
language, you might express this as `String | Int`, but Chris Lattner and 
others have said on this list that enums are the intended way of expressing 
this in Swift.
and the client should not be able to extend the set of types you can pass to 
that subscript. That said it can look like this: someInstance["key", "key1", 1, 
stringKeyInstance, intIndexInstance, intIndexInstance, …]

Creating hacks like unreachable types with hidden inits is prohibited.

Have fun!



-- 
Adrian Zubarev
Sent with Airmail

Am 19. Februar 2017 um 23:25:11, Xiaodi Wu (xiaodi...@gmail.com) schrieb:

Sorry, I have read through this thread twice and do not understand the point 
you are making. Can you explain your example once more?

Specifically, I do not understand why it is that your code should have problems 
with third-party types that conform to your protocol. If your protocol has 
requirements that third-party types cannot fulfill, then naturally those 
requirements will prevent a third-party from conforming new types to your 
protocol. OTOH, if your protocol does not have any requirements that 
third-party types cannot fulfill, then your code that accepts anything that 
conforms to your protocol should be indifferent to whether the conforming type 
is defined by you or someone else. After all, a conforming type would fulfill 
all the semantic and syntactic requirements of the protocol! If your protocol 
has requirements that you are unable to state in code, causing third-party 
types to conform that really shouldn't, then that is a case for additional 
features that allow you to express those requirements more accurately, not an 
argument for having protocols that can't be conformed to by a third-party. What 
am I missing?


On Sun, Feb 19, 2017 at 11:53 AM, Adrian Zubarev via swift-evolution 
 wrote:
That’s the whole point I was making. :) Thank you Matthew. That makes my 
example a real world example and not just some bike shedding.

-- 
Adrian Zubarev
Sent with Airmail

Am 19. Februar 2017 um 18:50:31, Matthew Johnson (matt...@anandabits.com) 
schrieb:



Sent from my iPad

On Feb 19, 2017, at 11:29 AM, David Waite via swift-evolution 
 wrote:

Just FYI, I solved this issue in my own library (which included a json jpointer 
implementation) via:

public enum SubscriptParameter {
  case string(String)
  case int(Int)
}

extension SubscriptParameter : ExpressibleByIntegerLiteral {
  public init(integerLiteral value: Int) {
    self = .int(value)
  }
}

extension SubscriptParameter : ExpressibleByStringLiteral {
  public init(stringLiteral value: String) {
    self = .string(value)
  }
  public init(extendedGraphemeClusterLiteral value: String) {
    self.init(stringLiteral: value)
  }
  public init(unicodeScalarLiteral value: String) {
    self.init(stringLiteral: value)
  }
}


Re: [swift-evolution] [Draft] open and public protocols

2017-02-19 Thread Xiaodi Wu via swift-evolution
On Sun, Feb 19, 2017 at 5:10 PM, Adrian Zubarev <
adrian.zuba...@devandartist.com> wrote:

> Because someInstance["key", .string("key1"), .integer(1),
> .string(stringKeyInstance), .integer(intIndexInstance),
> .integer(intIndexInstance), …] is simply ugly and should be hidden. Such
> API looks horrible.
>
I agree. This cries out for improvements to enums. Indeed, I have run into
the same issue with this and have a proposal idea saved up regarding
anonymous enum cases and subtyping relationships. It would not have been
in-scope for phase 1, so I did not write to the list about it. I'm short on
time these days, but eventually I'll propose it unless someone else gets to
it first. However, this problem does not justify `open` vs. `public`.


> Is this discussion really going to end with every statement being
> questioned with “why”?
>
Why not?


> Why is 42 the number that rules the universe?
>
Surely, it is for the same reason that May 25 is Towel Day.


> --
> Adrian Zubarev
> Sent with Airmail
>
> Am 20. Februar 2017 um 00:03:44, Xiaodi Wu (xiaodi...@gmail.com) schrieb:
>
> On Sun, Feb 19, 2017 at 4:51 PM, Adrian Zubarev <
> adrian.zuba...@devandartist.com> wrote:
>
>> Matthew has pretty much summed up everything with a single question in
>> his last reply. It makes me tired of repeating myself over and over again.
>>
>> Here’s the challenge for you:
>>
>> Implement a subscript where the first parameter is a String (trivial),
>> but the second to n are String’s and/or Int’s. There is no restriction of
>> order for the Int’s and String’s and there could be as many as you’d like,
>> so no overloads are allowed (a hint: variadics). You should be able to use
>> variables in that subscript and literals. You’re not allowed to use enum
>> constructors
>>
> Why not? You want a parameter that takes either String or Int. In another
> language, you might express this as `String | Int`, but Chris Lattner and
> others have said on this list that enums are the intended way of expressing
> this in Swift.
>
>> and the client should not be able to extend the set of types you can pass
>> to that subscript. That said it can look like this: someInstance["key",
>> "key1", 1, stringKeyInstance, intIndexInstance, intIndexInstance, …]
>>
>> Creating hacks like unreachable types with hidden inits is prohibited.
>>
>> Have fun!
>>
>>
>> --
>> Adrian Zubarev
>> Sent with Airmail
>>
>> Am 19. Februar 2017 um 23:25:11, Xiaodi Wu (xiaodi...@gmail.com) schrieb:
>>
>> Sorry, I have read through this thread twice and do not understand the
>> point you are making. Can you explain your example once more?
>>
>> Specifically, I do not understand why it is that your code should have
>> problems with third-party types that conform to your protocol. If your
>> protocol has requirements that third-party types cannot fulfill, then
>> naturally those requirements will prevent a third-party from conforming new
>> types to your protocol. OTOH, if your protocol does not have any
>> requirements that third-party types cannot fulfill, then your code that
>> accepts anything that conforms to your protocol should be indifferent to
>> whether the conforming type is defined by you or someone else. After all, a
>> conforming type would fulfill all the semantic and syntactic requirements
>> of the protocol! If your protocol has requirements that you are unable to
>> state in code, causing third-party types to conform that really shouldn't,
>> then that is a case for additional features that allow you to express those
>> requirements more accurately, not an argument for having protocols that
>> can't be conformed to by a third-party. What am I missing?
>>
>>
>> On Sun, Feb 19, 2017 at 11:53 AM, Adrian Zubarev via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>>> That’s the whole point I was making. :) Thank you Matthew. That makes my
>>> example a real world example and not just some bike shedding.
>>>
>>> --
>>> Adrian Zubarev
>>> Sent with Airmail
>>>
>>> Am 19. Februar 2017 um 18:50:31, Matthew Johnson (matt...@anandabits.com)
>>> schrieb:
>>>
>>>
>>>
>>> Sent from my iPad
>>>
>>> On Feb 19, 2017, at 11:29 AM, David Waite via swift-evolution <
>>> swift-evolution@swift.org> wrote:
>>>
>>> Just FYI, I solved this issue in my own library (which included a json
>>> jpointer implementation) via:
>>>
>>> public enum SubscriptParameter {
>>>   case string(String)
>>>   case int(Int)
>>> }
>>>
>>> extension SubscriptParameter : ExpressibleByIntegerLiteral {
>>>   public init(integerLiteral value: Int) {
>>> self = .int(value)
>>>   }
>>> }
>>>
>>> extension SubscriptParameter : ExpressibleByStringLiteral {
>>>   public init(stringLiteral value: String) {
>>> self = .string(value)
>>>   }
>>>   public init(extendedGraphemeClusterLiteral value: String) {
>>> self.init(stringLiteral: value)
>>>   }
>>>
>>>   public init(unicodeScalarLiteral value: String) {
>>> self.init(stringLiteral: value)
>>>   }
>>> }
>>>
>>> extension 

Re: [swift-evolution] [Draft] open and public protocols

2017-02-19 Thread Brent Royal-Gordon via swift-evolution
> On Feb 18, 2017, at 10:58 PM, David Waite via swift-evolution 
>  wrote:
> 
> I am unsure if this feature is a good idea. Does someone have a real-world 
> use for this which isn’t just hiding strong implementation coupling behind a 
> protocol?

Strong coupling is sometimes inevitable.

In a previous thread, I brought up an example of a place I would use this 
feature: Wrapping the SQLite APIs. For instance:

public protocol SQLiteValue {
init(statement: SQLiteStatement, columnAt index: Int) throws
func bind(to statement: SQLiteStatement, at index: Int) throws
}
extension Int: SQLiteValue {
public init(statement: SQLiteStatement, columnAt index: Int) 
throws {
self = sqlite3_column_int(statement.stmt, index)
}
public func bind(to statement: SQLiteStatement, at index: Int) 
throws {
try throwIfNotOK(
sqlite3_bind_int64(statement.stmt, index, self)
)
}
}
extension Double: SQLiteValue {…}
extension Data: SQLiteValue {…}
extension String: SQLiteValue {…}
extension Optional: SQLiteValue where Wrapped: SQLiteValue {…}

This is a case of your hated "strong implementation coupling". But the coupling 
is to a library that ultimately writes data to disk in a portable format. 
Strong coupling here is inevitable.

What is the purpose of permitting outside conformances to `SQLiteValue`? There 
is no useful way to conform to `SQLiteValue`; the underlying library supports 
certain types, and I've implemented support for those types. Allowing outside 
conformances can only mislead people into fruitlessly trying to conform their 
types, not realizing that the calls they need simply aren't exposed.

Moreover, exposing these details unnecessarily freezes the design of 
`SQLiteValue`. If I want to change the design of this parameter handling in a 
future version, well, too bad, the API is public, I'm stuck. *For an API I 
don't intend anyone to conform to publicly in the first place.* That kind of 
sucks, doesn't it?

-- 
Brent Royal-Gordon
Architechies

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


Re: [swift-evolution] [Draft] open and public protocols

2017-02-19 Thread David Hart via swift-evolution

> On 20 Feb 2017, at 00:10, Adrian Zubarev via swift-evolution 
>  wrote:
> 
> Because someInstance["key", .string("key1"), .integer(1), 
> .string(stringKeyInstance), .integer(intIndexInstance), 
> .integer(intIndexInstance), …] is simply ugly and should be hidden. Such API 
> looks horrible.
> 
> Is this discussion really going to end with every statement being questioned 
> with “why”? Why is 42 the number that rules the universe?
> 
Lets stay polite and keep things civil.

The "the client should not be able to extend the set of types you can pass to 
that subscript.” requirement seems totally arbitrary and an anti-pattern. I’m 
perfectly happy with:

enum Key {
case string(String)
case int(Int)
}

protocol KeyConvertible {
var key: Key { get }
}

subscript(initial: String, others: KeyConvertible...) -> Foo

> -- 
> Adrian Zubarev
> Sent with Airmail
> 
> Am 20. Februar 2017 um 00:03:44, Xiaodi Wu (xiaodi...@gmail.com 
> ) schrieb:
> 
>> On Sun, Feb 19, 2017 at 4:51 PM, Adrian Zubarev 
>> > 
>> wrote:
>> Matthew has pretty much summed up everything with a single question in his 
>> last reply. It makes me tired of repeating myself over and over again.
>> 
>> Here’s the challenge for you:
>> 
>> Implement a subscript where the first parameter is a String (trivial), but 
>> the second to n are String’s and/or Int’s. There is no restriction of order 
>> for the Int’s and String’s and there could be as many as you’d like, so no 
>> overloads are allowed (a hint: variadics). You should be able to use 
>> variables in that subscript and literals. You’re not allowed to use enum 
>> constructors
>> 
>> Why not? You want a parameter that takes either String or Int. In another 
>> language, you might express this as `String | Int`, but Chris Lattner and 
>> others have said on this list that enums are the intended way of expressing 
>> this in Swift.
>> and the client should not be able to extend the set of types you can pass to 
>> that subscript. That said it can look like this: someInstance["key", "key1", 
>> 1, stringKeyInstance, intIndexInstance, intIndexInstance, …]
>> 
>> Creating hacks like unreachable types with hidden inits is prohibited.
>> 
>> Have fun!
>> 
>> 
>> 
>> -- 
>> Adrian Zubarev
>> Sent with Airmail
>> 
>> Am 19. Februar 2017 um 23:25:11, Xiaodi Wu (xiaodi...@gmail.com 
>> ) schrieb:
>> 
>>> Sorry, I have read through this thread twice and do not understand the 
>>> point you are making. Can you explain your example once more?
>>> 
>>> Specifically, I do not understand why it is that your code should have 
>>> problems with third-party types that conform to your protocol. If your 
>>> protocol has requirements that third-party types cannot fulfill, then 
>>> naturally those requirements will prevent a third-party from conforming new 
>>> types to your protocol. OTOH, if your protocol does not have any 
>>> requirements that third-party types cannot fulfill, then your code that 
>>> accepts anything that conforms to your protocol should be indifferent to 
>>> whether the conforming type is defined by you or someone else. After all, a 
>>> conforming type would fulfill all the semantic and syntactic requirements 
>>> of the protocol! If your protocol has requirements that you are unable to 
>>> state in code, causing third-party types to conform that really shouldn't, 
>>> then that is a case for additional features that allow you to express those 
>>> requirements more accurately, not an argument for having protocols that 
>>> can't be conformed to by a third-party. What am I missing?
>>> 
>>> 
>>> On Sun, Feb 19, 2017 at 11:53 AM, Adrian Zubarev via swift-evolution 
>>> > wrote:
>>> That’s the whole point I was making. :) Thank you Matthew. That makes my 
>>> example a real world example and not just some bike shedding.
>>> 
>>> -- 
>>> Adrian Zubarev
>>> Sent with Airmail
>>> 
>>> Am 19. Februar 2017 um 18:50:31, Matthew Johnson (matt...@anandabits.com 
>>> ) schrieb:
>>> 
 
 
 Sent from my iPad
 
 On Feb 19, 2017, at 11:29 AM, David Waite via swift-evolution 
 > wrote:
 
> Just FYI, I solved this issue in my own library (which included a json 
> jpointer implementation) via:
> 
> public enum SubscriptParameter {
>   case string(String)
>   case int(Int)
> }
> 
> extension SubscriptParameter : ExpressibleByIntegerLiteral {
>   public init(integerLiteral value: Int) {
> self = .int(value)
>   }
> }
> 
> extension SubscriptParameter : ExpressibleByStringLiteral {
>   public init(stringLiteral value: String) {
> self = .string(value)
>   }
>   public 

Re: [swift-evolution] [Draft] open and public protocols

2017-02-19 Thread Adrian Zubarev via swift-evolution
Because someInstance["key", .string("key1"), .integer(1), 
.string(stringKeyInstance), .integer(intIndexInstance), 
.integer(intIndexInstance), …] is simply ugly and should be hidden. Such API 
looks horrible.

Is this discussion really going to end with every statement being questioned 
with “why”? Why is 42 the number that rules the universe?



-- 
Adrian Zubarev
Sent with Airmail

Am 20. Februar 2017 um 00:03:44, Xiaodi Wu (xiaodi...@gmail.com) schrieb:

On Sun, Feb 19, 2017 at 4:51 PM, Adrian Zubarev 
 wrote:
Matthew has pretty much summed up everything with a single question in his last 
reply. It makes me tired of repeating myself over and over again.

Here’s the challenge for you:

Implement a subscript where the first parameter is a String (trivial), but the 
second to n are String’s and/or Int’s. There is no restriction of order for the 
Int’s and String’s and there could be as many as you’d like, so no overloads 
are allowed (a hint: variadics). You should be able to use variables in that 
subscript and literals. You’re not allowed to use enum constructors

Why not? You want a parameter that takes either String or Int. In another 
language, you might express this as `String | Int`, but Chris Lattner and 
others have said on this list that enums are the intended way of expressing 
this in Swift.
and the client should not be able to extend the set of types you can pass to 
that subscript. That said it can look like this: someInstance["key", "key1", 1, 
stringKeyInstance, intIndexInstance, intIndexInstance, …]

Creating hacks like unreachable types with hidden inits is prohibited.

Have fun!



-- 
Adrian Zubarev
Sent with Airmail

Am 19. Februar 2017 um 23:25:11, Xiaodi Wu (xiaodi...@gmail.com) schrieb:

Sorry, I have read through this thread twice and do not understand the point 
you are making. Can you explain your example once more?

Specifically, I do not understand why it is that your code should have problems 
with third-party types that conform to your protocol. If your protocol has 
requirements that third-party types cannot fulfill, then naturally those 
requirements will prevent a third-party from conforming new types to your 
protocol. OTOH, if your protocol does not have any requirements that 
third-party types cannot fulfill, then your code that accepts anything that 
conforms to your protocol should be indifferent to whether the conforming type 
is defined by you or someone else. After all, a conforming type would fulfill 
all the semantic and syntactic requirements of the protocol! If your protocol 
has requirements that you are unable to state in code, causing third-party 
types to conform that really shouldn't, then that is a case for additional 
features that allow you to express those requirements more accurately, not an 
argument for having protocols that can't be conformed to by a third-party. What 
am I missing?


On Sun, Feb 19, 2017 at 11:53 AM, Adrian Zubarev via swift-evolution 
 wrote:
That’s the whole point I was making. :) Thank you Matthew. That makes my 
example a real world example and not just some bike shedding.

-- 
Adrian Zubarev
Sent with Airmail

Am 19. Februar 2017 um 18:50:31, Matthew Johnson (matt...@anandabits.com) 
schrieb:



Sent from my iPad

On Feb 19, 2017, at 11:29 AM, David Waite via swift-evolution 
 wrote:

Just FYI, I solved this issue in my own library (which included a json jpointer 
implementation) via:

public enum SubscriptParameter {
  case string(String)
  case int(Int)
}

extension SubscriptParameter : ExpressibleByIntegerLiteral {
  public init(integerLiteral value: Int) {
    self = .int(value)
  }
}

extension SubscriptParameter : ExpressibleByStringLiteral {
  public init(stringLiteral value: String) {
    self = .string(value)
  }
  public init(extendedGraphemeClusterLiteral value: String) {
    self.init(stringLiteral: value)
  }
  public init(unicodeScalarLiteral value: String) {
    self.init(stringLiteral: value)
  }
}

extension SubscriptParameter : CustomStringConvertible {
  public var description: String {
    switch self {
    case .string(let str):
      return "\"\(str)\""
    case .int(let i):
      return String(i)
    }
  }
}

func debug(_ path:SubscriptParameter...) {
  print("path is \(path)")
}

debug(1, "foo", 2, "bar”) // path is [1, “foo”, 2, “bar”]

Can you make this work with variables - not just literals - and still prevent 
users from extending the set of types and without requiring an enum case 
constructor to be used by clients?



On Feb 19, 2017, at 1:14 AM, Adrian Zubarev  
wrote:

If you haven’t followed the other thread Matthew previously opened than you 
have missed the example I showed there.

Here it is again:

public protocol SubscriptParameterType {
 
// This property was needed to prevent the client from breaking
// the library by conforming to the protocol, but 

Re: [swift-evolution] [Draft] open and public protocols

2017-02-19 Thread Xiaodi Wu via swift-evolution
On Sun, Feb 19, 2017 at 4:51 PM, Adrian Zubarev <
adrian.zuba...@devandartist.com> wrote:

> Matthew has pretty much summed up everything with a single question in his
> last reply. It makes me tired of repeating myself over and over again.
>
> Here’s the challenge for you:
>
> Implement a subscript where the first parameter is a String (trivial), but
> the second to n are String’s and/or Int’s. There is no restriction of order
> for the Int’s and String’s and there could be as many as you’d like, so no
> overloads are allowed (a hint: variadics). You should be able to use
> variables in that subscript and literals. You’re not allowed to use enum
> constructors
>
Why not? You want a parameter that takes either String or Int. In another
language, you might express this as `String | Int`, but Chris Lattner and
others have said on this list that enums are the intended way of expressing
this in Swift.

> and the client should not be able to extend the set of types you can pass
> to that subscript. That said it can look like this: someInstance["key",
> "key1", 1, stringKeyInstance, intIndexInstance, intIndexInstance, …]
>
> Creating hacks like unreachable types with hidden inits is prohibited.
>
> Have fun!
>
>
>
> --
> Adrian Zubarev
> Sent with Airmail
>
> Am 19. Februar 2017 um 23:25:11, Xiaodi Wu (xiaodi...@gmail.com) schrieb:
>
> Sorry, I have read through this thread twice and do not understand the
> point you are making. Can you explain your example once more?
>
> Specifically, I do not understand why it is that your code should have
> problems with third-party types that conform to your protocol. If your
> protocol has requirements that third-party types cannot fulfill, then
> naturally those requirements will prevent a third-party from conforming new
> types to your protocol. OTOH, if your protocol does not have any
> requirements that third-party types cannot fulfill, then your code that
> accepts anything that conforms to your protocol should be indifferent to
> whether the conforming type is defined by you or someone else. After all, a
> conforming type would fulfill all the semantic and syntactic requirements
> of the protocol! If your protocol has requirements that you are unable to
> state in code, causing third-party types to conform that really shouldn't,
> then that is a case for additional features that allow you to express those
> requirements more accurately, not an argument for having protocols that
> can't be conformed to by a third-party. What am I missing?
>
>
> On Sun, Feb 19, 2017 at 11:53 AM, Adrian Zubarev via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>> That’s the whole point I was making. :) Thank you Matthew. That makes my
>> example a real world example and not just some bike shedding.
>>
>> --
>> Adrian Zubarev
>> Sent with Airmail
>>
>> Am 19. Februar 2017 um 18:50:31, Matthew Johnson (matt...@anandabits.com)
>> schrieb:
>>
>>
>>
>> Sent from my iPad
>>
>> On Feb 19, 2017, at 11:29 AM, David Waite via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>> Just FYI, I solved this issue in my own library (which included a json
>> jpointer implementation) via:
>>
>> public enum SubscriptParameter {
>>   case string(String)
>>   case int(Int)
>> }
>>
>> extension SubscriptParameter : ExpressibleByIntegerLiteral {
>>   public init(integerLiteral value: Int) {
>> self = .int(value)
>>   }
>> }
>>
>> extension SubscriptParameter : ExpressibleByStringLiteral {
>>   public init(stringLiteral value: String) {
>> self = .string(value)
>>   }
>>   public init(extendedGraphemeClusterLiteral value: String) {
>> self.init(stringLiteral: value)
>>   }
>>
>>   public init(unicodeScalarLiteral value: String) {
>> self.init(stringLiteral: value)
>>   }
>> }
>>
>> extension SubscriptParameter : CustomStringConvertible {
>>   public var description: String {
>> switch self {
>> case .string(let str):
>>   return "\"\(str)\""
>> case .int(let i):
>>   return String(i)
>> }
>>   }
>> }
>>
>> func debug(_ path:SubscriptParameter...) {
>>   print("path is \(path)")
>> }
>>
>> debug(1, "foo", 2, "bar”) // path is [1, “foo”, 2, “bar”]
>>
>>
>> Can you make this work with variables - not just literals - and still
>> prevent users from extending the set of types and without requiring an enum
>> case constructor to be used by clients?
>>
>>
>>
>> On Feb 19, 2017, at 1:14 AM, Adrian Zubarev <
>> adrian.zuba...@devandartist.com> wrote:
>>
>> If you haven’t followed the other thread Matthew previously opened than
>> you have missed the example I showed there.
>>
>> Here it is again:
>>
>> public protocol SubscriptParameterType {
>>
>> // This property was needed to prevent the client from breaking
>> // the library by conforming to the protocol, but I'd like to
>> // keep it invisible for the client, or even better prevent the
>> // client from conforming to the protocol.
>> var parameter: Document.SubscriptParameter { get }
>> }

Re: [swift-evolution] [Draft] open and public protocols

2017-02-19 Thread Xiaodi Wu via swift-evolution
On Sun, Feb 19, 2017 at 4:46 PM, Karl Wagner  wrote:

>
> > On 19 Feb 2017, at 23:24, Xiaodi Wu via swift-evolution <
> swift-evolution@swift.org> wrote:
> >
> > Sorry, I have read through this thread twice and do not understand the
> point you are making. Can you explain your example once more?
> >
> > Specifically, I do not understand why it is that your code should have
> problems with third-party types that conform to your protocol. If your
> protocol has requirements that third-party types cannot fulfill, then
> naturally those requirements will prevent a third-party from conforming new
> types to your protocol. OTOH, if your protocol does not have any
> requirements that third-party types cannot fulfill, then your code that
> accepts anything that conforms to your protocol should be indifferent to
> whether the conforming type is defined by you or someone else. After all, a
> conforming type would fulfill all the semantic and syntactic requirements
> of the protocol! If your protocol has requirements that you are unable to
> state in code, causing third-party types to conform that really shouldn't,
> then that is a case for additional features that allow you to express those
> requirements more accurately, not an argument for having protocols that
> can't be conformed to by a third-party. What am I missing?
> >
>
> I see it as an API expressivity thing; it’s not that clients _can’t_
> technically conform to the protocol, it’s that they _shouldn’t_ because
> that’s not why I’m exposing it.
>
> There are protocols that you do expose because you expect others to
> conform to them. There are others which you only expect to be used as
> generic/existential constraints.
>
> That’s basically the same reasoning as having a distinction between
> public/open for classes, too;


It isn't. The text of the proposal spends several paragraphs motivating the
distinction between public and open classes in the following way:

"A subclass that overrides methods of its superclass is intricately
intertwined with it. The two systems are not composed, and their behavior
cannot be understood independently. [...] Subclasses cannot be
independently tested using a mocked implementation of the superclass or
composed to apply the customizations of two different subclasses to a
single instance."

This is in direct contradistinction to protocols. Protocols *are* meant to
be composed. While a type is meant to uphold the semantic guarantees of
protocols to which it conforms, the behavior of a protocol and its
conforming types *are* meant to be understood independently. Conforming
types *are* meant to be testable independently from the protocols to which
they conform.


before we had “open” as a separate thing, you could subclass anything that
> was public. There was extra motivation for classes because of the
> opportunities for the optimiser to devirtualise function calls which may
> not be as strong a factor for protocols, but from an API design perspective
> it’s still nice to have consistent capabilities. From looking at my own
> code, I know that marking-up protocols which clients can conform to with
> @open would make both of our lives easier.
>
> I wouldn’t mind if we allowed the compiler to not enforce this rule very
> strongly (e.g. with a suppressible warning). Depends on what is achievable.
>
> - Karl
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft] open and public protocols

2017-02-19 Thread Adrian Zubarev via swift-evolution
Matthew has pretty much summed up everything with a single question in his last 
reply. It makes me tired of repeating myself over and over again.

Here’s the challenge for you:

Implement a subscript where the first parameter is a String (trivial), but the 
second to n are String’s and/or Int’s. There is no restriction of order for the 
Int’s and String’s and there could be as many as you’d like, so no overloads 
are allowed (a hint: variadics). You should be able to use variables in that 
subscript and literals. You’re not allowed to use enum constructors and the 
client should not be able to extend the set of types you can pass to that 
subscript. That said it can look like this: someInstance["key", "key1", 1, 
stringKeyInstance, intIndexInstance, intIndexInstance, …]

Creating hacks like unreachable types with hidden inits is prohibited.

Have fun!



-- 
Adrian Zubarev
Sent with Airmail

Am 19. Februar 2017 um 23:25:11, Xiaodi Wu (xiaodi...@gmail.com) schrieb:

Sorry, I have read through this thread twice and do not understand the point 
you are making. Can you explain your example once more?

Specifically, I do not understand why it is that your code should have problems 
with third-party types that conform to your protocol. If your protocol has 
requirements that third-party types cannot fulfill, then naturally those 
requirements will prevent a third-party from conforming new types to your 
protocol. OTOH, if your protocol does not have any requirements that 
third-party types cannot fulfill, then your code that accepts anything that 
conforms to your protocol should be indifferent to whether the conforming type 
is defined by you or someone else. After all, a conforming type would fulfill 
all the semantic and syntactic requirements of the protocol! If your protocol 
has requirements that you are unable to state in code, causing third-party 
types to conform that really shouldn't, then that is a case for additional 
features that allow you to express those requirements more accurately, not an 
argument for having protocols that can't be conformed to by a third-party. What 
am I missing?


On Sun, Feb 19, 2017 at 11:53 AM, Adrian Zubarev via swift-evolution 
 wrote:
That’s the whole point I was making. :) Thank you Matthew. That makes my 
example a real world example and not just some bike shedding.

-- 
Adrian Zubarev
Sent with Airmail

Am 19. Februar 2017 um 18:50:31, Matthew Johnson (matt...@anandabits.com) 
schrieb:



Sent from my iPad

On Feb 19, 2017, at 11:29 AM, David Waite via swift-evolution 
 wrote:

Just FYI, I solved this issue in my own library (which included a json jpointer 
implementation) via:

public enum SubscriptParameter {
  case string(String)
  case int(Int)
}

extension SubscriptParameter : ExpressibleByIntegerLiteral {
  public init(integerLiteral value: Int) {
    self = .int(value)
  }
}

extension SubscriptParameter : ExpressibleByStringLiteral {
  public init(stringLiteral value: String) {
    self = .string(value)
  }
  public init(extendedGraphemeClusterLiteral value: String) {
    self.init(stringLiteral: value)
  }
  public init(unicodeScalarLiteral value: String) {
    self.init(stringLiteral: value)
  }
}

extension SubscriptParameter : CustomStringConvertible {
  public var description: String {
    switch self {
    case .string(let str):
      return "\"\(str)\""
    case .int(let i):
      return String(i)
    }
  }
}

func debug(_ path:SubscriptParameter...) {
  print("path is \(path)")
}

debug(1, "foo", 2, "bar”) // path is [1, “foo”, 2, “bar”]

Can you make this work with variables - not just literals - and still prevent 
users from extending the set of types and without requiring an enum case 
constructor to be used by clients?



On Feb 19, 2017, at 1:14 AM, Adrian Zubarev  
wrote:

If you haven’t followed the other thread Matthew previously opened than you 
have missed the example I showed there.

Here it is again:

public protocol SubscriptParameterType {

// This property was needed to prevent the client from breaking
// the library by conforming to the protocol, but I'd like to 
// keep it invisible for the client, or even better prevent the
// client from conforming to the protocol.
var parameter: Document.SubscriptParameter { get }
}

extension Document {

public enum SubscriptParameter {

case string(String)
case integer(Int)
}
}

extension String : SubscriptParameterType {

public var parameter: Document.SubscriptParameter {

return .string(self)
}
}

extension Int : SubscriptParameterType {

public var parameter: Document.SubscriptParameter {

return .integer(self)
}
}

// Somewhere inside the `Document` type
public subscript(firstKey: String, parameters: SubscriptParameterType...) -> 
Value? { … }
The 

Re: [swift-evolution] [Draft] open and public protocols

2017-02-19 Thread Karl Wagner via swift-evolution

> On 19 Feb 2017, at 23:24, Xiaodi Wu via swift-evolution 
>  wrote:
> 
> Sorry, I have read through this thread twice and do not understand the point 
> you are making. Can you explain your example once more?
> 
> Specifically, I do not understand why it is that your code should have 
> problems with third-party types that conform to your protocol. If your 
> protocol has requirements that third-party types cannot fulfill, then 
> naturally those requirements will prevent a third-party from conforming new 
> types to your protocol. OTOH, if your protocol does not have any requirements 
> that third-party types cannot fulfill, then your code that accepts anything 
> that conforms to your protocol should be indifferent to whether the 
> conforming type is defined by you or someone else. After all, a conforming 
> type would fulfill all the semantic and syntactic requirements of the 
> protocol! If your protocol has requirements that you are unable to state in 
> code, causing third-party types to conform that really shouldn't, then that 
> is a case for additional features that allow you to express those 
> requirements more accurately, not an argument for having protocols that can't 
> be conformed to by a third-party. What am I missing?
> 

I see it as an API expressivity thing; it’s not that clients _can’t_ 
technically conform to the protocol, it’s that they _shouldn’t_ because that’s 
not why I’m exposing it.

There are protocols that you do expose because you expect others to conform to 
them. There are others which you only expect to be used as generic/existential 
constraints.

That’s basically the same reasoning as having a distinction between public/open 
for classes, too; before we had “open” as a separate thing, you could subclass 
anything that was public. There was extra motivation for classes because of the 
opportunities for the optimiser to devirtualise function calls which may not be 
as strong a factor for protocols, but from an API design perspective it’s still 
nice to have consistent capabilities. From looking at my own code, I know that 
marking-up protocols which clients can conform to with @open would make both of 
our lives easier.

I wouldn’t mind if we allowed the compiler to not enforce this rule very 
strongly (e.g. with a suppressible warning). Depends on what is achievable.

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


Re: [swift-evolution] [Draft] open and public protocols

2017-02-19 Thread David Hart via swift-evolution

> On 19 Feb 2017, at 23:24, Xiaodi Wu via swift-evolution 
>  wrote:
> 
> Sorry, I have read through this thread twice and do not understand the point 
> you are making. Can you explain your example once more?
> 
> Specifically, I do not understand why it is that your code should have 
> problems with third-party types that conform to your protocol. If your 
> protocol has requirements that third-party types cannot fulfill, then 
> naturally those requirements will prevent a third-party from conforming new 
> types to your protocol. OTOH, if your protocol does not have any requirements 
> that third-party types cannot fulfill, then your code that accepts anything 
> that conforms to your protocol should be indifferent to whether the 
> conforming type is defined by you or someone else. After all, a conforming 
> type would fulfill all the semantic and syntactic requirements of the 
> protocol! If your protocol has requirements that you are unable to state in 
> code, causing third-party types to conform that really shouldn't, then that 
> is a case for additional features that allow you to express those 
> requirements more accurately, not an argument for having protocols that can't 
> be conformed to by a third-party. What am I missing?

Yeah, sums up my opinion pretty accurately.

> On Sun, Feb 19, 2017 at 11:53 AM, Adrian Zubarev via swift-evolution 
> > wrote:
> That’s the whole point I was making. :) Thank you Matthew. That makes my 
> example a real world example and not just some bike shedding.
> 
> -- 
> Adrian Zubarev
> Sent with Airmail
> 
> Am 19. Februar 2017 um 18:50:31, Matthew Johnson (matt...@anandabits.com 
> ) schrieb:
> 
>> 
>> 
>> Sent from my iPad
>> 
>> On Feb 19, 2017, at 11:29 AM, David Waite via swift-evolution 
>> > wrote:
>> 
>>> Just FYI, I solved this issue in my own library (which included a json 
>>> jpointer implementation) via:
>>> 
>>> public enum SubscriptParameter {
>>>   case string(String)
>>>   case int(Int)
>>> }
>>> 
>>> extension SubscriptParameter : ExpressibleByIntegerLiteral {
>>>   public init(integerLiteral value: Int) {
>>> self = .int(value)
>>>   }
>>> }
>>> 
>>> extension SubscriptParameter : ExpressibleByStringLiteral {
>>>   public init(stringLiteral value: String) {
>>> self = .string(value)
>>>   }
>>>   public init(extendedGraphemeClusterLiteral value: String) {
>>> self.init(stringLiteral: value)
>>>   }
>>>   public init(unicodeScalarLiteral value: String) {
>>> self.init(stringLiteral: value)
>>>   }
>>> }
>>> 
>>> extension SubscriptParameter : CustomStringConvertible {
>>>   public var description: String {
>>> switch self {
>>> case .string(let str):
>>>   return "\"\(str)\""
>>> case .int(let i):
>>>   return String(i)
>>> }
>>>   }
>>> }
>>> 
>>> func debug(_ path:SubscriptParameter...) {
>>>   print("path is \(path)")
>>> }
>>> 
>>> debug(1, "foo", 2, "bar”) // path is [1, “foo”, 2, “bar”]
>> 
>> Can you make this work with variables - not just literals - and still 
>> prevent users from extending the set of types and without requiring an enum 
>> case constructor to be used by clients?
>> 
>> 
>>> 
 On Feb 19, 2017, at 1:14 AM, Adrian Zubarev 
 > 
 wrote:
 
 If you haven’t followed the other thread Matthew previously opened than 
 you have missed the example I showed there.
 
 Here it is again:
 
 public protocol SubscriptParameterType {

 // This property was needed to prevent the client from breaking
 // the library by conforming to the protocol, but I'd like to
 // keep it invisible for the client, or even better prevent the
 // client from conforming to the protocol.
 var parameter: Document.SubscriptParameter { get }
 }
 
 extension Document {

 public enum SubscriptParameter {

 case string(String)
 case integer(Int)
 }
 }
 
 extension String : SubscriptParameterType {

 public var parameter: Document.SubscriptParameter {

 return .string(self)
 }
 }
 
 extension Int : SubscriptParameterType {

 public var parameter: Document.SubscriptParameter {

 return .integer(self)
 }
 }
 
 // Somewhere inside the `Document` type
 public subscript(firstKey: String, parameters: SubscriptParameterType...) 
 -> Value? { … }
 The absence of closed protocols forced me to create a special requirement 
 on that protocol to prevent the client from conforming to that protocol 
 and passing instances of other types my API 

Re: [swift-evolution] [Draft] open and public protocols

2017-02-19 Thread Xiaodi Wu via swift-evolution
Sorry, I have read through this thread twice and do not understand the
point you are making. Can you explain your example once more?

Specifically, I do not understand why it is that your code should have
problems with third-party types that conform to your protocol. If your
protocol has requirements that third-party types cannot fulfill, then
naturally those requirements will prevent a third-party from conforming new
types to your protocol. OTOH, if your protocol does not have any
requirements that third-party types cannot fulfill, then your code that
accepts anything that conforms to your protocol should be indifferent to
whether the conforming type is defined by you or someone else. After all, a
conforming type would fulfill all the semantic and syntactic requirements
of the protocol! If your protocol has requirements that you are unable to
state in code, causing third-party types to conform that really shouldn't,
then that is a case for additional features that allow you to express those
requirements more accurately, not an argument for having protocols that
can't be conformed to by a third-party. What am I missing?


On Sun, Feb 19, 2017 at 11:53 AM, Adrian Zubarev via swift-evolution <
swift-evolution@swift.org> wrote:

> That’s the whole point I was making. :) Thank you Matthew. That makes my
> example a real world example and not just some bike shedding.
>
> --
> Adrian Zubarev
> Sent with Airmail
>
> Am 19. Februar 2017 um 18:50:31, Matthew Johnson (matt...@anandabits.com)
> schrieb:
>
>
>
> Sent from my iPad
>
> On Feb 19, 2017, at 11:29 AM, David Waite via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> Just FYI, I solved this issue in my own library (which included a json
> jpointer implementation) via:
>
> public enum SubscriptParameter {
>   case string(String)
>   case int(Int)
> }
>
> extension SubscriptParameter : ExpressibleByIntegerLiteral {
>   public init(integerLiteral value: Int) {
> self = .int(value)
>   }
> }
>
> extension SubscriptParameter : ExpressibleByStringLiteral {
>   public init(stringLiteral value: String) {
> self = .string(value)
>   }
>   public init(extendedGraphemeClusterLiteral value: String) {
> self.init(stringLiteral: value)
>   }
>
>   public init(unicodeScalarLiteral value: String) {
> self.init(stringLiteral: value)
>   }
> }
>
> extension SubscriptParameter : CustomStringConvertible {
>   public var description: String {
> switch self {
> case .string(let str):
>   return "\"\(str)\""
> case .int(let i):
>   return String(i)
> }
>   }
> }
>
> func debug(_ path:SubscriptParameter...) {
>   print("path is \(path)")
> }
>
> debug(1, "foo", 2, "bar”) // path is [1, “foo”, 2, “bar”]
>
>
> Can you make this work with variables - not just literals - and still
> prevent users from extending the set of types and without requiring an enum
> case constructor to be used by clients?
>
>
>
> On Feb 19, 2017, at 1:14 AM, Adrian Zubarev  com> wrote:
>
> If you haven’t followed the other thread Matthew previously opened than
> you have missed the example I showed there.
>
> Here it is again:
>
> public protocol SubscriptParameterType {
>
> // This property was needed to prevent the client from breaking
> // the library by conforming to the protocol, but I'd like to
> // keep it invisible for the client, or even better prevent the
> // client from conforming to the protocol.
> var parameter: Document.SubscriptParameter { get }
> }
>
> extension Document {
>
> public enum SubscriptParameter {
>
> case string(String)
> case integer(Int)
> }
> }
>
> extension String : SubscriptParameterType {
>
> public var parameter: Document.SubscriptParameter {
>
> return .string(self)
> }
> }
>
> extension Int : SubscriptParameterType {
>
> public var parameter: Document.SubscriptParameter {
>
> return .integer(self)
> }
> }
>
> // Somewhere inside the `Document` type
> public subscript(firstKey: String, parameters: SubscriptParameterType...) -> 
> Value? { … }
>
> The absence of closed protocols forced me to create a special requirement
> on that protocol to prevent the client from conforming to that protocol and
> passing instances of other types my API wouldn’t want to deal with. That
> creates unnecessary copies and I need to unpack the enum payload to find
> out which type the user passed. Instead I could simply close the protocol,
> wouldn’t need the requirement to exist and I could simply cast the type to
>  String or Int when needed.
>
> That implementation enables more safe queries of my Document type like
>
> document["key1", intIndexInstance, stringKeyInstance, 10, "key"]
>
> rather than
>
> document["key1/\(intIndexInstance)/\(stringKeyInstance)/10/key"].
> --
>
> Here is a list of hidden and semi-hidden protocols from the standard
> library that could be closed. Formatted version: 

Re: [swift-evolution] [Draft] open and public protocols

2017-02-19 Thread Adrian Zubarev via swift-evolution
That’s the whole point I was making. :) Thank you Matthew. That makes my 
example a real world example and not just some bike shedding.

-- 
Adrian Zubarev
Sent with Airmail

Am 19. Februar 2017 um 18:50:31, Matthew Johnson (matt...@anandabits.com) 
schrieb:



Sent from my iPad

On Feb 19, 2017, at 11:29 AM, David Waite via swift-evolution 
 wrote:

Just FYI, I solved this issue in my own library (which included a json jpointer 
implementation) via:

public enum SubscriptParameter {
  case string(String)
  case int(Int)
}

extension SubscriptParameter : ExpressibleByIntegerLiteral {
  public init(integerLiteral value: Int) {
    self = .int(value)
  }
}

extension SubscriptParameter : ExpressibleByStringLiteral {
  public init(stringLiteral value: String) {
    self = .string(value)
  }
  public init(extendedGraphemeClusterLiteral value: String) {
    self.init(stringLiteral: value)
  }
  public init(unicodeScalarLiteral value: String) {
    self.init(stringLiteral: value)
  }
}

extension SubscriptParameter : CustomStringConvertible {
  public var description: String {
    switch self {
    case .string(let str):
      return "\"\(str)\""
    case .int(let i):
      return String(i)
    }
  }
}

func debug(_ path:SubscriptParameter...) {
  print("path is \(path)")
}

debug(1, "foo", 2, "bar”) // path is [1, “foo”, 2, “bar”]

Can you make this work with variables - not just literals - and still prevent 
users from extending the set of types and without requiring an enum case 
constructor to be used by clients?



On Feb 19, 2017, at 1:14 AM, Adrian Zubarev  
wrote:

If you haven’t followed the other thread Matthew previously opened than you 
have missed the example I showed there.

Here it is again:

public protocol SubscriptParameterType {
   
// This property was needed to prevent the client from breaking
// the library by conforming to the protocol, but I'd like to
// keep it invisible for the client, or even better prevent the
// client from conforming to the protocol.
var parameter: Document.SubscriptParameter { get }
}

extension Document {
   
public enum SubscriptParameter {
   
case string(String)
case integer(Int)
}
}

extension String : SubscriptParameterType {
   
public var parameter: Document.SubscriptParameter {
   
return .string(self)
}
}

extension Int : SubscriptParameterType {
   
public var parameter: Document.SubscriptParameter {
   
return .integer(self)
}
}

// Somewhere inside the `Document` type
public subscript(firstKey: String, parameters: SubscriptParameterType...) -> 
Value? { … }
The absence of closed protocols forced me to create a special requirement on 
that protocol to prevent the client from conforming to that protocol and 
passing instances of other types my API wouldn’t want to deal with. That 
creates unnecessary copies and I need to unpack the enum payload to find out 
which type the user passed. Instead I could simply close the protocol, wouldn’t 
need the requirement to exist and I could simply cast the type to String or Int 
when needed.

That implementation enables more safe queries of my Document type like

document["key1", intIndexInstance, stringKeyInstance, 10, "key"]

rather than 

document["key1/\(intIndexInstance)/\(stringKeyInstance)/10/key"].

Here is a list of hidden and semi-hidden protocols from the standard library 
that could be closed. Formatted version: 
https://gist.github.com/DevAndArtist/168c800d784829be536c407311953ab7

PathProtocol
/swift/stdlib/public/core/AnyHashable.swift:16  
_HasCustomAnyHashableRepresentation
/swift/stdlib/public/core/BidirectionalCollection.swift:21  
_BidirectionalIndexable
/swift/stdlib/public/core/BridgeObjectiveC.swift:19 _ObjectiveCBridgeable
/swift/stdlib/public/core/Collection.swift:20   _IndexableBase
/swift/stdlib/public/core/Collection.swift:176  _Indexable
/swift/stdlib/public/core/CompilerProtocols.swift:193   
_ExpressibleByBuiltinIntegerLiteral
/swift/stdlib/public/core/CompilerProtocols.swift:240   
_ExpressibleByBuiltinFloatLiteral
/swift/stdlib/public/core/CompilerProtocols.swift:283   
_ExpressibleByBuiltinBooleanLiteral
/swift/stdlib/public/core/CompilerProtocols.swift:316   
_ExpressibleByBuiltinUnicodeScalarLiteral
/swift/stdlib/public/core/CompilerProtocols.swift:350   
_ExpressibleByBuiltinExtendedGraphemeClusterLiteral
/swift/stdlib/public/core/CompilerProtocols.swift:398   
_ExpressibleByBuiltinStringLiteral
/swift/stdlib/public/core/CompilerProtocols.swift:407   
_ExpressibleByBuiltinUTF16StringLiteral
/swift/stdlib/public/core/CompilerProtocols.swift:670   
_ExpressibleByStringInterpolation
/swift/stdlib/public/core/CompilerProtocols.swift:709   
_ExpressibleByColorLiteral
/swift/stdlib/public/core/CompilerProtocols.swift:720   
_ExpressibleByImageLiteral

Re: [swift-evolution] [Draft] open and public protocols

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


Sent from my iPad

> On Feb 19, 2017, at 10:39 AM, Adrian Zubarev 
>  wrote:
> 
> Still not what I was asking about.
> 
> Module A contains a single open protocol: open protocol P { func foo() }
> Module B contains a single open class that conforms to P:
> open class B : P {
> /* what is the default access modifier here? */ func foo()
> }
> 

I believe it would be the same with or without the protocol conformance.  In 
any case, this has nothing to do with this proposal.  It does not affect open 
classes or open protocols.

> 
> -- 
> Adrian Zubarev
> Sent with Airmail
> 
> Am 19. Februar 2017 um 17:35:04, Matthew Johnson (matt...@anandabits.com) 
> schrieb:
> 
>> 
>> 
>> Sent from my iPhone
>> 
>> On Feb 19, 2017, at 10:28 AM, Adrian Zubarev 
>>  wrote:
>> 
>>> I really feel I’m blind, I cannot find it. Is the access modifier of open 
>>> protocol *members* on open/public classes public by default, or open?
>>> 
>>> If open, can we downgrade it to public in an open class?
>> 
>> I didn't specifically address members of open classes but did address open 
>> classes.  This proposal does not have any impact of the visibility of 
>> members of open classes that conform to a public (nonopen) protocol, 
>> including the default.
>>> 
>>> 
>>> -- 
>>> Adrian Zubarev
>>> Sent with Airmail
>>> 
>>> Am 19. Februar 2017 um 17:16:59, Matthew Johnson (matt...@anandabits.com) 
>>> schrieb:
>>> 
 
 
 Sent from my iPhone
 
 On Feb 19, 2017, at 10:11 AM, Adrian Zubarev 
  wrote:
 
> @Matthew: Have you considered what happens with the access modifier of an 
> open protocol when an open/public class conforms to it?
> 
 
 Yes I covered this in the detailed design section of the proposal.
> // Module A
> open protocol A {
> func foo()
> }
> 
> // Module B
> open class B : A {
> (open or public) func foo() {}
> // If `open`, can we downgrade to `public`?
> // The other way around seems straightforward
> }
>>> 
> 
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft] open and public protocols

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


Sent from my iPad

> On Feb 19, 2017, at 11:29 AM, David Waite via swift-evolution 
>  wrote:
> 
> Just FYI, I solved this issue in my own library (which included a json 
> jpointer implementation) via:
> 
> public enum SubscriptParameter {
>   case string(String)
>   case int(Int)
> }
> 
> extension SubscriptParameter : ExpressibleByIntegerLiteral {
>   public init(integerLiteral value: Int) {
> self = .int(value)
>   }
> }
> 
> extension SubscriptParameter : ExpressibleByStringLiteral {
>   public init(stringLiteral value: String) {
> self = .string(value)
>   }
>   public init(extendedGraphemeClusterLiteral value: String) {
> self.init(stringLiteral: value)
>   }
>   public init(unicodeScalarLiteral value: String) {
> self.init(stringLiteral: value)
>   }
> }
> 
> extension SubscriptParameter : CustomStringConvertible {
>   public var description: String {
> switch self {
> case .string(let str):
>   return "\"\(str)\""
> case .int(let i):
>   return String(i)
> }
>   }
> }
> 
> func debug(_ path:SubscriptParameter...) {
>   print("path is \(path)")
> }
> 
> debug(1, "foo", 2, "bar”) // path is [1, “foo”, 2, “bar”]

Can you make this work with variables - not just literals - and still prevent 
users from extending the set of types and without requiring an enum case 
constructor to be used by clients?


> 
>> On Feb 19, 2017, at 1:14 AM, Adrian Zubarev 
>>  wrote:
>> 
>> If you haven’t followed the other thread Matthew previously opened than you 
>> have missed the example I showed there.
>> 
>> Here it is again:
>> 
>> public protocol SubscriptParameterType {
>>   
>> // This property was needed to prevent the client from breaking
>> // the library by conforming to the protocol, but I'd like to   
>> // keep it invisible for the client, or even better prevent the
>> // client from conforming to the protocol.
>> var parameter: Document.SubscriptParameter { get }
>> }
>> 
>> extension Document {
>>   
>> public enum SubscriptParameter {
>>   
>> case string(String)
>> case integer(Int)
>> }
>> }
>> 
>> extension String : SubscriptParameterType {
>>   
>> public var parameter: Document.SubscriptParameter {
>>   
>> return .string(self)
>> }
>> }
>> 
>> extension Int : SubscriptParameterType {
>>   
>> public var parameter: Document.SubscriptParameter {
>>   
>> return .integer(self)
>> }
>> }
>> 
>> // Somewhere inside the `Document` type
>> public subscript(firstKey: String, parameters: SubscriptParameterType...) -> 
>> Value? { … }
>> The absence of closed protocols forced me to create a special requirement on 
>> that protocol to prevent the client from conforming to that protocol and 
>> passing instances of other types my API wouldn’t want to deal with. That 
>> creates unnecessary copies and I need to unpack the enum payload to find out 
>> which type the user passed. Instead I could simply close the protocol, 
>> wouldn’t need the requirement to exist and I could simply cast the type to 
>> String or Int when needed.
>> 
>> That implementation enables more safe queries of my Document type like
>> 
>> document["key1", intIndexInstance, stringKeyInstance, 10, "key"]
>> 
>> rather than 
>> 
>> document["key1/\(intIndexInstance)/\(stringKeyInstance)/10/key"].
>> 
>> Here is a list of hidden and semi-hidden protocols from the standard library 
>> that could be closed. Formatted version: 
>> https://gist.github.com/DevAndArtist/168c800d784829be536c407311953ab7
>> 
>> Path Protocol
>> /swift/stdlib/public/core/AnyHashable.swift:16   
>> _HasCustomAnyHashableRepresentation
>> /swift/stdlib/public/core/BidirectionalCollection.swift:21   
>> _BidirectionalIndexable
>> /swift/stdlib/public/core/BridgeObjectiveC.swift:19  _ObjectiveCBridgeable
>> /swift/stdlib/public/core/Collection.swift:20_IndexableBase
>> /swift/stdlib/public/core/Collection.swift:176   _Indexable
>> /swift/stdlib/public/core/CompilerProtocols.swift:193
>> _ExpressibleByBuiltinIntegerLiteral
>> /swift/stdlib/public/core/CompilerProtocols.swift:240
>> _ExpressibleByBuiltinFloatLiteral
>> /swift/stdlib/public/core/CompilerProtocols.swift:283
>> _ExpressibleByBuiltinBooleanLiteral
>> /swift/stdlib/public/core/CompilerProtocols.swift:316
>> _ExpressibleByBuiltinUnicodeScalarLiteral
>> /swift/stdlib/public/core/CompilerProtocols.swift:350
>> _ExpressibleByBuiltinExtendedGraphemeClusterLiteral
>> /swift/stdlib/public/core/CompilerProtocols.swift:398
>> _ExpressibleByBuiltinStringLiteral
>> /swift/stdlib/public/core/CompilerProtocols.swift:407
>> _ExpressibleByBuiltinUTF16StringLiteral
>> /swift/stdlib/public/core/CompilerProtocols.swift:670
>> _ExpressibleByStringInterpolation
>> /swift/stdlib/public/core/CompilerProtocols.swift:709
>> 

Re: [swift-evolution] [Draft] open and public protocols

2017-02-19 Thread Karl Wagner via swift-evolution

> On 19 Feb 2017, at 17:36, David Hart  wrote:
> 
> This makes more sense already. But in this case, wouldn't I be interested, as 
> a client, in creating my own TextStreams, some of which might write to a 
> custom log file, to a web service, etc... ?
> 
> On 19 Feb 2017, at 17:00, Karl Wagner  > wrote:
> 
>> 
>>> On 19 Feb 2017, at 16:17, David Hart via swift-evolution 
>>> > wrote:
>>> 
>>> I still don't see the use case for this. Perhaps I'm wrong, but if an API 
>>> creates a protocol for the sole purpose of representing a set of concrete 
>>> types, that looks more to me like bad API design, and not a missing feature 
>>> in the language. Can you give me a small concrete real-world example of an 
>>> API which requires that? 
>> 
>> 
>> Whether or not a protocol is open is also a part of API expressivity; often 
>> a library will want to expose a protocol only as a way to enable 
>> generic/existential programming over a fixed set of types, without intending 
>> that any clients add new conformers. Protocols are crucial to expressing the 
>> shared patterns amongst the set of types.
>> 
>> For example, I might have a TextStream protocol:
>> 
>> public protocol TextStream {
>> func write(_: String)
>> }
>> 
>> And I might decide to expose a property as type “TextStream” purely because 
>> I reserve the right to change the underlying concrete type. I want clients 
>> to work on the protocol-existential level.
>> 
>> public class Component {
>> var debugWriter: TextStream
>> }
>> 
>> By doing that, the underlying concrete type is no longer part of my API or 
>> ABI. I can change it between versions without breaking clients, but it’s not 
>> meaningful for any clients to create their own TextStreams; that’s not part 
>> of what my library does/allows.
>> 
>> - Karl

Perhaps, but there are times when you don’t want that, or when accommodating 
custom instances is not so straightforward. The debugWriter instance is only 
_exposed_ as a “TextStream”; but there may be more (internal) requirements on 
the underlying instance - e.g. that it is Flushable, 
InitialisableFromNativeFileObject, or whatever. I would rather not expose them 
all, and just expose the instance as “something which is a TextStream, so you 
can call TextStream methods on it”, if I decide that’s all they need to know.

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


Re: [swift-evolution] [Draft] open and public protocols

2017-02-19 Thread Adrian Zubarev via swift-evolution
Try to pass let intInstance = 42 in your function. ;)

That will result in .int(intInstance).

My implementation does not need that at all.



-- 
Adrian Zubarev
Sent with Airmail

Am 19. Februar 2017 um 18:29:54, David Waite (da...@alkaline-solutions.com) 
schrieb:

Just FYI, I solved this issue in my own library (which included a json jpointer 
implementation) via:

public enum SubscriptParameter {
  case string(String)
  case int(Int)
}

extension SubscriptParameter : ExpressibleByIntegerLiteral {
  public init(integerLiteral value: Int) {
    self = .int(value)
  }
}

extension SubscriptParameter : ExpressibleByStringLiteral {
  public init(stringLiteral value: String) {
    self = .string(value)
  }
  public init(extendedGraphemeClusterLiteral value: String) {
    self.init(stringLiteral: value)
  }
  public init(unicodeScalarLiteral value: String) {
    self.init(stringLiteral: value)
  }
}

extension SubscriptParameter : CustomStringConvertible {
  public var description: String {
    switch self {
    case .string(let str):
      return "\"\(str)\""
    case .int(let i):
      return String(i)
    }
  }
}

func debug(_ path:SubscriptParameter...) {
  print("path is \(path)")
}

debug(1, "foo", 2, "bar”) // path is [1, “foo”, 2, “bar”]

On Feb 19, 2017, at 1:14 AM, Adrian Zubarev  
wrote:

If you haven’t followed the other thread Matthew previously opened than you 
have missed the example I showed there.

Here it is again:

public protocol SubscriptParameterType {
   
// This property was needed to prevent the client from breaking
// the library by conforming to the protocol, but I'd like to
// keep it invisible for the client, or even better prevent the
// client from conforming to the protocol.
var parameter: Document.SubscriptParameter { get }
}

extension Document {
   
public enum SubscriptParameter {
   
case string(String)
case integer(Int)
}
}

extension String : SubscriptParameterType {
   
public var parameter: Document.SubscriptParameter {
   
return .string(self)
}
}

extension Int : SubscriptParameterType {
   
public var parameter: Document.SubscriptParameter {
   
return .integer(self)
}
}

// Somewhere inside the `Document` type
public subscript(firstKey: String, parameters: SubscriptParameterType...) -> 
Value? { … }
The absence of closed protocols forced me to create a special requirement on 
that protocol to prevent the client from conforming to that protocol and 
passing instances of other types my API wouldn’t want to deal with. That 
creates unnecessary copies and I need to unpack the enum payload to find out 
which type the user passed. Instead I could simply close the protocol, wouldn’t 
need the requirement to exist and I could simply cast the type to String or Int 
when needed.

That implementation enables more safe queries of my Document type like

document["key1", intIndexInstance, stringKeyInstance, 10, "key"]

rather than 

document["key1/\(intIndexInstance)/\(stringKeyInstance)/10/key"].

Here is a list of hidden and semi-hidden protocols from the standard library 
that could be closed. Formatted version: 
https://gist.github.com/DevAndArtist/168c800d784829be536c407311953ab7

PathProtocol
/swift/stdlib/public/core/AnyHashable.swift:16  
_HasCustomAnyHashableRepresentation
/swift/stdlib/public/core/BidirectionalCollection.swift:21  
_BidirectionalIndexable
/swift/stdlib/public/core/BridgeObjectiveC.swift:19 _ObjectiveCBridgeable
/swift/stdlib/public/core/Collection.swift:20   _IndexableBase
/swift/stdlib/public/core/Collection.swift:176  _Indexable
/swift/stdlib/public/core/CompilerProtocols.swift:193   
_ExpressibleByBuiltinIntegerLiteral
/swift/stdlib/public/core/CompilerProtocols.swift:240   
_ExpressibleByBuiltinFloatLiteral
/swift/stdlib/public/core/CompilerProtocols.swift:283   
_ExpressibleByBuiltinBooleanLiteral
/swift/stdlib/public/core/CompilerProtocols.swift:316   
_ExpressibleByBuiltinUnicodeScalarLiteral
/swift/stdlib/public/core/CompilerProtocols.swift:350   
_ExpressibleByBuiltinExtendedGraphemeClusterLiteral
/swift/stdlib/public/core/CompilerProtocols.swift:398   
_ExpressibleByBuiltinStringLiteral
/swift/stdlib/public/core/CompilerProtocols.swift:407   
_ExpressibleByBuiltinUTF16StringLiteral
/swift/stdlib/public/core/CompilerProtocols.swift:670   
_ExpressibleByStringInterpolation
/swift/stdlib/public/core/CompilerProtocols.swift:709   
_ExpressibleByColorLiteral
/swift/stdlib/public/core/CompilerProtocols.swift:720   
_ExpressibleByImageLiteral
/swift/stdlib/public/core/CompilerProtocols.swift:730   
_ExpressibleByFileReferenceLiteral
/swift/stdlib/public/core/CompilerProtocols.swift:750   _DestructorSafeContainer
/swift/stdlib/public/core/FixedPoint.swift.gyb:53   _Integer
/swift/stdlib/public/core/FixedPoint.swift.gyb:70   _SignedInteger

Re: [swift-evolution] [Draft] open and public protocols

2017-02-19 Thread David Waite via swift-evolution
Just FYI, I solved this issue in my own library (which included a json jpointer 
implementation) via:

public enum SubscriptParameter {
  case string(String)
  case int(Int)
}

extension SubscriptParameter : ExpressibleByIntegerLiteral {
  public init(integerLiteral value: Int) {
self = .int(value)
  }
}

extension SubscriptParameter : ExpressibleByStringLiteral {
  public init(stringLiteral value: String) {
self = .string(value)
  }
  public init(extendedGraphemeClusterLiteral value: String) {
self.init(stringLiteral: value)
  }
  public init(unicodeScalarLiteral value: String) {
self.init(stringLiteral: value)
  }
}

extension SubscriptParameter : CustomStringConvertible {
  public var description: String {
switch self {
case .string(let str):
  return "\"\(str)\""
case .int(let i):
  return String(i)
}
  }
}

func debug(_ path:SubscriptParameter...) {
  print("path is \(path)")
}

debug(1, "foo", 2, "bar”) // path is [1, “foo”, 2, “bar”]

> On Feb 19, 2017, at 1:14 AM, Adrian Zubarev  
> wrote:
> 
> If you haven’t followed the other thread Matthew previously opened than you 
> have missed the example I showed there.
> 
> Here it is again:
> 
> public protocol SubscriptParameterType {
>   
> // This property was needed to prevent the client from breaking
> // the library by conforming to the protocol, but I'd like to   
> // keep it invisible for the client, or even better prevent the
> // client from conforming to the protocol.
> var parameter: Document.SubscriptParameter { get }
> }
> 
> extension Document {
>   
> public enum SubscriptParameter {
>   
> case string(String)
> case integer(Int)
> }
> }
> 
> extension String : SubscriptParameterType {
>   
> public var parameter: Document.SubscriptParameter {
>   
> return .string(self)
> }
> }
> 
> extension Int : SubscriptParameterType {
>   
> public var parameter: Document.SubscriptParameter {
>   
> return .integer(self)
> }
> }
> 
> // Somewhere inside the `Document` type
> public subscript(firstKey: String, parameters: SubscriptParameterType...) -> 
> Value? { … }
> The absence of closed protocols forced me to create a special requirement on 
> that protocol to prevent the client from conforming to that protocol and 
> passing instances of other types my API wouldn’t want to deal with. That 
> creates unnecessary copies and I need to unpack the enum payload to find out 
> which type the user passed. Instead I could simply close the protocol, 
> wouldn’t need the requirement to exist and I could simply cast the type to 
> String or Int when needed.
> 
> That implementation enables more safe queries of my Document type like
> 
> document["key1", intIndexInstance, stringKeyInstance, 10, "key"]
> 
> rather than 
> 
> document["key1/\(intIndexInstance)/\(stringKeyInstance)/10/key"].
> 
> Here is a list of hidden and semi-hidden protocols from the standard library 
> that could be closed. Formatted version: 
> https://gist.github.com/DevAndArtist/168c800d784829be536c407311953ab7 
> 
> Path  Protocol
> /swift/stdlib/public/core/AnyHashable.swift:16
> _HasCustomAnyHashableRepresentation
> /swift/stdlib/public/core/BidirectionalCollection.swift:21
> _BidirectionalIndexable
> /swift/stdlib/public/core/BridgeObjectiveC.swift:19   _ObjectiveCBridgeable
> /swift/stdlib/public/core/Collection.swift:20 _IndexableBase
> /swift/stdlib/public/core/Collection.swift:176_Indexable
> /swift/stdlib/public/core/CompilerProtocols.swift:193 
> _ExpressibleByBuiltinIntegerLiteral
> /swift/stdlib/public/core/CompilerProtocols.swift:240 
> _ExpressibleByBuiltinFloatLiteral
> /swift/stdlib/public/core/CompilerProtocols.swift:283 
> _ExpressibleByBuiltinBooleanLiteral
> /swift/stdlib/public/core/CompilerProtocols.swift:316 
> _ExpressibleByBuiltinUnicodeScalarLiteral
> /swift/stdlib/public/core/CompilerProtocols.swift:350 
> _ExpressibleByBuiltinExtendedGraphemeClusterLiteral
> /swift/stdlib/public/core/CompilerProtocols.swift:398 
> _ExpressibleByBuiltinStringLiteral
> /swift/stdlib/public/core/CompilerProtocols.swift:407 
> _ExpressibleByBuiltinUTF16StringLiteral
> /swift/stdlib/public/core/CompilerProtocols.swift:670 
> _ExpressibleByStringInterpolation
> /swift/stdlib/public/core/CompilerProtocols.swift:709 
> _ExpressibleByColorLiteral
> /swift/stdlib/public/core/CompilerProtocols.swift:720 
> _ExpressibleByImageLiteral
> /swift/stdlib/public/core/CompilerProtocols.swift:730 
> _ExpressibleByFileReferenceLiteral
> /swift/stdlib/public/core/CompilerProtocols.swift:750 _DestructorSafeContainer
> /swift/stdlib/public/core/FixedPoint.swift.gyb:53 _Integer
> /swift/stdlib/public/core/FixedPoint.swift.gyb:70 _SignedInteger
> /swift/stdlib/public/core/FixedPoint.swift.gyb:108
> 

Re: [swift-evolution] [Draft] open and public protocols

2017-02-19 Thread Adrian Zubarev via swift-evolution
The are no reasons to allow that to the client. A key is a String and an index 
is an Int. I don’t see any point why the client would need its own model of 
generating a String or an Int. The usage of that protocol is a limitation of 
the language because we don’t support Either types, so I fall back to 
existentials.



-- 
Adrian Zubarev
Sent with Airmail

Am 19. Februar 2017 um 17:40:01, David Hart (da...@hartbit.com) schrieb:



On 19 Feb 2017, at 17:00, Adrian Zubarev  
wrote:

In my case we don’t have an Either type, nor do we allow implicit type 
conversions. Remove the property from my protocol and forget about the enum 
that I used there. Conform to the protocol in your app a type different from 
String or Int and call the subscript. This will result in a runtime crash, 
because the API won’t know what do to with your type. Sure it could return nil, 
but then I can only say “happy debugging to find your wrong type”.

But isn't the either type the right solution to make sure you always get the 
output type you expect while allowing clients to provide custom type that 
conform to the protocol and generate your expected types (string and ont) in 
interesting ways?

The usage of the protocol is simply an implementation artifact, because there 
is no other way (except crazy long overloads) of creating such a subscript that 
accepts a String or an Int from the second parameter. The protocol was never 
meant to be conformable to outside the API itself.

The requirement that the protocol has in my example was the workaround to 
prevent the crash and iff you device to conform to that protocol, which, as I 
already mentioned, is not intended at all.

I can only repeat myself: if you haven’t bumped into such an issue, than call 
yourself lucky.



-- 
Adrian Zubarev
Sent with Airmail

Am 19. Februar 2017 um 16:05:28, David Hart (da...@hartbit.com) schrieb:

I'm sorry but I'm really lost: in your example, how could the client break the 
library by providing a custom type that conforms to the protocol? Why do you 
say that something like KeyConvertible shouldn't even exist? They exist so 
clients can extend libraires and make them even more useful. I still haven't 
seen a case where it's necessary to avoid clients to conform to a protocol.

On 19 Feb 2017, at 14:02, Adrian Zubarev  
wrote:

That won’t work, plus the suggested solution makes life even more complicated. 
I need to be able to index an array, so I’m not willing to simply give up 
integers and do some extra work behind the scenes and convert a String to an 
Int. Furthermore there is no need something like KeyConvertible to even exist.



-- 
Adrian Zubarev
Sent with Airmail

Am 19. Februar 2017 um 13:58:35, David Hart (da...@hartbit.com) schrieb:

I honestly don't see the use case. The example you showed is an example of how 
your circumvented the lack of "closed" protocols in Swift. But I'd really like 
to see an example of the necessity for closed protocols in the first place:

In your case, I would simply defined the API as:

protocol KeyConvertible {
    var key: String { get }
}

public subscript(firstKey: String, parameters: KeyConvertible...) {}

Which would allow clients to implement their own KeyConvertible conforming 
types which convert into key paths.

On 19 Feb 2017, at 09:14, Adrian Zubarev via swift-evolution 
 wrote:

If you haven’t followed the other thread Matthew previously opened than you 
have missed the example I showed there.

Here it is again:

public protocol SubscriptParameterType {
 
// This property was needed to prevent the client from breaking
// the library by conforming to the protocol, but I'd like to  
// keep it invisible for the client, or even better prevent the
// client from conforming to the protocol.
var parameter: Document.SubscriptParameter { get }
}

extension Document {
 
public enum SubscriptParameter {
 
case string(String)
case integer(Int)
}
}

extension String : SubscriptParameterType {
 
public var parameter: Document.SubscriptParameter {
 
return .string(self)
}
}

extension Int : SubscriptParameterType {
 
public var parameter: Document.SubscriptParameter {
 
return .integer(self)
}
}

// Somewhere inside the `Document` type
public subscript(firstKey: String, parameters: SubscriptParameterType...) -> 
Value? { … }
The absence of closed protocols forced me to create a special requirement on 
that protocol to prevent the client from conforming to that protocol and 
passing instances of other types my API wouldn’t want to deal with. That 
creates unnecessary copies and I need to unpack the enum payload to find out 
which type the user passed. Instead I could simply close the protocol, wouldn’t 
need the requirement to exist and I could simply cast the type 

Re: [swift-evolution] [Draft] open and public protocols

2017-02-19 Thread David Hart via swift-evolution


> On 19 Feb 2017, at 17:00, Adrian Zubarev  
> wrote:
> 
> In my case we don’t have an Either type, nor do we allow implicit type 
> conversions. Remove the property from my protocol and forget about the enum 
> that I used there. Conform to the protocol in your app a type different from 
> String or Int and call the subscript. This will result in a runtime crash, 
> because the API won’t know what do to with your type. Sure it could return 
> nil, but then I can only say “happy debugging to find your wrong type”.
> 
But isn't the either type the right solution to make sure you always get the 
output type you expect while allowing clients to provide custom type that 
conform to the protocol and generate your expected types (string and ont) in 
interesting ways?

> The usage of the protocol is simply an implementation artifact, because there 
> is no other way (except crazy long overloads) of creating such a subscript 
> that accepts a String or an Int from the second parameter. The protocol was 
> never meant to be conformable to outside the API itself.
> 
> The requirement that the protocol has in my example was the workaround to 
> prevent the crash and iff you device to conform to that protocol, which, as I 
> already mentioned, is not intended at all.
> 
> I can only repeat myself: if you haven’t bumped into such an issue, than call 
> yourself lucky.
> 
> 
> 
> -- 
> Adrian Zubarev
> Sent with Airmail
> 
> Am 19. Februar 2017 um 16:05:28, David Hart (da...@hartbit.com) schrieb:
> 
>> I'm sorry but I'm really lost: in your example, how could the client break 
>> the library by providing a custom type that conforms to the protocol? Why do 
>> you say that something like KeyConvertible shouldn't even exist? They exist 
>> so clients can extend libraires and make them even more useful. I still 
>> haven't seen a case where it's necessary to avoid clients to conform to a 
>> protocol.
>> 
>> On 19 Feb 2017, at 14:02, Adrian Zubarev  
>> wrote:
>> 
>>> That won’t work, plus the suggested solution makes life even more 
>>> complicated. I need to be able to index an array, so I’m not willing to 
>>> simply give up integers and do some extra work behind the scenes and 
>>> convert a String to an Int. Furthermore there is no need something like 
>>> KeyConvertible to even exist.
>>> 
>>> 
>>> 
>>> -- 
>>> Adrian Zubarev
>>> Sent with Airmail
>>> 
>>> Am 19. Februar 2017 um 13:58:35, David Hart (da...@hartbit.com) schrieb:
>>> 
 I honestly don't see the use case. The example you showed is an example of 
 how your circumvented the lack of "closed" protocols in Swift. But I'd 
 really like to see an example of the necessity for closed protocols in the 
 first place:
 
 In your case, I would simply defined the API as:
 
 protocol KeyConvertible {
 var key: String { get }
 }
 
 public subscript(firstKey: String, parameters: KeyConvertible...) {}
 
 Which would allow clients to implement their own KeyConvertible conforming 
 types which convert into key paths.
 
 On 19 Feb 2017, at 09:14, Adrian Zubarev via swift-evolution 
  wrote:
 
> If you haven’t followed the other thread Matthew previously opened than 
> you have missed the example I showed there.
> 
> Here it is again:
> 
> public protocol SubscriptParameterType {
> 
> // This property was needed to prevent the client from breaking
> // the library by conforming to the protocol, but I'd like to 
> // keep it invisible for the client, or even better prevent the
> // client from conforming to the protocol.
> var parameter: Document.SubscriptParameter { get }
> }
> 
> extension Document {
> 
> public enum SubscriptParameter {
> 
> case string(String)
> case integer(Int)
> }
> }
> 
> extension String : SubscriptParameterType {
> 
> public var parameter: Document.SubscriptParameter {
> 
> return .string(self)
> }
> }
> 
> extension Int : SubscriptParameterType {
> 
> public var parameter: Document.SubscriptParameter {
> 
> return .integer(self)
> }
> }
> 
> // Somewhere inside the `Document` type
> public subscript(firstKey: String, parameters: SubscriptParameterType...) 
> -> Value? { … }
> The absence of closed protocols forced me to create a special requirement 
> on that protocol to prevent the client from conforming to that protocol 
> and passing instances of other types my API wouldn’t want to deal with. 
> That creates unnecessary copies and I need to unpack the enum payload to 
> find out which type the user passed. Instead I could simply close the 

Re: [swift-evolution] [Draft] open and public protocols

2017-02-19 Thread Adrian Zubarev via swift-evolution
Still not what I was asking about.

Module A contains a single open protocol: open protocol P { func foo() }
Module B contains a single open class that conforms to P:
open class B : P {
/* what is the default access modifier here? */ func foo()
}


-- 
Adrian Zubarev
Sent with Airmail

Am 19. Februar 2017 um 17:35:04, Matthew Johnson (matt...@anandabits.com) 
schrieb:



Sent from my iPhone

On Feb 19, 2017, at 10:28 AM, Adrian Zubarev  
wrote:

I really feel I’m blind, I cannot find it. Is the access modifier of open 
protocol *members* on open/public classes public by default, or open?

If open, can we downgrade it to public in an open class?

I didn't specifically address members of open classes but did address open 
classes.  This proposal does not have any impact of the visibility of members 
of open classes that conform to a public (nonopen) protocol, including the 
default.


-- 
Adrian Zubarev
Sent with Airmail

Am 19. Februar 2017 um 17:16:59, Matthew Johnson (matt...@anandabits.com) 
schrieb:



Sent from my iPhone

On Feb 19, 2017, at 10:11 AM, Adrian Zubarev  
wrote:

@Matthew: Have you considered what happens with the access modifier of an open 
protocol when an open/public class conforms to it?


Yes I covered this in the detailed design section of the proposal.
 // Module A
open protocol A {
func foo()
}

// Module B
open class B : A {
(open or public) func foo() {}
// If `open`, can we downgrade to `public`?
// The other way around seems straightforward
}
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft] open and public protocols

2017-02-19 Thread David Hart via swift-evolution
This makes more sense already. But in this case, wouldn't I be interested, as a 
client, in creating my own TextStreams, some of which might write to a custom 
log file, to a web service, etc... ?

> On 19 Feb 2017, at 17:00, Karl Wagner  wrote:
> 
> 
>> On 19 Feb 2017, at 16:17, David Hart via swift-evolution 
>>  wrote:
>> 
>> I still don't see the use case for this. Perhaps I'm wrong, but if an API 
>> creates a protocol for the sole purpose of representing a set of concrete 
>> types, that looks more to me like bad API design, and not a missing feature 
>> in the language. Can you give me a small concrete real-world example of an 
>> API which requires that? 
> 
> 
> Whether or not a protocol is open is also a part of API expressivity; often a 
> library will want to expose a protocol only as a way to enable 
> generic/existential programming over a fixed set of types, without intending 
> that any clients add new conformers. Protocols are crucial to expressing the 
> shared patterns amongst the set of types.
> 
> For example, I might have a TextStream protocol:
> 
> public protocol TextStream {
> func write(_: String)
> }
> 
> And I might decide to expose a property as type “TextStream” purely because I 
> reserve the right to change the underlying concrete type. I want clients to 
> work on the protocol-existential level.
> 
> public class Component {
> var debugWriter: TextStream
> }
> 
> By doing that, the underlying concrete type is no longer part of my API or 
> ABI. I can change it between versions without breaking clients, but it’s not 
> meaningful for any clients to create their own TextStreams; that’s not part 
> of what my library does/allows.
> 
> - Karl
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft] open and public protocols

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


Sent from my iPhone

> On Feb 19, 2017, at 10:28 AM, Adrian Zubarev 
>  wrote:
> 
> I really feel I’m blind, I cannot find it. Is the access modifier of open 
> protocol *members* on open/public classes public by default, or open?
> 
> If open, can we downgrade it to public in an open class?

I didn't specifically address members of open classes but did address open 
classes.  This proposal does not have any impact of the visibility of members 
of open classes that conform to a public (nonopen) protocol, including the 
default.
> 
> 
> -- 
> Adrian Zubarev
> Sent with Airmail
> 
> Am 19. Februar 2017 um 17:16:59, Matthew Johnson (matt...@anandabits.com) 
> schrieb:
> 
>> 
>> 
>> Sent from my iPhone
>> 
>> On Feb 19, 2017, at 10:11 AM, Adrian Zubarev 
>>  wrote:
>> 
>>> @Matthew: Have you considered what happens with the access modifier of an 
>>> open protocol when an open/public class conforms to it?
>>> 
>> 
>> Yes I covered this in the detailed design section of the proposal.
>>> // Module A
>>> open protocol A {
>>> func foo()
>>> }
>>> 
>>> // Module B
>>> open class B : A {
>>> (open or public) func foo() {}
>>> // If `open`, can we downgrade to `public`?
>>> // The other way around seems straightforward   
>>> }
> 
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft] open and public protocols

2017-02-19 Thread Adrian Zubarev via swift-evolution
I really feel I’m blind, I cannot find it. Is the access modifier of open 
protocol *members* on open/public classes public by default, or open?

If open, can we downgrade it to public in an open class?


-- 
Adrian Zubarev
Sent with Airmail

Am 19. Februar 2017 um 17:16:59, Matthew Johnson (matt...@anandabits.com) 
schrieb:



Sent from my iPhone

On Feb 19, 2017, at 10:11 AM, Adrian Zubarev  
wrote:

@Matthew: Have you considered what happens with the access modifier of an open 
protocol when an open/public class conforms to it?


Yes I covered this in the detailed design section of the proposal.
// Module A
open protocol A {
func foo()
}

// Module B
open class B : A {
(open or public) func foo() {}
// If `open`, can we downgrade to `public`?
// The other way around seems straightforward   
}
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft] open and public protocols

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


Sent from my iPhone

> On Feb 19, 2017, at 10:11 AM, Adrian Zubarev 
>  wrote:
> 
> @Matthew: Have you considered what happens with the access modifier of an 
> open protocol when an open/public class conforms to it?
> 

Yes I covered this in the detailed design section of the proposal.
> // Module A
> open protocol A {
> func foo()
> }
> 
> // Module B
> open class B : A {
> (open or public) func foo() {}
> // If `open`, can we downgrade to `public`?
> // The other way around seems straightforward  
> }
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft] open and public protocols

2017-02-19 Thread Adrian Zubarev via swift-evolution
@Matthew: Have you considered what happens with the access modifier of an open 
protocol when an open/public class conforms to it?

// Module A
open protocol A {
func foo()
}

// Module B
open class B : A {
(open or public) func foo() {}
// If `open`, can we downgrade to `public`?
// The other way around seems straightforward 
}
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft] open and public protocols

2017-02-19 Thread Karl Wagner via swift-evolution

> On 19 Feb 2017, at 16:17, David Hart via swift-evolution 
>  wrote:
> 
> I still don't see the use case for this. Perhaps I'm wrong, but if an API 
> creates a protocol for the sole purpose of representing a set of concrete 
> types, that looks more to me like bad API design, and not a missing feature 
> in the language. Can you give me a small concrete real-world example of an 
> API which requires that? 


Whether or not a protocol is open is also a part of API expressivity; often a 
library will want to expose a protocol only as a way to enable 
generic/existential programming over a fixed set of types, without intending 
that any clients add new conformers. Protocols are crucial to expressing the 
shared patterns amongst the set of types.

For example, I might have a TextStream protocol:

public protocol TextStream {
func write(_: String)
}

And I might decide to expose a property as type “TextStream” purely because I 
reserve the right to change the underlying concrete type. I want clients to 
work on the protocol-existential level.

public class Component {
var debugWriter: TextStream
}

By doing that, the underlying concrete type is no longer part of my API or ABI. 
I can change it between versions without breaking clients, but it’s not 
meaningful for any clients to create their own TextStreams; that’s not part of 
what my library does/allows.

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


Re: [swift-evolution] [Draft] open and public protocols

2017-02-19 Thread Adrian Zubarev via swift-evolution
In my case we don’t have an Either type, nor do we allow implicit type 
conversions. Remove the property from my protocol and forget about the enum 
that I used there. Conform to the protocol in your app a type different from 
String or Int and call the subscript. This will result in a runtime crash, 
because the API won’t know what do to with your type. Sure it could return nil, 
but then I can only say “happy debugging to find your wrong type”.

The usage of the protocol is simply an implementation artifact, because there 
is no other way (except crazy long overloads) of creating such a subscript that 
accepts a String or an Int from the second parameter. The protocol was never 
meant to be conformable to outside the API itself.

The requirement that the protocol has in my example was the workaround to 
prevent the crash and iff you device to conform to that protocol, which, as I 
already mentioned, is not intended at all.

I can only repeat myself: if you haven’t bumped into such an issue, than call 
yourself lucky.



-- 
Adrian Zubarev
Sent with Airmail

Am 19. Februar 2017 um 16:05:28, David Hart (da...@hartbit.com) schrieb:

I'm sorry but I'm really lost: in your example, how could the client break the 
library by providing a custom type that conforms to the protocol? Why do you 
say that something like KeyConvertible shouldn't even exist? They exist so 
clients can extend libraires and make them even more useful. I still haven't 
seen a case where it's necessary to avoid clients to conform to a protocol.

On 19 Feb 2017, at 14:02, Adrian Zubarev  
wrote:

That won’t work, plus the suggested solution makes life even more complicated. 
I need to be able to index an array, so I’m not willing to simply give up 
integers and do some extra work behind the scenes and convert a String to an 
Int. Furthermore there is no need something like KeyConvertible to even exist.



-- 
Adrian Zubarev
Sent with Airmail

Am 19. Februar 2017 um 13:58:35, David Hart (da...@hartbit.com) schrieb:

I honestly don't see the use case. The example you showed is an example of how 
your circumvented the lack of "closed" protocols in Swift. But I'd really like 
to see an example of the necessity for closed protocols in the first place:

In your case, I would simply defined the API as:

protocol KeyConvertible {
    var key: String { get }
}

public subscript(firstKey: String, parameters: KeyConvertible...) {}

Which would allow clients to implement their own KeyConvertible conforming 
types which convert into key paths.

On 19 Feb 2017, at 09:14, Adrian Zubarev via swift-evolution 
 wrote:

If you haven’t followed the other thread Matthew previously opened than you 
have missed the example I showed there.

Here it is again:

public protocol SubscriptParameterType {

// This property was needed to prevent the client from breaking
// the library by conforming to the protocol, but I'd like to 
// keep it invisible for the client, or even better prevent the
// client from conforming to the protocol.
var parameter: Document.SubscriptParameter { get }
}

extension Document {

public enum SubscriptParameter {

case string(String)
case integer(Int)
}
}

extension String : SubscriptParameterType {

public var parameter: Document.SubscriptParameter {

return .string(self)
}
}

extension Int : SubscriptParameterType {

public var parameter: Document.SubscriptParameter {

return .integer(self)
}
}

// Somewhere inside the `Document` type
public subscript(firstKey: String, parameters: SubscriptParameterType...) -> 
Value? { … }
The absence of closed protocols forced me to create a special requirement on 
that protocol to prevent the client from conforming to that protocol and 
passing instances of other types my API wouldn’t want to deal with. That 
creates unnecessary copies and I need to unpack the enum payload to find out 
which type the user passed. Instead I could simply close the protocol, wouldn’t 
need the requirement to exist and I could simply cast the type to String or Int 
when needed.

That implementation enables more safe queries of my Document type like

document["key1", intIndexInstance, stringKeyInstance, 10, "key"]

rather than

document["key1/\(intIndexInstance)/\(stringKeyInstance)/10/key"].

Here is a list of hidden and semi-hidden protocols from the standard library 
that could be closed. Formatted version: 
https://gist.github.com/DevAndArtist/168c800d784829be536c407311953ab7

PathProtocol
/swift/stdlib/public/core/AnyHashable.swift:16  
_HasCustomAnyHashableRepresentation
/swift/stdlib/public/core/BidirectionalCollection.swift:21  
_BidirectionalIndexable
/swift/stdlib/public/core/BridgeObjectiveC.swift:19 _ObjectiveCBridgeable
/swift/stdlib/public/core/Collection.swift:20   _IndexableBase

Re: [swift-evolution] [Draft] open and public protocols

2017-02-19 Thread Matthew Johnson via swift-evolution
Sure.  For example, maybe I have a UI widget that can display a collection of 
items that the user can configure.  Maybe they need to be in a sequence but can 
only be one of a fixed set of types defined by the library (artist, album 
song), etc.  I do not want the user to be able to add to the set of types but I 
do want them to be able to provide a heterogeneous collection of instances to 
display in the UI.

Sent from my iPad

> On Feb 19, 2017, at 9:17 AM, David Hart  wrote:
> 
> I still don't see the use case for this. Perhaps I'm wrong, but if an API 
> creates a protocol for the sole purpose of representing a set of concrete 
> types, that looks more to me like bad API design, and not a missing feature 
> in the language. Can you give me a small concrete real-world example of an 
> API which requires that? 
> 
>> On 19 Feb 2017, at 16:10, Matthew Johnson via swift-evolution 
>>  wrote:
>> 
>> 
>> 
>> Sent from my iPad
>> 
>>> On Feb 19, 2017, at 12:58 AM, David Waite  
>>> wrote:
>>> 
>>> I am unsure if this feature is a good idea. Does someone have a real-world 
>>> use for this which isn’t just hiding strong implementation coupling behind 
>>> a protocol?
>> 
>> Yes.  If this proposal moves ahead we can implement an API that takes a 
>> hereogenous collection with implicit conversion for several different 
>> concrete types while ensuring that all elements are of a type provided by 
>> the library:
>> 
>> public protocol Foo {}
>> public struct One: Foo {}
>> public struct Two: Foo {}
>> // other conforming types in the library
>> 
>> func takesFoos(_ foos: [Foo]) {}
>> 
>> // in user code:
>> takesFoos([One(), One(), Two(), One()])
>> 
>> This use case could be subsumed by enums if we implement some of the ideas 
>> in my value subtyping manifesto but those are for the future and may or may 
>> not be accepted.  This is a relatively small change that can e made in Swift 
>> 4.
>> 
>>> When I consume a protocol, it is under the assumption that the protocol is 
>>> documented such that I would be able to work against *any* implementation 
>>> of the protocol. With a closed protocol, I would have to assume that there 
>>> are significant side effects, either undocumented or difficult for a third 
>>> party to duplicate. To my experience, that sounds brittle.
>>> 
>>> Assuming you aren’t switching on the implementing type of a protocol (which 
>>> itself can be a sign that your design isn’t properly using polymorphism), 
>>> one could get this design by creating a struct with the interface desired, 
>>> and passing invocations through to an internal protocol reference.
>>> 
>>> -DW
>>> 
 On Feb 18, 2017, at 1:41 PM, Matthew Johnson via swift-evolution 
  wrote:
 
 Now that we’re in phase 2 I’d like to officially propose we introduce 
 `open` protocols and require conformances to  `public` protocols be inside 
 the declaring module.  Let’s use this thread for feedback on the official 
 proposal.  After a healthy round of discussion I’ll open a PR to submit it 
 for review.
 
 
 # Feature name
 
 * Proposal: [SE-](-open-public-protocols.md)
 * Authors: [Matthew Johnson](https://github.com/anandabits)
 * Review Manager: TBD
 * Status: **Awaiting review**
 
 ## Introduction
 
 This proposal introduces `open protocol` and changes the meaning of 
 `public protocol` to match the meaning of `public class` (in this case, 
 conformances are only allowed inside the declaring module).
 
 The pitch thread leading up to this proposal was: [consistent public 
 access 
 modifiers](https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170206/031653.html)
 
 ## Motivation
 
 A general principle the Swift community has adopted for access control is 
 that defaults should reserve maximum flexibility for a library.  The 
 ensures that any capabilities beyond mere visibility are not available 
 unless the author of the library has explicitly declared their intent that 
 the capabilities be made available.  Finally, when it is possible to 
 switch from one semantic to another without breaking clients (but not 
 vice-versa) we should prefer the more forgiving (i.e. fixable) semantic as 
 the (soft) default.
 
 `public` is considered a "soft default" in the sense that it is the first 
 access modifier a user will reach for when exposing a declaration outside 
 of the module.  In the case of protocols the current meaning of `public` 
 does not meet the principle of preserving maximum flexibility for the 
 author of the library.  It allows users of the library to conform to the 
 protocol.
 
 There are good reasons a library may not wish to allow users to add 
 conformances to a protocol.  For example, it may not wish to 

Re: [swift-evolution] [Draft] open and public protocols

2017-02-19 Thread David Hart via swift-evolution
I still don't see the use case for this. Perhaps I'm wrong, but if an API 
creates a protocol for the sole purpose of representing a set of concrete 
types, that looks more to me like bad API design, and not a missing feature in 
the language. Can you give me a small concrete real-world example of an API 
which requires that? 

> On 19 Feb 2017, at 16:10, Matthew Johnson via swift-evolution 
>  wrote:
> 
> 
> 
> Sent from my iPad
> 
>> On Feb 19, 2017, at 12:58 AM, David Waite  
>> wrote:
>> 
>> I am unsure if this feature is a good idea. Does someone have a real-world 
>> use for this which isn’t just hiding strong implementation coupling behind a 
>> protocol?
> 
> Yes.  If this proposal moves ahead we can implement an API that takes a 
> hereogenous collection with implicit conversion for several different 
> concrete types while ensuring that all elements are of a type provided by the 
> library:
> 
> public protocol Foo {}
> public struct One: Foo {}
> public struct Two: Foo {}
> // other conforming types in the library
> 
> func takesFoos(_ foos: [Foo]) {}
> 
> // in user code:
> takesFoos([One(), One(), Two(), One()])
> 
> This use case could be subsumed by enums if we implement some of the ideas in 
> my value subtyping manifesto but those are for the future and may or may not 
> be accepted.  This is a relatively small change that can e made in Swift 4.
> 
>> When I consume a protocol, it is under the assumption that the protocol is 
>> documented such that I would be able to work against *any* implementation of 
>> the protocol. With a closed protocol, I would have to assume that there are 
>> significant side effects, either undocumented or difficult for a third party 
>> to duplicate. To my experience, that sounds brittle.
>> 
>> Assuming you aren’t switching on the implementing type of a protocol (which 
>> itself can be a sign that your design isn’t properly using polymorphism), 
>> one could get this design by creating a struct with the interface desired, 
>> and passing invocations through to an internal protocol reference.
>> 
>> -DW
>> 
>>> On Feb 18, 2017, at 1:41 PM, Matthew Johnson via swift-evolution 
>>>  wrote:
>>> 
>>> Now that we’re in phase 2 I’d like to officially propose we introduce 
>>> `open` protocols and require conformances to  `public` protocols be inside 
>>> the declaring module.  Let’s use this thread for feedback on the official 
>>> proposal.  After a healthy round of discussion I’ll open a PR to submit it 
>>> for review.
>>> 
>>> 
>>> # Feature name
>>> 
>>> * Proposal: [SE-](-open-public-protocols.md)
>>> * Authors: [Matthew Johnson](https://github.com/anandabits)
>>> * Review Manager: TBD
>>> * Status: **Awaiting review**
>>> 
>>> ## Introduction
>>> 
>>> This proposal introduces `open protocol` and changes the meaning of `public 
>>> protocol` to match the meaning of `public class` (in this case, 
>>> conformances are only allowed inside the declaring module).
>>> 
>>> The pitch thread leading up to this proposal was: [consistent public access 
>>> modifiers](https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170206/031653.html)
>>> 
>>> ## Motivation
>>> 
>>> A general principle the Swift community has adopted for access control is 
>>> that defaults should reserve maximum flexibility for a library.  The 
>>> ensures that any capabilities beyond mere visibility are not available 
>>> unless the author of the library has explicitly declared their intent that 
>>> the capabilities be made available.  Finally, when it is possible to switch 
>>> from one semantic to another without breaking clients (but not vice-versa) 
>>> we should prefer the more forgiving (i.e. fixable) semantic as the (soft) 
>>> default.
>>> 
>>> `public` is considered a "soft default" in the sense that it is the first 
>>> access modifier a user will reach for when exposing a declaration outside 
>>> of the module.  In the case of protocols the current meaning of `public` 
>>> does not meet the principle of preserving maximum flexibility for the 
>>> author of the library.  It allows users of the library to conform to the 
>>> protocol.
>>> 
>>> There are good reasons a library may not wish to allow users to add 
>>> conformances to a protocol.  For example, it may not wish to expose the 
>>> conforming concrete types.  While similar behavior could be accomplished 
>>> with an enum if cases could be private, that requires an implementation to 
>>> use switch statements rather than polymorphism.
>>> 
>>> Even if all the conforming types are also public there are cases where 
>>> polymorphism is the preferred implementation.  For example, if the set of 
>>> conforming types is not expected to be fixed (despite all being inside the 
>>> library) the authors may not want to have to maintain switch statements 
>>> every time they need to add or remove a confroming type which would be 
>>> 

Re: [swift-evolution] [Draft] open and public protocols

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


Sent from my iPad

> On Feb 19, 2017, at 12:58 AM, David Waite  
> wrote:
> 
> I am unsure if this feature is a good idea. Does someone have a real-world 
> use for this which isn’t just hiding strong implementation coupling behind a 
> protocol?

Yes.  If this proposal moves ahead we can implement an API that takes a 
hereogenous collection with implicit conversion for several different concrete 
types while ensuring that all elements are of a type provided by the library:

public protocol Foo {}
public struct One: Foo {}
public struct Two: Foo {}
// other conforming types in the library

func takesFoos(_ foos: [Foo]) {}

// in user code:
takesFoos([One(), One(), Two(), One()])

This use case could be subsumed by enums if we implement some of the ideas in 
my value subtyping manifesto but those are for the future and may or may not be 
accepted.  This is a relatively small change that can e made in Swift 4.

> When I consume a protocol, it is under the assumption that the protocol is 
> documented such that I would be able to work against *any* implementation of 
> the protocol. With a closed protocol, I would have to assume that there are 
> significant side effects, either undocumented or difficult for a third party 
> to duplicate. To my experience, that sounds brittle.
> 
> Assuming you aren’t switching on the implementing type of a protocol (which 
> itself can be a sign that your design isn’t properly using polymorphism), one 
> could get this design by creating a struct with the interface desired, and 
> passing invocations through to an internal protocol reference.
> 
> -DW
> 
>> On Feb 18, 2017, at 1:41 PM, Matthew Johnson via swift-evolution 
>>  wrote:
>> 
>> Now that we’re in phase 2 I’d like to officially propose we introduce `open` 
>> protocols and require conformances to  `public` protocols be inside the 
>> declaring module.  Let’s use this thread for feedback on the official 
>> proposal.  After a healthy round of discussion I’ll open a PR to submit it 
>> for review.
>> 
>> 
>> # Feature name
>> 
>> * Proposal: [SE-](-open-public-protocols.md)
>> * Authors: [Matthew Johnson](https://github.com/anandabits)
>> * Review Manager: TBD
>> * Status: **Awaiting review**
>> 
>> ## Introduction
>> 
>> This proposal introduces `open protocol` and changes the meaning of `public 
>> protocol` to match the meaning of `public class` (in this case, conformances 
>> are only allowed inside the declaring module).
>> 
>> The pitch thread leading up to this proposal was: [consistent public access 
>> modifiers](https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170206/031653.html)
>> 
>> ## Motivation
>> 
>> A general principle the Swift community has adopted for access control is 
>> that defaults should reserve maximum flexibility for a library.  The ensures 
>> that any capabilities beyond mere visibility are not available unless the 
>> author of the library has explicitly declared their intent that the 
>> capabilities be made available.  Finally, when it is possible to switch from 
>> one semantic to another without breaking clients (but not vice-versa) we 
>> should prefer the more forgiving (i.e. fixable) semantic as the (soft) 
>> default.
>> 
>> `public` is considered a "soft default" in the sense that it is the first 
>> access modifier a user will reach for when exposing a declaration outside of 
>> the module.  In the case of protocols the current meaning of `public` does 
>> not meet the principle of preserving maximum flexibility for the author of 
>> the library.  It allows users of the library to conform to the protocol.
>> 
>> There are good reasons a library may not wish to allow users to add 
>> conformances to a protocol.  For example, it may not wish to expose the 
>> conforming concrete types.  While similar behavior could be accomplished 
>> with an enum if cases could be private, that requires an implementation to 
>> use switch statements rather than polymorphism.
>> 
>> Even if all the conforming types are also public there are cases where 
>> polymorphism is the preferred implementation.  For example, if the set of 
>> conforming types is not expected to be fixed (despite all being inside the 
>> library) the authors may not want to have to maintain switch statements 
>> every time they need to add or remove a confroming type which would be 
>> necessary if an enum were used instead.  Polymorphism allows us to avoid 
>> this, giving us the ability to add and remove conforming types within the 
>> implementation of the library without the burden of maintaining switch 
>> statements.
>> 
>> Aligning the access modifiers for protocols and classes allows us to specify 
>> both conformable and non-conformable protocols, provides a soft default that 
>> is consistent with the principle of (soft) defaults reserving maximum 
>> flexibility for the library, and increases the overall consistency of the 
>> 

Re: [swift-evolution] [Draft] open and public protocols

2017-02-19 Thread David Hart via swift-evolution
I'm sorry but I'm really lost: in your example, how could the client break the 
library by providing a custom type that conforms to the protocol? Why do you 
say that something like KeyConvertible shouldn't even exist? They exist so 
clients can extend libraires and make them even more useful. I still haven't 
seen a case where it's necessary to avoid clients to conform to a protocol.

> On 19 Feb 2017, at 14:02, Adrian Zubarev  
> wrote:
> 
> That won’t work, plus the suggested solution makes life even more 
> complicated. I need to be able to index an array, so I’m not willing to 
> simply give up integers and do some extra work behind the scenes and convert 
> a String to an Int. Furthermore there is no need something like 
> KeyConvertible to even exist.
> 
> 
> 
> -- 
> Adrian Zubarev
> Sent with Airmail
> 
> Am 19. Februar 2017 um 13:58:35, David Hart (da...@hartbit.com) schrieb:
> 
>> I honestly don't see the use case. The example you showed is an example of 
>> how your circumvented the lack of "closed" protocols in Swift. But I'd 
>> really like to see an example of the necessity for closed protocols in the 
>> first place:
>> 
>> In your case, I would simply defined the API as:
>> 
>> protocol KeyConvertible {
>> var key: String { get }
>> }
>> 
>> public subscript(firstKey: String, parameters: KeyConvertible...) {}
>> 
>> Which would allow clients to implement their own KeyConvertible conforming 
>> types which convert into key paths.
>> 
>> On 19 Feb 2017, at 09:14, Adrian Zubarev via swift-evolution 
>>  wrote:
>> 
>>> If you haven’t followed the other thread Matthew previously opened than you 
>>> have missed the example I showed there.
>>> 
>>> Here it is again:
>>> 
>>> public protocol SubscriptParameterType {
>>>
>>> // This property was needed to prevent the client from breaking
>>> // the library by conforming to the protocol, but I'd like to
>>> // keep it invisible for the client, or even better prevent the
>>> // client from conforming to the protocol.
>>> var parameter: Document.SubscriptParameter { get }
>>> }
>>> 
>>> extension Document {
>>>
>>> public enum SubscriptParameter {
>>>
>>> case string(String)
>>> case integer(Int)
>>> }
>>> }
>>> 
>>> extension String : SubscriptParameterType {
>>>
>>> public var parameter: Document.SubscriptParameter {
>>>
>>> return .string(self)
>>> }
>>> }
>>> 
>>> extension Int : SubscriptParameterType {
>>>
>>> public var parameter: Document.SubscriptParameter {
>>>
>>> return .integer(self)
>>> }
>>> }
>>> 
>>> // Somewhere inside the `Document` type
>>> public subscript(firstKey: String, parameters: SubscriptParameterType...) 
>>> -> Value? { … }
>>> The absence of closed protocols forced me to create a special requirement 
>>> on that protocol to prevent the client from conforming to that protocol and 
>>> passing instances of other types my API wouldn’t want to deal with. That 
>>> creates unnecessary copies and I need to unpack the enum payload to find 
>>> out which type the user passed. Instead I could simply close the protocol, 
>>> wouldn’t need the requirement to exist and I could simply cast the type to 
>>> String or Int when needed.
>>> 
>>> That implementation enables more safe queries of my Document type like
>>> 
>>> document["key1", intIndexInstance, stringKeyInstance, 10, "key"]
>>> 
>>> rather than
>>> 
>>> document["key1/\(intIndexInstance)/\(stringKeyInstance)/10/key"].
>>> 
>>> Here is a list of hidden and semi-hidden protocols from the standard 
>>> library that could be closed. Formatted version: 
>>> https://gist.github.com/DevAndArtist/168c800d784829be536c407311953ab7
>>> 
>>> PathProtocol
>>> /swift/stdlib/public/core/AnyHashable.swift:16  
>>> _HasCustomAnyHashableRepresentation
>>> /swift/stdlib/public/core/BidirectionalCollection.swift:21  
>>> _BidirectionalIndexable
>>> /swift/stdlib/public/core/BridgeObjectiveC.swift:19 _ObjectiveCBridgeable
>>> /swift/stdlib/public/core/Collection.swift:20   _IndexableBase
>>> /swift/stdlib/public/core/Collection.swift:176  _Indexable
>>> /swift/stdlib/public/core/CompilerProtocols.swift:193   
>>> _ExpressibleByBuiltinIntegerLiteral
>>> /swift/stdlib/public/core/CompilerProtocols.swift:240   
>>> _ExpressibleByBuiltinFloatLiteral
>>> /swift/stdlib/public/core/CompilerProtocols.swift:283   
>>> _ExpressibleByBuiltinBooleanLiteral
>>> /swift/stdlib/public/core/CompilerProtocols.swift:316   
>>> _ExpressibleByBuiltinUnicodeScalarLiteral
>>> /swift/stdlib/public/core/CompilerProtocols.swift:350   
>>> _ExpressibleByBuiltinExtendedGraphemeClusterLiteral
>>> /swift/stdlib/public/core/CompilerProtocols.swift:398   
>>> _ExpressibleByBuiltinStringLiteral
>>> /swift/stdlib/public/core/CompilerProtocols.swift:407   
>>> 

Re: [swift-evolution] [Draft] open and public protocols

2017-02-19 Thread Adrian Zubarev via swift-evolution
IMHO the existence of open as an _exclusive_ access modifier is not worth. If 
people not going with the consistent idea of open vs. public then open should 
be removed completely, then public should be reverted to what it meant before. 
Afterwards we would introduce closed as an extra attribute. open class would be 
equivalent to public class, where today public class would become closed public 
class. That would be a little more consistent to final public behavior.



-- 
Adrian Zubarev
Sent with Airmail

Am 19. Februar 2017 um 14:02:54, Adrian Zubarev 
(adrian.zuba...@devandartist.com) schrieb:

That won’t work, plus the suggested solution makes life even more complicated. 
I need to be able to index an array, so I’m not willing to simply give up 
integers and do some extra work behind the scenes and convert a String to an 
Int. Furthermore there is no need something like KeyConvertible to even exist.



-- 
Adrian Zubarev
Sent with Airmail

Am 19. Februar 2017 um 13:58:35, David Hart (da...@hartbit.com) schrieb:

I honestly don't see the use case. The example you showed is an example of how 
your circumvented the lack of "closed" protocols in Swift. But I'd really like 
to see an example of the necessity for closed protocols in the first place:

In your case, I would simply defined the API as:

protocol KeyConvertible {
    var key: String { get }
}

public subscript(firstKey: String, parameters: KeyConvertible...) {}

Which would allow clients to implement their own KeyConvertible conforming 
types which convert into key paths.

On 19 Feb 2017, at 09:14, Adrian Zubarev via swift-evolution 
 wrote:

If you haven’t followed the other thread Matthew previously opened than you 
have missed the example I showed there.

Here it is again:

public protocol SubscriptParameterType {

// This property was needed to prevent the client from breaking
// the library by conforming to the protocol, but I'd like to 
// keep it invisible for the client, or even better prevent the
// client from conforming to the protocol.
var parameter: Document.SubscriptParameter { get }
}

extension Document {

public enum SubscriptParameter {

case string(String)
case integer(Int)
}
}

extension String : SubscriptParameterType {

public var parameter: Document.SubscriptParameter {

return .string(self)
}
}

extension Int : SubscriptParameterType {

public var parameter: Document.SubscriptParameter {

return .integer(self)
}
}

// Somewhere inside the `Document` type
public subscript(firstKey: String, parameters: SubscriptParameterType...) -> 
Value? { … }
The absence of closed protocols forced me to create a special requirement on 
that protocol to prevent the client from conforming to that protocol and 
passing instances of other types my API wouldn’t want to deal with. That 
creates unnecessary copies and I need to unpack the enum payload to find out 
which type the user passed. Instead I could simply close the protocol, wouldn’t 
need the requirement to exist and I could simply cast the type to String or Int 
when needed.

That implementation enables more safe queries of my Document type like

document["key1", intIndexInstance, stringKeyInstance, 10, "key"]

rather than

document["key1/\(intIndexInstance)/\(stringKeyInstance)/10/key"].

Here is a list of hidden and semi-hidden protocols from the standard library 
that could be closed. Formatted version: 
https://gist.github.com/DevAndArtist/168c800d784829be536c407311953ab7

PathProtocol
/swift/stdlib/public/core/AnyHashable.swift:16  
_HasCustomAnyHashableRepresentation
/swift/stdlib/public/core/BidirectionalCollection.swift:21  
_BidirectionalIndexable
/swift/stdlib/public/core/BridgeObjectiveC.swift:19 _ObjectiveCBridgeable
/swift/stdlib/public/core/Collection.swift:20   _IndexableBase
/swift/stdlib/public/core/Collection.swift:176  _Indexable
/swift/stdlib/public/core/CompilerProtocols.swift:193   
_ExpressibleByBuiltinIntegerLiteral
/swift/stdlib/public/core/CompilerProtocols.swift:240   
_ExpressibleByBuiltinFloatLiteral
/swift/stdlib/public/core/CompilerProtocols.swift:283   
_ExpressibleByBuiltinBooleanLiteral
/swift/stdlib/public/core/CompilerProtocols.swift:316   
_ExpressibleByBuiltinUnicodeScalarLiteral
/swift/stdlib/public/core/CompilerProtocols.swift:350   
_ExpressibleByBuiltinExtendedGraphemeClusterLiteral
/swift/stdlib/public/core/CompilerProtocols.swift:398   
_ExpressibleByBuiltinStringLiteral
/swift/stdlib/public/core/CompilerProtocols.swift:407   
_ExpressibleByBuiltinUTF16StringLiteral
/swift/stdlib/public/core/CompilerProtocols.swift:670   
_ExpressibleByStringInterpolation
/swift/stdlib/public/core/CompilerProtocols.swift:709   
_ExpressibleByColorLiteral
/swift/stdlib/public/core/CompilerProtocols.swift:720   
_ExpressibleByImageLiteral

Re: [swift-evolution] [Draft] open and public protocols

2017-02-19 Thread Adrian Zubarev via swift-evolution
That won’t work, plus the suggested solution makes life even more complicated. 
I need to be able to index an array, so I’m not willing to simply give up 
integers and do some extra work behind the scenes and convert a String to an 
Int. Furthermore there is no need something like KeyConvertible to even exist.



-- 
Adrian Zubarev
Sent with Airmail

Am 19. Februar 2017 um 13:58:35, David Hart (da...@hartbit.com) schrieb:

I honestly don't see the use case. The example you showed is an example of how 
your circumvented the lack of "closed" protocols in Swift. But I'd really like 
to see an example of the necessity for closed protocols in the first place:

In your case, I would simply defined the API as:

protocol KeyConvertible {
    var key: String { get }
}

public subscript(firstKey: String, parameters: KeyConvertible...) {}

Which would allow clients to implement their own KeyConvertible conforming 
types which convert into key paths.

On 19 Feb 2017, at 09:14, Adrian Zubarev via swift-evolution 
 wrote:

If you haven’t followed the other thread Matthew previously opened than you 
have missed the example I showed there.

Here it is again:

public protocol SubscriptParameterType {
   
// This property was needed to prevent the client from breaking
// the library by conforming to the protocol, but I'd like to
// keep it invisible for the client, or even better prevent the
// client from conforming to the protocol.
var parameter: Document.SubscriptParameter { get }
}

extension Document {
   
public enum SubscriptParameter {
   
case string(String)
case integer(Int)
}
}

extension String : SubscriptParameterType {
   
public var parameter: Document.SubscriptParameter {
   
return .string(self)
}
}

extension Int : SubscriptParameterType {
   
public var parameter: Document.SubscriptParameter {
   
return .integer(self)
}
}

// Somewhere inside the `Document` type
public subscript(firstKey: String, parameters: SubscriptParameterType...) -> 
Value? { … }
The absence of closed protocols forced me to create a special requirement on 
that protocol to prevent the client from conforming to that protocol and 
passing instances of other types my API wouldn’t want to deal with. That 
creates unnecessary copies and I need to unpack the enum payload to find out 
which type the user passed. Instead I could simply close the protocol, wouldn’t 
need the requirement to exist and I could simply cast the type to String or Int 
when needed.

That implementation enables more safe queries of my Document type like

document["key1", intIndexInstance, stringKeyInstance, 10, "key"]

rather than

document["key1/\(intIndexInstance)/\(stringKeyInstance)/10/key"].

Here is a list of hidden and semi-hidden protocols from the standard library 
that could be closed. Formatted version: 
https://gist.github.com/DevAndArtist/168c800d784829be536c407311953ab7

PathProtocol
/swift/stdlib/public/core/AnyHashable.swift:16  
_HasCustomAnyHashableRepresentation
/swift/stdlib/public/core/BidirectionalCollection.swift:21  
_BidirectionalIndexable
/swift/stdlib/public/core/BridgeObjectiveC.swift:19 _ObjectiveCBridgeable
/swift/stdlib/public/core/Collection.swift:20   _IndexableBase
/swift/stdlib/public/core/Collection.swift:176  _Indexable
/swift/stdlib/public/core/CompilerProtocols.swift:193   
_ExpressibleByBuiltinIntegerLiteral
/swift/stdlib/public/core/CompilerProtocols.swift:240   
_ExpressibleByBuiltinFloatLiteral
/swift/stdlib/public/core/CompilerProtocols.swift:283   
_ExpressibleByBuiltinBooleanLiteral
/swift/stdlib/public/core/CompilerProtocols.swift:316   
_ExpressibleByBuiltinUnicodeScalarLiteral
/swift/stdlib/public/core/CompilerProtocols.swift:350   
_ExpressibleByBuiltinExtendedGraphemeClusterLiteral
/swift/stdlib/public/core/CompilerProtocols.swift:398   
_ExpressibleByBuiltinStringLiteral
/swift/stdlib/public/core/CompilerProtocols.swift:407   
_ExpressibleByBuiltinUTF16StringLiteral
/swift/stdlib/public/core/CompilerProtocols.swift:670   
_ExpressibleByStringInterpolation
/swift/stdlib/public/core/CompilerProtocols.swift:709   
_ExpressibleByColorLiteral
/swift/stdlib/public/core/CompilerProtocols.swift:720   
_ExpressibleByImageLiteral
/swift/stdlib/public/core/CompilerProtocols.swift:730   
_ExpressibleByFileReferenceLiteral
/swift/stdlib/public/core/CompilerProtocols.swift:750   _DestructorSafeContainer
/swift/stdlib/public/core/FixedPoint.swift.gyb:53   _Integer
/swift/stdlib/public/core/FixedPoint.swift.gyb:70   _SignedInteger
/swift/stdlib/public/core/FixedPoint.swift.gyb:108  
_DisallowMixedSignArithmetic
/swift/stdlib/public/core/Hashable.swift:16 _Hashable
/swift/stdlib/public/core/Index.swift:16_Incrementable
/swift/stdlib/public/core/IntegerArithmetic.swift.gyb:33
_IntegerArithmetic
/swift/stdlib/public/core/Mirror.swift:721 

Re: [swift-evolution] [Draft] open and public protocols

2017-02-19 Thread David Hart via swift-evolution
I honestly don't see the use case. The example you showed is an example of how 
your circumvented the lack of "closed" protocols in Swift. But I'd really like 
to see an example of the necessity for closed protocols in the first place:

In your case, I would simply defined the API as:

protocol KeyConvertible {
var key: String { get }
}

public subscript(firstKey: String, parameters: KeyConvertible...) {}

Which would allow clients to implement their own KeyConvertible conforming 
types which convert into key paths.

> On 19 Feb 2017, at 09:14, Adrian Zubarev via swift-evolution 
>  wrote:
> 
> If you haven’t followed the other thread Matthew previously opened than you 
> have missed the example I showed there.
> 
> Here it is again:
> 
> public protocol SubscriptParameterType {
>   
> // This property was needed to prevent the client from breaking
> // the library by conforming to the protocol, but I'd like to   
> // keep it invisible for the client, or even better prevent the
> // client from conforming to the protocol.
> var parameter: Document.SubscriptParameter { get }
> }
> 
> extension Document {
>   
> public enum SubscriptParameter {
>   
> case string(String)
> case integer(Int)
> }
> }
> 
> extension String : SubscriptParameterType {
>   
> public var parameter: Document.SubscriptParameter {
>   
> return .string(self)
> }
> }
> 
> extension Int : SubscriptParameterType {
>   
> public var parameter: Document.SubscriptParameter {
>   
> return .integer(self)
> }
> }
> 
> // Somewhere inside the `Document` type
> public subscript(firstKey: String, parameters: SubscriptParameterType...) -> 
> Value? { … }
> The absence of closed protocols forced me to create a special requirement on 
> that protocol to prevent the client from conforming to that protocol and 
> passing instances of other types my API wouldn’t want to deal with. That 
> creates unnecessary copies and I need to unpack the enum payload to find out 
> which type the user passed. Instead I could simply close the protocol, 
> wouldn’t need the requirement to exist and I could simply cast the type to 
> String or Int when needed.
> 
> That implementation enables more safe queries of my Document type like
> 
> document["key1", intIndexInstance, stringKeyInstance, 10, "key"]
> 
> rather than
> 
> document["key1/\(intIndexInstance)/\(stringKeyInstance)/10/key"].
> 
> Here is a list of hidden and semi-hidden protocols from the standard library 
> that could be closed. Formatted version: 
> https://gist.github.com/DevAndArtist/168c800d784829be536c407311953ab7
> 
> Path  Protocol
> /swift/stdlib/public/core/AnyHashable.swift:16
> _HasCustomAnyHashableRepresentation
> /swift/stdlib/public/core/BidirectionalCollection.swift:21
> _BidirectionalIndexable
> /swift/stdlib/public/core/BridgeObjectiveC.swift:19   _ObjectiveCBridgeable
> /swift/stdlib/public/core/Collection.swift:20 _IndexableBase
> /swift/stdlib/public/core/Collection.swift:176_Indexable
> /swift/stdlib/public/core/CompilerProtocols.swift:193 
> _ExpressibleByBuiltinIntegerLiteral
> /swift/stdlib/public/core/CompilerProtocols.swift:240 
> _ExpressibleByBuiltinFloatLiteral
> /swift/stdlib/public/core/CompilerProtocols.swift:283 
> _ExpressibleByBuiltinBooleanLiteral
> /swift/stdlib/public/core/CompilerProtocols.swift:316 
> _ExpressibleByBuiltinUnicodeScalarLiteral
> /swift/stdlib/public/core/CompilerProtocols.swift:350 
> _ExpressibleByBuiltinExtendedGraphemeClusterLiteral
> /swift/stdlib/public/core/CompilerProtocols.swift:398 
> _ExpressibleByBuiltinStringLiteral
> /swift/stdlib/public/core/CompilerProtocols.swift:407 
> _ExpressibleByBuiltinUTF16StringLiteral
> /swift/stdlib/public/core/CompilerProtocols.swift:670 
> _ExpressibleByStringInterpolation
> /swift/stdlib/public/core/CompilerProtocols.swift:709 
> _ExpressibleByColorLiteral
> /swift/stdlib/public/core/CompilerProtocols.swift:720 
> _ExpressibleByImageLiteral
> /swift/stdlib/public/core/CompilerProtocols.swift:730 
> _ExpressibleByFileReferenceLiteral
> /swift/stdlib/public/core/CompilerProtocols.swift:750 _DestructorSafeContainer
> /swift/stdlib/public/core/FixedPoint.swift.gyb:53 _Integer
> /swift/stdlib/public/core/FixedPoint.swift.gyb:70 _SignedInteger
> /swift/stdlib/public/core/FixedPoint.swift.gyb:108
> _DisallowMixedSignArithmetic
> /swift/stdlib/public/core/Hashable.swift:16   _Hashable
> /swift/stdlib/public/core/Index.swift:16  _Incrementable
> /swift/stdlib/public/core/IntegerArithmetic.swift.gyb:33  
> _IntegerArithmetic
> /swift/stdlib/public/core/Mirror.swift:721
> _DefaultCustomPlaygroundQuickLookable
> /swift/stdlib/public/core/MutableCollection.swift:20  _MutableIndexable
> /swift/stdlib/public/core/NewtypeWrapper.swift.gyb:16 _SwiftNewtypeWrapper
> /swift/stdlib/public/core/Pointer.swift:16_Pointer
> 

Re: [swift-evolution] [Draft] open and public protocols

2017-02-19 Thread Adrian Zubarev via swift-evolution
If you haven’t followed the other thread Matthew previously opened than you 
have missed the example I showed there.

Here it is again:

public protocol SubscriptParameterType {
  
// This property was needed to prevent the client from breaking
// the library by conforming to the protocol, but I'd like to   
// keep it invisible for the client, or even better prevent the
// client from conforming to the protocol.
var parameter: Document.SubscriptParameter { get }
}

extension Document {
  
public enum SubscriptParameter {
  
case string(String)
case integer(Int)
}
}

extension String : SubscriptParameterType {
  
public var parameter: Document.SubscriptParameter {
  
return .string(self)
}
}

extension Int : SubscriptParameterType {
  
public var parameter: Document.SubscriptParameter {
  
return .integer(self)
}
}

// Somewhere inside the `Document` type
public subscript(firstKey: String, parameters: SubscriptParameterType...) -> 
Value? { … }
The absence of closed protocols forced me to create a special requirement on 
that protocol to prevent the client from conforming to that protocol and 
passing instances of other types my API wouldn’t want to deal with. That 
creates unnecessary copies and I need to unpack the enum payload to find out 
which type the user passed. Instead I could simply close the protocol, wouldn’t 
need the requirement to exist and I could simply cast the type to String or Int 
when needed.

That implementation enables more safe queries of my Document type like

document["key1", intIndexInstance, stringKeyInstance, 10, "key"]

rather than

document["key1/\(intIndexInstance)/\(stringKeyInstance)/10/key"].

Here is a list of hidden and semi-hidden protocols from the standard library 
that could be closed. Formatted version: 
https://gist.github.com/DevAndArtist/168c800d784829be536c407311953ab7

PathProtocol
/swift/stdlib/public/core/AnyHashable.swift:16  
_HasCustomAnyHashableRepresentation
/swift/stdlib/public/core/BidirectionalCollection.swift:21  
_BidirectionalIndexable
/swift/stdlib/public/core/BridgeObjectiveC.swift:19 _ObjectiveCBridgeable
/swift/stdlib/public/core/Collection.swift:20   _IndexableBase
/swift/stdlib/public/core/Collection.swift:176  _Indexable
/swift/stdlib/public/core/CompilerProtocols.swift:193   
_ExpressibleByBuiltinIntegerLiteral
/swift/stdlib/public/core/CompilerProtocols.swift:240   
_ExpressibleByBuiltinFloatLiteral
/swift/stdlib/public/core/CompilerProtocols.swift:283   
_ExpressibleByBuiltinBooleanLiteral
/swift/stdlib/public/core/CompilerProtocols.swift:316   
_ExpressibleByBuiltinUnicodeScalarLiteral
/swift/stdlib/public/core/CompilerProtocols.swift:350   
_ExpressibleByBuiltinExtendedGraphemeClusterLiteral
/swift/stdlib/public/core/CompilerProtocols.swift:398   
_ExpressibleByBuiltinStringLiteral
/swift/stdlib/public/core/CompilerProtocols.swift:407   
_ExpressibleByBuiltinUTF16StringLiteral
/swift/stdlib/public/core/CompilerProtocols.swift:670   
_ExpressibleByStringInterpolation
/swift/stdlib/public/core/CompilerProtocols.swift:709   
_ExpressibleByColorLiteral
/swift/stdlib/public/core/CompilerProtocols.swift:720   
_ExpressibleByImageLiteral
/swift/stdlib/public/core/CompilerProtocols.swift:730   
_ExpressibleByFileReferenceLiteral
/swift/stdlib/public/core/CompilerProtocols.swift:750   _DestructorSafeContainer
/swift/stdlib/public/core/FixedPoint.swift.gyb:53   _Integer
/swift/stdlib/public/core/FixedPoint.swift.gyb:70   _SignedInteger
/swift/stdlib/public/core/FixedPoint.swift.gyb:108  
_DisallowMixedSignArithmetic
/swift/stdlib/public/core/Hashable.swift:16 _Hashable
/swift/stdlib/public/core/Index.swift:16_Incrementable
/swift/stdlib/public/core/IntegerArithmetic.swift.gyb:33
_IntegerArithmetic
/swift/stdlib/public/core/Mirror.swift:721  
_DefaultCustomPlaygroundQuickLookable
/swift/stdlib/public/core/MutableCollection.swift:20_MutableIndexable
/swift/stdlib/public/core/NewtypeWrapper.swift.gyb:16   _SwiftNewtypeWrapper
/swift/stdlib/public/core/Pointer.swift:16  _Pointer
/swift/stdlib/public/core/RandomAccessCollection.swift:20   
_RandomAccessIndexable
/swift/stdlib/public/core/RangeReplaceableCollection.swift.gyb:27   
_RangeReplaceableIndexable
/swift/stdlib/public/core/ReflectionLegacy.swift:41 _Mirror
/swift/stdlib/public/core/ShadowProtocols.swift:27  _ShadowProtocol
/swift/stdlib/public/core/ShadowProtocols.swift:31  _NSFastEnumeration
/swift/stdlib/public/core/ShadowProtocols.swift:41  _NSEnumerator
/swift/stdlib/public/core/ShadowProtocols.swift:51  _NSCopying
/swift/stdlib/public/core/ShadowProtocols.swift:61  _NSArrayCore
/swift/stdlib/public/core/ShadowProtocols.swift:83  _NSDictionaryCore
/swift/stdlib/public/core/ShadowProtocols.swift:125 _NSDictionary
/swift/stdlib/public/core/ShadowProtocols.swift:137 

Re: [swift-evolution] [Draft] open and public protocols

2017-02-18 Thread David Waite via swift-evolution
I am unsure if this feature is a good idea. Does someone have a real-world use 
for this which isn’t just hiding strong implementation coupling behind a 
protocol?

When I consume a protocol, it is under the assumption that the protocol is 
documented such that I would be able to work against *any* implementation of 
the protocol. With a closed protocol, I would have to assume that there are 
significant side effects, either undocumented or difficult for a third party to 
duplicate. To my experience, that sounds brittle.

Assuming you aren’t switching on the implementing type of a protocol (which 
itself can be a sign that your design isn’t properly using polymorphism), one 
could get this design by creating a struct with the interface desired, and 
passing invocations through to an internal protocol reference.

-DW

> On Feb 18, 2017, at 1:41 PM, Matthew Johnson via swift-evolution 
>  wrote:
> 
> Now that we’re in phase 2 I’d like to officially propose we introduce `open` 
> protocols and require conformances to  `public` protocols be inside the 
> declaring module.  Let’s use this thread for feedback on the official 
> proposal.  After a healthy round of discussion I’ll open a PR to submit it 
> for review.
> 
> 
> # Feature name
> 
> * Proposal: [SE-](-open-public-protocols.md)
> * Authors: [Matthew Johnson](https://github.com/anandabits)
> * Review Manager: TBD
> * Status: **Awaiting review**
> 
> ## Introduction
> 
> This proposal introduces `open protocol` and changes the meaning of `public 
> protocol` to match the meaning of `public class` (in this case, conformances 
> are only allowed inside the declaring module).
> 
> The pitch thread leading up to this proposal was: [consistent public access 
> modifiers](https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170206/031653.html)
> 
> ## Motivation
> 
> A general principle the Swift community has adopted for access control is 
> that defaults should reserve maximum flexibility for a library.  The ensures 
> that any capabilities beyond mere visibility are not available unless the 
> author of the library has explicitly declared their intent that the 
> capabilities be made available.  Finally, when it is possible to switch from 
> one semantic to another without breaking clients (but not vice-versa) we 
> should prefer the more forgiving (i.e. fixable) semantic as the (soft) 
> default.
> 
> `public` is considered a "soft default" in the sense that it is the first 
> access modifier a user will reach for when exposing a declaration outside of 
> the module.  In the case of protocols the current meaning of `public` does 
> not meet the principle of preserving maximum flexibility for the author of 
> the library.  It allows users of the library to conform to the protocol.
> 
> There are good reasons a library may not wish to allow users to add 
> conformances to a protocol.  For example, it may not wish to expose the 
> conforming concrete types.  While similar behavior could be accomplished with 
> an enum if cases could be private, that requires an implementation to use 
> switch statements rather than polymorphism.
> 
> Even if all the conforming types are also public there are cases where 
> polymorphism is the preferred implementation.  For example, if the set of 
> conforming types is not expected to be fixed (despite all being inside the 
> library) the authors may not want to have to maintain switch statements every 
> time they need to add or remove a confroming type which would be necessary if 
> an enum were used instead.  Polymorphism allows us to avoid this, giving us 
> the ability to add and remove conforming types within the implementation of 
> the library without the burden of maintaining switch statements.
> 
> Aligning the access modifiers for protocols and classes allows us to specify 
> both conformable and non-conformable protocols, provides a soft default that 
> is consistent with the principle of (soft) defaults reserving maximum 
> flexibility for the library, and increases the overall consistency of the 
> language by aligning the semantics of access control for protocols and 
> classes.
> 
> The standard library currently has at least one protocol (`MirrorPath`) that 
> is documented as disallowing client conformances.  If this proposal is 
> adopted it is likely that `MirrorPath` would be declared `public protocol` 
> and not `open protocol`.
> 
> Jordan Rose has indicated that the Apple frameworks also include a number of 
> protocols documented with the intent that users do not add conformances.  
> Perhaps an importer annotation would allow the compiler to enforce these 
> semantics in Swift code as well.
> 
> ## Proposed solution
> 
> The proposed solution is to change the meaning of `public protocol` to 
> disallow conformances outside the declaring module and introduce `open 
> protocol` to allow conformances outside the decalring module (equivalent to 
> the current 

Re: [swift-evolution] [Draft] open and public protocols

2017-02-18 Thread Xiaodi Wu via swift-evolution
There's no way to make a source-breaking change non-breaking. A migration
path that meanders through several different designs just increases the
aggregate pain over multiple releases. The proposed migration path has the
great drawback that, even once approved, no person would actually be
allowed to write code that would compile under the final accepted design
until several versions in the future.

Either this issue about `open` protocols is so important that it meets the
bar for a source-breaking change in Swift 4 (see Ted Kremenek's post about
the very stringent criteria), and thus it merits a single discrete break in
source compatibility between Swift versions, or it is not sufficiently
important.


On Sat, Feb 18, 2017 at 4:44 PM, David Sweeris via swift-evolution <
swift-evolution@swift.org> wrote:

>
> > On Feb 18, 2017, at 14:28, Matthew Johnson 
> wrote:
> >
> >
> >> On Feb 18, 2017, at 3:52 PM, David Sweeris  wrote:
> >>
> >>
> >>> On Feb 18, 2017, at 13:12, Matthew Johnson 
> wrote:
> >>>
> >>>
>  On Feb 18, 2017, at 3:01 PM, David Sweeris 
> wrote:
> 
> 
> > On Feb 18, 2017, at 12:41 PM, Matthew Johnson via swift-evolution <
> swift-evolution@swift.org> wrote:
> >
> > ## Source compatibility
> >
> > This proposal breaks source compatibility, but in a way that allows
> for a simple mechanical migration.  A multi-release stratgegy will be used
> to roll out this proposal to provide maximum possible source compatibility
> from one release to the next.
> >
> > 1. In Swift 4, introduce the `open` keyword and the `@nonopen`
> attribute (which can be applied to `public protocol` to give it the new
> semantics of `public`).
> > 2. In Swift 4 (or 4.1 if necessary) start warning for `public
> protocol` with no annotation.
> > 3. In the subsequent release `public protocol` without annotation
> becomes an error.
> > 4. In the subsequent relase `public protocol` without annotation
> takes on the new semantics.
> > 5. `@nonopen` becomes a warning, and evenutally an erro as soon as
> we are comfortable making those changes.
> 
>  I don’t think we need @nonopen or warnings. IMHO, public/open should
> have the same semantics and syntax regardless of whether the declaration is
> a protocol or a concrete type (or a property?).
> 
>  Other than that nit, I can’t think of a reason to oppose this. So…
> +1, because I like making things as consistent as possible (also because of
> the reasons in the motivation).
> >>>
> >>> The purpose of using `@nonopen` for the migration is to eventually
> break people’s code if they don’t use the migrator and don’t annotate it.
> If we don’t do that the library may ship a version that unintentionally
> breaks their clients (by continuing to use `public` after its meaning has
> changed).
> >>>
> >>> It’s better to break the library before it breaks any clients.  That
> will impact many fewer developers.  This can be handled automatically by
> the migrator and will be a relatively minor inconvenience for developers
> who don’t use it.  That’s better than allowing an accidentally bad version
> of a library from shipping.
> >>
> >> Do we need it for types? "@nonopen public class Foo {...}"?
> >>
> >> (Serious question... I don't recall if we did this phased thing for
> open vs public types)
> >
> > No, because we already introduced that in Swift 3.  Swift 4 has a higher
> bar for breaking changes.  If the core team is willing to accept the
> proposal without a staged migration strategy I would not object to that.
> But I believe it’s best for breaking proposals to present a staged
> migration strategy for the core team to consider.  That’s what this is.  I
> wouldn’t want lack of a staged migration strategy to sink the proposal.
>
> Ah! Ok, I can see that.
>
> Well, for whatever my opinion is worth, I'd prefer we left that part out.
> But I'd rather leave it in than for the proposal to get rejected, though.
>
> - 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] [Draft] open and public protocols

2017-02-18 Thread David Sweeris via swift-evolution

> On Feb 18, 2017, at 14:28, Matthew Johnson  wrote:
> 
> 
>> On Feb 18, 2017, at 3:52 PM, David Sweeris  wrote:
>> 
>> 
>>> On Feb 18, 2017, at 13:12, Matthew Johnson  wrote:
>>> 
>>> 
 On Feb 18, 2017, at 3:01 PM, David Sweeris  wrote:
 
 
> On Feb 18, 2017, at 12:41 PM, Matthew Johnson via swift-evolution 
>  wrote:
> 
> ## Source compatibility
> 
> This proposal breaks source compatibility, but in a way that allows for a 
> simple mechanical migration.  A multi-release stratgegy will be used to 
> roll out this proposal to provide maximum possible source compatibility 
> from one release to the next.
> 
> 1. In Swift 4, introduce the `open` keyword and the `@nonopen` attribute 
> (which can be applied to `public protocol` to give it the new semantics 
> of `public`).
> 2. In Swift 4 (or 4.1 if necessary) start warning for `public protocol` 
> with no annotation.
> 3. In the subsequent release `public protocol` without annotation becomes 
> an error.
> 4. In the subsequent relase `public protocol` without annotation takes on 
> the new semantics.
> 5. `@nonopen` becomes a warning, and evenutally an erro as soon as we are 
> comfortable making those changes.
 
 I don’t think we need @nonopen or warnings. IMHO, public/open should have 
 the same semantics and syntax regardless of whether the declaration is a 
 protocol or a concrete type (or a property?).
 
 Other than that nit, I can’t think of a reason to oppose this. So… +1, 
 because I like making things as consistent as possible (also because of 
 the reasons in the motivation).
>>> 
>>> The purpose of using `@nonopen` for the migration is to eventually break 
>>> people’s code if they don’t use the migrator and don’t annotate it.  If we 
>>> don’t do that the library may ship a version that unintentionally breaks 
>>> their clients (by continuing to use `public` after its meaning has 
>>> changed).  
>>> 
>>> It’s better to break the library before it breaks any clients.  That will 
>>> impact many fewer developers.  This can be handled automatically by the 
>>> migrator and will be a relatively minor inconvenience for developers who 
>>> don’t use it.  That’s better than allowing an accidentally bad version of a 
>>> library from shipping.
>> 
>> Do we need it for types? "@nonopen public class Foo {...}"?
>> 
>> (Serious question... I don't recall if we did this phased thing for open vs 
>> public types)
> 
> No, because we already introduced that in Swift 3.  Swift 4 has a higher bar 
> for breaking changes.  If the core team is willing to accept the proposal 
> without a staged migration strategy I would not object to that.  But I 
> believe it’s best for breaking proposals to present a staged migration 
> strategy for the core team to consider.  That’s what this is.  I wouldn’t 
> want lack of a staged migration strategy to sink the proposal.

Ah! Ok, I can see that.

Well, for whatever my opinion is worth, I'd prefer we left that part out. But 
I'd rather leave it in than for the proposal to get rejected, though.

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


Re: [swift-evolution] [Draft] open and public protocols

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

> On Feb 18, 2017, at 3:52 PM, David Sweeris  wrote:
> 
> 
>> On Feb 18, 2017, at 13:12, Matthew Johnson  wrote:
>> 
>> 
>>> On Feb 18, 2017, at 3:01 PM, David Sweeris  wrote:
>>> 
>>> 
 On Feb 18, 2017, at 12:41 PM, Matthew Johnson via swift-evolution 
  wrote:
 
 ## Source compatibility
 
 This proposal breaks source compatibility, but in a way that allows for a 
 simple mechanical migration.  A multi-release stratgegy will be used to 
 roll out this proposal to provide maximum possible source compatibility 
 from one release to the next.
 
 1. In Swift 4, introduce the `open` keyword and the `@nonopen` attribute 
 (which can be applied to `public protocol` to give it the new semantics of 
 `public`).
 2. In Swift 4 (or 4.1 if necessary) start warning for `public protocol` 
 with no annotation.
 3. In the subsequent release `public protocol` without annotation becomes 
 an error.
 4. In the subsequent relase `public protocol` without annotation takes on 
 the new semantics.
 5. `@nonopen` becomes a warning, and evenutally an erro as soon as we are 
 comfortable making those changes.
>>> 
>>> I don’t think we need @nonopen or warnings. IMHO, public/open should have 
>>> the same semantics and syntax regardless of whether the declaration is a 
>>> protocol or a concrete type (or a property?).
>>> 
>>> Other than that nit, I can’t think of a reason to oppose this. So… +1, 
>>> because I like making things as consistent as possible (also because of the 
>>> reasons in the motivation).
>> 
>> The purpose of using `@nonopen` for the migration is to eventually break 
>> people’s code if they don’t use the migrator and don’t annotate it.  If we 
>> don’t do that the library may ship a version that unintentionally breaks 
>> their clients (by continuing to use `public` after its meaning has changed). 
>>  
>> 
>> It’s better to break the library before it breaks any clients.  That will 
>> impact many fewer developers.  This can be handled automatically by the 
>> migrator and will be a relatively minor inconvenience for developers who 
>> don’t use it.  That’s better than allowing an accidentally bad version of a 
>> library from shipping.
> 
> Do we need it for types? "@nonopen public class Foo {...}"?
> 
> (Serious question... I don't recall if we did this phased thing for open vs 
> public types)

No, because we already introduced that in Swift 3.  Swift 4 has a higher bar 
for breaking changes.  If the core team is willing to accept the proposal 
without a staged migration strategy I would not object to that.  But I believe 
it’s best for breaking proposals to present a staged migration strategy for the 
core team to consider.  That’s what this is.  I wouldn’t want lack of a staged 
migration strategy to sink the proposal.

> 
> - Dave Sweeris

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


Re: [swift-evolution] [Draft] open and public protocols

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

> On Feb 18, 2017, at 3:43 PM, Charles Srstka  wrote:
> 
>> On Feb 18, 2017, at 2:41 PM, Matthew Johnson via swift-evolution 
>> > wrote:
>> 
>> There are good reasons a library may not wish to allow users to add 
>> conformances to a protocol.  For example, it may not wish to expose the 
>> conforming concrete types.  While similar behavior could be accomplished 
>> with an enum if cases could be private, that requires an implementation to 
>> use switch statements rather than polymorphism.
> 
> Uh, what? You can expose protocols without exposing the concrete types that 
> conform to them. That’s kind of the whole point of protocols.
> 
> public protocol P {}
> 
> private struct S: P {}
> 
> public var p: P
> 
> reduces to this interface:
> 
> public protocol P {
> }
> 
> 
> public var p: P
> 
> The library can then assign something of type S to the “p” variable, and 
> clients will be able to use it without having access to its concrete type.
> 
> Charles
> 

Sorry, this part was not stated as clearly as it should have been.  What 
intends to say is that the library may wish to not only hide the concrete 
types, but also control the set of types which may conform to the protocol (or 
be associated values of the enum) such that users cannot add to the set of 
types.  I will update the document to more clearly describe this use case.  
Thanks for catching this!

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


Re: [swift-evolution] [Draft] open and public protocols

2017-02-18 Thread Adrian Zubarev via swift-evolution
Great proposal Matthew, huge thanks for pushing this forward and putting it 
together. I simply cannot wait for this to be implemented. :)

+1

I spotted two typos while reading:

public protocol P P{} - one P too much
There is somewhere an erro without an r at the end


-- 
Adrian Zubarev
Sent with Airmail

Am 18. Februar 2017 um 21:42:41, Matthew Johnson via swift-evolution 
(swift-evolution@swift.org) schrieb:

Now that we’re in phase 2 I’d like to officially propose we introduce `open` 
protocols and require conformances to `public` protocols be inside the 
declaring module. Let’s use this thread for feedback on the official proposal. 
After a healthy round of discussion I’ll open a PR to submit it for review.


# Feature name

* Proposal: [SE-](-open-public-protocols.md)
* Authors: [Matthew Johnson](https://github.com/anandabits)
* Review Manager: TBD
* Status: **Awaiting review**

## Introduction

This proposal introduces `open protocol` and changes the meaning of `public 
protocol` to match the meaning of `public class` (in this case, conformances 
are only allowed inside the declaring module).

The pitch thread leading up to this proposal was: [consistent public access 
modifiers](https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170206/031653.html)

## Motivation

A general principle the Swift community has adopted for access control is that 
defaults should reserve maximum flexibility for a library. The ensures that any 
capabilities beyond mere visibility are not available unless the author of the 
library has explicitly declared their intent that the capabilities be made 
available. Finally, when it is possible to switch from one semantic to another 
without breaking clients (but not vice-versa) we should prefer the more 
forgiving (i.e. fixable) semantic as the (soft) default.

`public` is considered a "soft default" in the sense that it is the first 
access modifier a user will reach for when exposing a declaration outside of 
the module. In the case of protocols the current meaning of `public` does not 
meet the principle of preserving maximum flexibility for the author of the 
library. It allows users of the library to conform to the protocol.

There are good reasons a library may not wish to allow users to add 
conformances to a protocol. For example, it may not wish to expose the 
conforming concrete types. While similar behavior could be accomplished with an 
enum if cases could be private, that requires an implementation to use switch 
statements rather than polymorphism.

Even if all the conforming types are also public there are cases where 
polymorphism is the preferred implementation. For example, if the set of 
conforming types is not expected to be fixed (despite all being inside the 
library) the authors may not want to have to maintain switch statements every 
time they need to add or remove a confroming type which would be necessary if 
an enum were used instead. Polymorphism allows us to avoid this, giving us the 
ability to add and remove conforming types within the implementation of the 
library without the burden of maintaining switch statements.

Aligning the access modifiers for protocols and classes allows us to specify 
both conformable and non-conformable protocols, provides a soft default that is 
consistent with the principle of (soft) defaults reserving maximum flexibility 
for the library, and increases the overall consistency of the language by 
aligning the semantics of access control for protocols and classes.

The standard library currently has at least one protocol (`MirrorPath`) that is 
documented as disallowing client conformances. If this proposal is adopted it 
is likely that `MirrorPath` would be declared `public protocol` and not `open 
protocol`.

Jordan Rose has indicated that the Apple frameworks also include a number of 
protocols documented with the intent that users do not add conformances. 
Perhaps an importer annotation would allow the compiler to enforce these 
semantics in Swift code as well.

## Proposed solution

The proposed solution is to change the meaning of `public protocol` to disallow 
conformances outside the declaring module and introduce `open protocol` to 
allow conformances outside the decalring module (equivalent to the current 
meaning of `public protocol`).

## Detailed design

The detailed design is relatively straightforward but there are three important 
wrinkles to consider.

### User refinement of public protocols

Consider the following example:

```swift
// Library module:
public protocol P {}
public class C: P {}

// User module:
protocol User: P {}
extension C: User {}
```

The user module is allowed to add a refinement to `P` because this does not 
have any impact on the impelementation of the library or its possible 
evolution. It simply allows the user to write code that is generic over a 
subset of the conforming types provided by the library.

### Public protocols with open conforming 

Re: [swift-evolution] [Draft] open and public protocols

2017-02-18 Thread Adrian Zubarev via swift-evolution
Protocols solve way more problems than this. Sometimes they are used as 
backdoors to existing APIs as well. It’s simply an implementation artifact that 
such a protocol might end up public, but there is no point to allow the client 
to conform to it.

I also showed a concrete example in the discussion thread where I needed a 
public-but-not-open protocol really badly. ;)



-- 
Adrian Zubarev
Sent with Airmail

Am 18. Februar 2017 um 22:45:00, Charles Srstka via swift-evolution 
(swift-evolution@swift.org) schrieb:

On Feb 18, 2017, at 2:41 PM, Matthew Johnson via swift-evolution 
 wrote:

There are good reasons a library may not wish to allow users to add 
conformances to a protocol.  For example, it may not wish to expose the 
conforming concrete types.  While similar behavior could be accomplished with 
an enum if cases could be private, that requires an implementation to use 
switch statements rather than polymorphism.

Uh, what? You can expose protocols without exposing the concrete types that 
conform to them. That’s kind of the whole point of protocols.

public protocol P {}

private struct S: P {}

public var p: P

reduces to this interface:

public protocol P {
}


public var p: P

The library can then assign something of type S to the “p” variable, and 
clients will be able to use it without having access to its concrete type.

Charles

___
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] [Draft] open and public protocols

2017-02-18 Thread David Sweeris via swift-evolution

> On Feb 18, 2017, at 13:12, Matthew Johnson  wrote:
> 
> 
>> On Feb 18, 2017, at 3:01 PM, David Sweeris  wrote:
>> 
>> 
>>> On Feb 18, 2017, at 12:41 PM, Matthew Johnson via swift-evolution 
>>>  wrote:
>>> 
>>> ## Source compatibility
>>> 
>>> This proposal breaks source compatibility, but in a way that allows for a 
>>> simple mechanical migration.  A multi-release stratgegy will be used to 
>>> roll out this proposal to provide maximum possible source compatibility 
>>> from one release to the next.
>>> 
>>> 1. In Swift 4, introduce the `open` keyword and the `@nonopen` attribute 
>>> (which can be applied to `public protocol` to give it the new semantics of 
>>> `public`).
>>> 2. In Swift 4 (or 4.1 if necessary) start warning for `public protocol` 
>>> with no annotation.
>>> 3. In the subsequent release `public protocol` without annotation becomes 
>>> an error.
>>> 4. In the subsequent relase `public protocol` without annotation takes on 
>>> the new semantics.
>>> 5. `@nonopen` becomes a warning, and evenutally an erro as soon as we are 
>>> comfortable making those changes.
>> 
>> I don’t think we need @nonopen or warnings. IMHO, public/open should have 
>> the same semantics and syntax regardless of whether the declaration is a 
>> protocol or a concrete type (or a property?).
>> 
>> Other than that nit, I can’t think of a reason to oppose this. So… +1, 
>> because I like making things as consistent as possible (also because of the 
>> reasons in the motivation).
> 
> The purpose of using `@nonopen` for the migration is to eventually break 
> people’s code if they don’t use the migrator and don’t annotate it.  If we 
> don’t do that the library may ship a version that unintentionally breaks 
> their clients (by continuing to use `public` after its meaning has changed).  
> 
> It’s better to break the library before it breaks any clients.  That will 
> impact many fewer developers.  This can be handled automatically by the 
> migrator and will be a relatively minor inconvenience for developers who 
> don’t use it.  That’s better than allowing an accidentally bad version of a 
> library from shipping.

Do we need it for types? "@nonopen public class Foo {...}"?

(Serious question... I don't recall if we did this phased thing for open vs 
public types)

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


Re: [swift-evolution] [Draft] open and public protocols

2017-02-18 Thread Charles Srstka via swift-evolution
> On Feb 18, 2017, at 2:41 PM, Matthew Johnson via swift-evolution 
>  wrote:
> 
> There are good reasons a library may not wish to allow users to add 
> conformances to a protocol.  For example, it may not wish to expose the 
> conforming concrete types.  While similar behavior could be accomplished with 
> an enum if cases could be private, that requires an implementation to use 
> switch statements rather than polymorphism.

Uh, what? You can expose protocols without exposing the concrete types that 
conform to them. That’s kind of the whole point of protocols.

public protocol P {}

private struct S: P {}

public var p: P

reduces to this interface:

public protocol P {
}


public var p: P

The library can then assign something of type S to the “p” variable, and 
clients will be able to use it without having access to its concrete type.

Charles

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


Re: [swift-evolution] [Draft] open and public protocols

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

> On Feb 18, 2017, at 3:01 PM, David Sweeris  wrote:
> 
> 
>> On Feb 18, 2017, at 12:41 PM, Matthew Johnson via swift-evolution 
>>  wrote:
>> 
>> ## Source compatibility
>> 
>> This proposal breaks source compatibility, but in a way that allows for a 
>> simple mechanical migration.  A multi-release stratgegy will be used to roll 
>> out this proposal to provide maximum possible source compatibility from one 
>> release to the next.
>> 
>> 1. In Swift 4, introduce the `open` keyword and the `@nonopen` attribute 
>> (which can be applied to `public protocol` to give it the new semantics of 
>> `public`).
>> 2. In Swift 4 (or 4.1 if necessary) start warning for `public protocol` with 
>> no annotation.
>> 3. In the subsequent release `public protocol` without annotation becomes an 
>> error.
>> 4. In the subsequent relase `public protocol` without annotation takes on 
>> the new semantics.
>> 5. `@nonopen` becomes a warning, and evenutally an erro as soon as we are 
>> comfortable making those changes.
> 
> I don’t think we need @nonopen or warnings. IMHO, public/open should have the 
> same semantics and syntax regardless of whether the declaration is a protocol 
> or a concrete type (or a property?).
> 
> Other than that nit, I can’t think of a reason to oppose this. So… +1, 
> because I like making things as consistent as possible (also because of the 
> reasons in the motivation).

The purpose of using `@nonopen` for the migration is to eventually break 
people’s code if they don’t use the migrator and don’t annotate it.  If we 
don’t do that the library may ship a version that unintentionally breaks their 
clients (by continuing to use `public` after its meaning has changed).  

It’s better to break the library before it breaks any clients.  That will 
impact many fewer developers.  This can be handled automatically by the 
migrator and will be a relatively minor inconvenience for developers who don’t 
use it.  That’s better than allowing an accidentally bad version of a library 
from shipping.

> 
> - Dave Sweeris

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


Re: [swift-evolution] [Draft] open and public protocols

2017-02-18 Thread David Sweeris via swift-evolution

> On Feb 18, 2017, at 12:41 PM, Matthew Johnson via swift-evolution 
>  wrote:
> 
> ## Source compatibility
> 
> This proposal breaks source compatibility, but in a way that allows for a 
> simple mechanical migration.  A multi-release stratgegy will be used to roll 
> out this proposal to provide maximum possible source compatibility from one 
> release to the next.
> 
> 1. In Swift 4, introduce the `open` keyword and the `@nonopen` attribute 
> (which can be applied to `public protocol` to give it the new semantics of 
> `public`).
> 2. In Swift 4 (or 4.1 if necessary) start warning for `public protocol` with 
> no annotation.
> 3. In the subsequent release `public protocol` without annotation becomes an 
> error.
> 4. In the subsequent relase `public protocol` without annotation takes on the 
> new semantics.
> 5. `@nonopen` becomes a warning, and evenutally an erro as soon as we are 
> comfortable making those changes.

I don’t think we need @nonopen or warnings. IMHO, public/open should have the 
same semantics and syntax regardless of whether the declaration is a protocol 
or a concrete type (or a property?).

Other than that nit, I can’t think of a reason to oppose this. So… +1, because 
I like making things as consistent as possible (also because of the reasons in 
the motivation).

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