[swift-evolution] [Proposal] Qualified Imports and Modules

T.J. Usiyan griotspeak at gmail.com
Mon Jul 18 18:50:13 CDT 2016


>
> > 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 <
swift-evolution at swift.org> wrote:

> > On Jul 18, 2016, at 2:09 PM, Robert Widmann via swift-evolution <
> swift-evolution at swift.org> 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
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160718/c2628db8/attachment.html>


More information about the swift-evolution mailing list