> 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