> 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

Reply via email to