> On 19 Jul 2016, at 00:09, Robert Widmann via swift-evolution 
> <[email protected]> wrote:
> 
> 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.
> 
> The initial impetus was set out in a radar (rdar://17630570 
> <rdar://17630570>) I sent fairly early on that didn’t receive a response, so 
> I started a swift-evolution 
> <http://permalink.gmane.org/gmane.comp.lang.swift.evolution/1378> thread 
> discussing the basics of this proposal.  It has been refined and expanded a 
> bit to include an effort to make Swift modules explicit and updated with the 
> feedback of that first thread.  Contents of the proposal are inline and can 
> also be had as a gist 
> <https://gist.github.com/CodaFi/42e5e5e94d857547abc381d9a9d0afd6> or on 
> Github. <https://github.com/apple/swift-evolution/pull/440>

Firstly, thank you Robert, TJ, and Harlan for the proposal and especially for 
considering the introduction of submodules too! Those would be very useful when 
Swift libraries start growing. But maybe we can delay that discussion past 
Swift 3.

* * *

Secondly, I used to be in the selective import camp before, but I think it's 
somewhat counter to Swift's feel and direction where most of the API is wrapped 
inside types, and function names consist of not just the base name but argument 
labels too (even if we now have the "Gregorian" naming SE-0021 available). So 
while I don't see a big problem introducing something like

    import Foo.(fooConstant, bar(a:b) as bar1(a:b:), IrrelevantType as _)

to pick identifiers à la carte, I don't think it would be useful very often. 
And the alternative of accessing `bar` through the module name as `Foo.bar` 
does work just as well already.

…Well, that is except for the problem when the module name `Foo` happens to be 
shadowed by a non-module name `Foo`. I'd rather tackle that problem, and I do 
so as follows:

* * *

My usual pain points with imported (micro-)frameworks have been:

A) …when two modules (e.g. `Foo` and `Bar`) export the same identifier (`baz`) 
for different meanings.
B) …when a local or imported identifier (e.g. `class Tree`) has the same name 
as a module `Tree`.

In case A, I can just disambiguate by prefixing with the module name: `Foo.baz` 
vs. `Bar.baz`.

In case B, there is really no way around that I'm aware of. Anyway you write 
`Tree.foo` Swift will try to look up under the type `Tree` and never the module 
`Tree`.

Those two issues could be addressed by simply introducing qualified imports as 
follows:

    import Darwin as Darwin // qualified import (there could be a shorthand but 
what?)
    import UIKit as UI      // qualified import with renaming
    import Tree             // unqualified import brings in struct Tree.Tree, 
among others.
    import Tree as T        // qualified import
    
    let out = Darwin.stdout      // ok
    var vc: UI.UIViewController? // ok
    let tree: Tree = T.emptyTree // ok; `struct Tree.Tree` was imported 
unqualified
    
    let err = stderr
    // error: Use of unresolved identifier 'stderr'
    // note: did you mean 'Darwin.stderr'?
    
    var view: UIView?
    // error: Use of unresolved type 'UIView'
    // note: did you mean 'UI.UIView'?
    
    enum UI {}
    // error: invalid redeclaration of 'UI'
    // note: 'UI' previously declared (line 2)

The qualified import syntax, `import MODULE as NAME`, imports the module MODULE 
such that its contents can be accessed through the prefix of `NAME.` – but not 
without it, unless also imported without qualification.

The given NAME uses up that identifier in the current scope (as if it was a 
private type) such that there can be no locally visible type or value with the 
same name in that scope. For example, if the current module defined NAME 
publicly or internally in another file, then that identifier would be shadowed 
in this file by the qualified module name NAME.

Side note: It is still possible to chain multiple module imports, qualified or 
not, on the same line (albeit not a particularly good coding style if they're 
unrelated). The order of imports does not matter. So the above example could've 
been written as:

    import Darwin as Darwin, UIKit as UI, Tree as T, Tree

* * *

I think that's the small change we need most urgently. The rest can wait.

— Pyry

PS: Another thing I'd see useful, especially when migrating code from the 
`MyPlayground_Sources` module to a real project would be a syntax something 
like `_.foo` to access the `foo` that is visible in the current file top-level, 
so to escape any local shadowing.

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to