Modules in Swift are really designed for code that is intended to be shipped separately. as Jon found out modules are pretty heavyweight and introduce a lot of unwanted abstraction and complexity when all you want to do is write things in a namespace. (Also if you forgot, importing a module in Swift dumps all of its symbols into the global namespace so Module.Thing is really meaningless.) sometimes this is a good thing because no one wants to be writing Glibc.fopen over and over especially when you have to #if #endif it out every time with Darwin.fopen if you want your library to run on OSX but this feature also makes modules ineffective as a namespacing scheme.
On Fri, Dec 29, 2017 at 8:35 PM, Eneko Alonso <eneko.alo...@gmail.com> wrote: > …all i wanted to do was write Thing:Namespace.Protocol > > > Have you thought of using Swift modules for that? Maybe that would be a > better approach than trying to name-space within a module? > > Regards, > Eneko Alonso > > On Dec 29, 2017, at 16:51, Kelvin Ma via swift-evolution < > swift-evolution@swift.org> wrote: > > …all i wanted to do was write Thing:Namespace.Protocol > > On Thu, Dec 28, 2017 at 4:43 PM, Adrian Zubarev via swift-evolution < > swift-evolution@swift.org> wrote: > >> Well again I don’t think we should disallow capturing the outer generic >> type parameter just because you cannot use the protocol inside the outer >> type atm., you still can add a type-eraser. To be honest such usage of the >> existential is not even a requirement for the outer type. On there other >> hand we might want to set the default for the associated type like I showed >> in my previous message. The nested protocol could serve a completely >> different purpose. Furthermore I still think that Generic<A>.P and >> Generic<B>.P should be distinct protocols just like nested generic and >> non-generic types are within an outer generic type. Sure there could be >> other problems with ambiguity if you think of something like >> GenericViewController<T>.Delegate, but the disambiguation when >> conforming to such protocols requires a different solution and is a well >> known limitation today. >> >> That said you won’t design such nested types anyways if you know the >> existing language limitation. I’d say let’s keep it simple in theory and >> just align the nesting behaviour. >> >> About existentials: >> >> For that scenario I can only speak for myself. I wouldn’t want to allow >> directly the where clause existentials like this. It is far better and >> more readable when we force the where clause on typealiases instead. We >> could lift that restriction later if we’d like to, but not the other way >> around. I think it’s okay if we start with a small restriction first and >> see if it adopts well (this is MHO), because this way it shouldn’t harm >> anybody. >> >> >> >> >> Am 28. Dezember 2017 um 21:51:29, Karl Wagner (razie...@gmail.com) >> schrieb: >> >> >> >> On 28. Dec 2017, at 12:34, Adrian Zubarev <adrian.zubarev@devandartist.c >> om> wrote: >> >> I disagree with some of your points. Do begin with, I don’t think we >> should disallow capturing the generic type parameter, because I think there >> might be a good way to prevent parameterization of nested protocols. >> >> To me this only feels like a natural consequence of nesting protocols >> anyways. To achieve this we have to provide an explicit associated type >> which will have a default type that refers to the captured outer generic >> type parameter. At this point we discover another issue that we cannot >> disambiguate generic type parameter like associated types yet and would be >> forced to name the associated type of the protocol differently. >> >> struct Generic<T> { >> protocol P { >> associatedtype R = T >> func f() -> R >> } >> } >> >> As you can see I didn’t include the variable in this example, because >> existential are orthogonal this issue. David Hart and I still want to write >> a proposal to allow the where clause on typealiases - maybe after the >> forum officially launches. >> >> Above I said that there is an issue and provided an example that would >> solve that issue with todays syntax, but I’d rather expand this idea. >> Consider this syntax of a generic type and a protocol with an associated >> type. >> >> protocol Proto { >> associatedtype Element >> } >> >> Proto.Element // This is an error like this, but it's still allowed in a >> generic context >> >> func function<P : Proto>(_: P) where P.Element == Int {} >> >> protocol OtherProto : Proto where Element == Int {} >> >> struct Test<Element> {} >> >> extension Test where Element == Int {} >> >> Test.Element // Can/should we allow this? >> >> If we could allow this in Swift then the above example with the nested >> protocol could be disambiguated nicely. >> >> struct Generic<T> { >> protocol P { >> associatedtype T = Generic.T >> func f() -> T >> } >> } >> >> Remember that Generic.T is only the default for P.T if you don’t set it >> yourself but when you conform or use that that protocol (in a generic >> context) you can still set it differntly. >> >> This consequence disallows protocol parameterization through nesting in a >> generic types, but still behaves very similar to nested generic types: >> >> struct Test<T> { >> struct NonGeneric { >> var t: T >> } >> >> struct Generic<R> { >> var t: T >> var r: R >> } >> } >> >> _ = Test<String>.NonGeneric(t: "😎") >> _ = Test<String>.Generic<Int>(t: "🤓", r: 42) >> >> —— >> >> >> Yeah, that’s all well and good. I don’t think we should parameterise >> protocols either; it feels like Swift hasn’t been designed with those in >> mind, and that’s fine. You would get in to all kinds of horrible conflicts >> if you tried to conform to both Generic<Int>.P and Generic<String>.P, >> because most functions would have the same signature but possibly very >> different implementations. You would likely end up having to separate the >> conformances by using a wrapper struct — in which case, why not just make >> them the same protocol and have the existing duplicate-conformance rules >> take care of it? >> >> An earlier version of the proposal included something like you describe. >> Basically, Generic<Int>.P and Generic<String>.P would be the same protocol. >> They would have an associated type to represent the parameter from >> Generic<T>, and within Generic<T>, all references to P would be implicitly >> constrained so that P.T == Self.T. You would write conformances to >> “Generic.P” with a constraint for T, as you do today. >> >> And for the existential variable inside Genric it really should be >> something like this (when the where clause is allowed and if we can refer >> differently to generic type parameters as well): >> >> struct Generic<T> { >> … >> typealias PConstrainedByT = P where T == Self.T >> var object: PConstrainedByT >> } >> >> >> If we have that ability, then we can totally do capturing. Forgive me, >> but I understand that as pretty-much the same as generalised existentials >> (without local type binding). >> If I can write the type of object as an existential of (generic protocol >> + constraints) via a typealias, then surely I must also be able to do it >> directly? So I could also write: >> >> struct Generic<T> { >> var object: P where T == Self.T >> } >> >> Anyway, I thought that was not on the table, and in any case I’m >> convinced that it should be a separate proposal. This gets to the heart of >> the interaction between generic types and protocols, and we all know it’s >> not always a smooth transition (hello AnyCollection, AnyHashable, etc...). >> We can cover the common cases (i.e. the Apple frameworks) without requiring >> capturing - especially since it’s apparently not too difficult to implement >> - and build from there. >> >> - Karl >> >> >> >> >> Am 27. Dezember 2017 um 19:53:36, Karl Wagner via swift-evolution ( >> swift-evolution@swift.org) schrieb: >> >> Yeah I wrote that proposal. I eventually stripped it down to just >> disallow all capturing, but it was still not selected by the core team for >> review ¯\_(ツ)_/¯ >> >> As for capturing semantics, once you start working through use-cases, >> it’s becomes clear that it's going to require generalised existentials. >> Otherwise, how would you use a Generic<T>.P? >> >> struct Generic<T> { >> protocol P { func f() -> T } >> >> var object: P // uh-oh! ‘Generic protocol can only be used as a >> generic parameter constraint' >> } >> >> So, you would need to add a generic parameter to actually *use* P from >> within Generic<T>, which of course limits you to a single concrete type of >> P: >> >> struct Generic<T, TypeOfP> where TypeOfP: Self.P { // Could this >> even work? What if P captures TypeOfP? >> protocol P { /* … */ } >> var object: TypeOfP >> } >> >> Which is just yucky. >> >> Ideally, the type of ‘object’ should be ‘Any<P where P.T == T>’, to >> express that it can be any conforming type with the appropriate >> constraints. You wouldn’t need to write that all out; we could infer that >> capturing is equivalent to a same-type constraint (or perhaps one of these >> “generalised supertype constraints” that were pitched recently). But we >> can’t express those kinds of existentials everywhere in the type-system >> today, so most examples of capturing fall down pretty quickly. >> >> - Karl >> >> On 25. Dec 2017, at 03:56, Slava Pestov via swift-evolution < >> swift-evolution@swift.org> wrote: >> >> There was a proposal to allow protocols to be nested inside types at one >> point but it didn’t move forward. >> >> Basically, if the outer type is a non-generic class, struct or enum, >> there’s no conceptual difficulty at all. >> >> If the outer type is a generic type or another protocol, you have a >> problem where the inner protocol can reference generic parameters or >> associated types of the outer type. This would either have to be banned, or >> we would need to come up with coherent semantics for it: >> >> struct Generic<T> { >> protocol P { >> func f() -> T >> } >> } >> >> struct Conforms : Generic<Int>.P { >> func f() -> Int { … } // Like this? >> } >> >> let c = Conforms() >> c is Generic<String>.P // is this false? Ie, are Generic<Int>.P and >> Generic<String>.P different protocols? >> >> Slava >> >> On Dec 24, 2017, at 6:53 PM, Kelvin Ma via swift-evolution < >> swift-evolution@swift.org> wrote: >> >> is there a reason why it’s not allowed to nest a protocol declaration >> inside another type? >> _______________________________________________ >> swift-evolution mailing list >> swift-evolution@swift.org >> https://lists.swift.org/mailman/listinfo/swift-evolution >> >> >> _______________________________________________ >> swift-evolution mailing list >> swift-evolution@swift.org >> https://lists.swift.org/mailman/listinfo/swift-evolution >> >> >> _______________________________________________ >> 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 > >
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution