> > > Modules names are tied to a directory structure that describes their > location relative to the current module and it will now be an error to > violate this rule. For example: > > > > module String // lives in ./String.swift > > > > module String.Core // lives in ./String/Core.swift > > > > module String.Core.Internals.Do.You.Even.Write // lives in > ./String/Core/Internals/Do/You/Even/Write.swift > I think this is a mistake for several reasons: > * You may need to split a single submodule across multiple files, but this > rule doesn't allow that.
You can, internally, have several modules and then create one that imports those smaller ones publicly with the name that you desire. > > * The module declaration and filename contain redundant information, and > one of them could get out of sync with the other. I agree with this point though I am not sure that it is so much of an issue. Diagnostics can handle much of the issue. > > * Xcode doesn't like to organize things into folders on disk and will > fight you tooth and nail. > * Deeply nested folders are a usability issue. Never forget the jury in > Oracle v. Google: > https://www.geek.com/wp-content/uploads/2016/05/courtroomhijinks.png On Mon, Jul 18, 2016 at 7:34 PM, Brent Royal-Gordon via swift-evolution < [email protected]> wrote: > > On Jul 18, 2016, at 2:09 PM, Robert Widmann via swift-evolution < > [email protected]> wrote: > > > > Hello all, > > > > TJ Usiyan, Harlan Haskins, and I have been working on a proposal to > rework qualified imports and introduce an explicit module system to Swift > that we’d like to publish for your viewing pleasure. > > This is really interesting. A few incomplete comments: > > > 2) hiding: The hiding directive is followed by a list of identifiers > within the imported module that should be hidden from this file. > > > > // Imports all of Foundation.Date except `Date.compare()` > > import Foundation.Date hiding (Date.compare()) > [snip] > > // Exports the entire public contents of Math.Integers, but nothing in > > // Math.Integers.Arithmetic. > > public import Math.Integers > > Would this work? > > module UIKit > > public import UIKit.UIGestureRecognizerSubclass.UIGestureRecognizer > hiding (UIGestureRecognizer.touchesBegan(_:with:), > UIGestureRecognizer.touchesMoved(_:with:), …) > > (If so, we'd need a way to hide only the setter of a property, not the > getter.) > > > Modules names are tied to a directory structure that describes their > location relative to the current module and it will now be an error to > violate this rule. For example: > > > > module String // lives in ./String.swift > > > > module String.Core // lives in ./String/Core.swift > > > > module String.Core.Internals.Do.You.Even.Write // lives in > ./String/Core/Internals/Do/You/Even/Write.swift > > I think this is a mistake for several reasons: > > * You may need to split a single submodule across multiple files, but this > rule doesn't allow that. > > * The module declaration and filename contain redundant information, and > one of them could get out of sync with the other. > > * Xcode doesn't like to organize things into folders on disk and will > fight you tooth and nail. > > * Deeply nested folders are a usability issue. Never forget the jury in > Oracle v. Google: > https://www.geek.com/wp-content/uploads/2016/05/courtroomhijinks.png > > At the very least, I would like to see allowances for multi-file > submodules—String/Core/Internals/Do/You/Even/Write**.swift. Better would be > to use long filenames—String.Core.Internals.Do.You.Even.Write*.swift. Even > better would be to just allow freeform naming and trust programmers to > organize their projects sanely. > > > Existing projects that do not adopt these rules will still retain their > implicit module name (usually defined as the name of the framework or > application that is being built) and may continue to use whatever directory > structure they wish, however they may not declare any explicit modules. > > > > This proposal also solves the problem of module export. A module that is > imported without an access level modifier will default to an internal > import per usual. However, when it is useful to fully expose the public > content of submodules to a client, a public modifier can be used. > Similarly, when it is useful to access internal or [file]private APIs, but > not expose them to clients, those access modifiers may be used. The rule of > thumb is: Only identifiers that are at least as visible as the qualifier on > the import make for valid import declarations. > > It appears the semantics here are "grab all declarations at level X and > above, and expose them in this module as level X". This is bizarre for a > number of reasons: > > * Currently, `import` can only access `internal` declarations using > `@testable`. This would change that. > > * Currently, `import` can't access `private` and `fileprivate` > declarations at all, and it's not clear what it would mean to add that. > What happens if two different parts of the module have different `private` > members with the same name? Which do you get? > > * Currently, `import` only affects the current file—it's effectively > "import `public` members as `fileprivate`". If your default is `internal > import`, that would imply that an import statement in one file would, by > default, expose the APIs it imported to all files. That's an important > change in behavior. > > I think you're mixing two things together that ought not to be. `import` > should always import only public APIs (unless you use `@testable`—which > might need a bit of renaming to support the additional use case of SPIs > between submodules and supermodules—in which case you also get `internal` > APIs). An access modifier on the `import` statement controls how they're > exposed to the rest of the file/project/world, and `private` is the > default. It's a little weird to have `private` be the default on `import` > when `internal` is the default on everything else, but the alternative is > to change `import`'s behavior in a way that is neither > backwards-compatible, nor likely to be correct. > > > Because import directives are file-local, they will never be exported > along with a public import and will default to exporting the entire > contents of the module as though you had never declared them. > > Whoa, wait, what? Why? I think hiding parts of the implementation is a > good use case for re-exporting a module. And I think the clear implication > of attaching these clauses directly to the import statement is that it > controls how the module is imported everywhere that statement makes it > visible, not just within the one file. If we're not going to do that, I > think these clauses ought to be separated from the `import` statement and > turned into something separate. > > -- > Brent Royal-Gordon > Architechies > > _______________________________________________ > swift-evolution mailing list > [email protected] > https://lists.swift.org/mailman/listinfo/swift-evolution >
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
