> On Feb 20, 2017, at 5:43 AM, Ross O'Brien via swift-evolution > <swift-evolution@swift.org> wrote: > > My two cents: > > I like that Swift has a way of restricting access to some properties and > functions to just the scope in which they're declared (Swift 3 private). > > At the moment I tend to use the Swift idiom of declaring a type, and then > declaring an extension each protocol conformance, and sometimes that means > putting a property in the type rather than the extension and that requires > fileprivate. That's not ideal, but if there were an idiomatically neater way > to declare a private property in the extension and have Swift recognise that > property as being part of the type but contextually linked only to that > protocol conformance then that would be good. > > 'Fileprivate' makes files equivalent to submodules, and this can lead to > undesirably long files. Possibly the dependence on filesystem structure feels > restrictive to some developers. It seems to me that in this four-tier > structure (public, internal, fileprivate, private) that a significant number > of developers think that's one, maybe two tiers too many (the system should > be simplified), and for others that's one, maybe two tiers too few > (fileprivate is doing too much, and a submodule tier would relieve that > pressure). > > I think a submodule access level has been suggested a lot of times, but I > don't think anyone's formally proposed a possible syntax for it. > > As Goffredo Marocchi said, I don't want to return to Objective C's dozen > import statements at the top of a file, but how would we denote that a file > is a member of a submodule? At the moment I think there are four ways - have > I missed any? > > 1) Submodules correspond directly to file directories (simple, but possibly > binds a project too closely to an operating system, inflexible for systems > like Git). > 2) The submodule has an access control file which lists its member files (as > modules do) > 3) Files opt-in to membership of a submodule (e.g. 'memberOf Submodule' just > below 'import Foundation') > 4) Files 'friend' other files into their submodule, somehow. > > Worth noting: the latter three of these suggestions don't implicitly prevent > a file from being a member of more than one submodule. > > I don't have my own answer to this question yet, but I think discussion of it > will help decide whether submodules are a practical possibility. If they are, > perhaps there's justification for fileprivate; if not, perhaps reverting to > Swift 2's private is better.
Thanks for bringing up submodules again! I think a well-designed, flexible submodule mechanism would be very nice to have. There are many issues that should be addressed along the way. Here are just a few: * How do we define the files that make up a submodule? (as you point out) * Are submodules hierarchical, allowing submodules to be nested inside of another submodule? * How does a submodule specify visibility of a member that is not public but is available to the rest of the module (or perhaps just a parent submodule)? * Can submodules have cross-dependencies? * Should it be possible for users of a module to import only a submodule rather than the entire module? * Should it be possible to compile submodules independently? * How do submodules interact with whole module optimization? * How do submodules address (or not address) namespacing? The last question is somewhat important. The design of submodules should not proceed without considering namespaces and whether or not submodules are intended to address this problem. In some languages, code in another file can introduce new names into a namespace declared elsewhere (i.e. they are module-less). Is this important? Some people may want to have namespaces that are open to extension (which obviously submodules are not). What are the use cases? If we decide we don’t need namespaces that are open to extension then submodules may be a suitable mechanism for handling use cases sometimes addressed with namespaces. One interesting thing to note is that if we do introduce submodules, especially if we introduce hierarchical submodules, then we have a pretty clean hierarchy of nested scopes. We could even say that files are an anonymous submodule. The picture looks like this: module | grandparent submodule | parent submodule | submodule | anonymous file submodule | outer lexical scope | inner lexical scope If we go in this direction and we want to allow submodules to expose a member upwards to a containing submodule, but not to the rest of the module as a whole, we will need some kind of way to refer to the name of the containing submodule. One logical way to do that is to simply parameterize `private` as some have suggested: private // current lexical scope private(OuterType) // imagine this: struct OuterType { struct InnerType { private(OtherType) var x = 42 } } private(file) private(ParentModule) private(GrandparentModule) The argument would be required to be a containing scope. This is pretty elegant and powerful. Unfortunately, it doesn’t work well with the behavior people expect from `private` because Swift relies heavily on extensions. People want `private` to be a good default that works well with the idiom of using extensions. This is why I think we should not abandon scoped access, but instead give it a new name. Scoped access does not need to be just about scopes *within* a file. This mechanism can be used for any scopes. Imagine reverting `private` to have the behavior people expect and using `scoped` for the more general mechanism: scoped // current lexical scope scoped(OuterType) // imagine this: struct OuterType { struct InnerType { private(OtherType) var x = 42 } } scoped(file) // private is an alias for this scoped(ParentSubmodule) scoped(GrandparentSubmodule) scoped(module) // internal is an alias for this This allows us to have a *single* inside the module access control mechanism which is powerful enough to handle submodules well that just happens to have a couple of syntactic sugar aliases for the most common use cases. We could even ditch `internal` since it is the default and thus rarely stated explicitly. We would have another available for those who do wish to state it explicitly. If we want to have an elegant but powerful system of access control I really think this is the way to go. If we don’t do this we could easily end up with a clunkier and less powerful mechanism that only works with submodules. > > Thanks, > Ross > > > On Mon, Feb 20, 2017 at 10:41 AM, Dimitri Racordon via swift-evolution > <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote: > I really don’t like the idea of an attritional access control file. > > Not everybody is using an IDE that automagically creates the structures and > files for your favourite language, and I would hate to see Swift go the Java > way where it’s impossible to build something seriously without Eclipse or > Netbeans. Xcode is great, but I think we should not design Swift thinking > it’s the norm to use it. > > I’d favourite any kind of syntax that is baked in the same file as the code. > > Thanks, > Dimitri > > _______________________________________________ > swift-evolution mailing list > swift-evolution@swift.org <mailto:swift-evolution@swift.org> > https://lists.swift.org/mailman/listinfo/swift-evolution > <https://lists.swift.org/mailman/listinfo/swift-evolution> > > > _______________________________________________ > swift-evolution mailing list > swift-evolution@swift.org > https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution