Totally agree with Joe here. I’d like to see a simplified version of the import design through ASAP. Mot people will quickly agree with it. The rest of the proposal is much more up for discussion IMHO.
> On 19 Jul 2016, at 03:19, Joe Groff via swift-evolution > <swift-evolution@swift.org> wrote: > > Our import story definitely needs work, and this is a step in the right > direction. Thanks for working on this! Some comments: > > - The import changes can be separated from the submodule issues. Enhancing > imports is IMO more important, and is source-breaking today, whereas 'module > ' declarations and submodules can be added later. I'd suggest breaking this > into two proposals. > - I think the `import` design you propose is a bit more complicated than it > needs to be. Python and Haskell get by just having "import everything" and > "import itemized (with aliases)". I don't see the need for 'hiding'; if you > have a rule that itemized imports get priority over import-everything, then > that covers the most important use case of selectively shadowing one module's > imports with another. Bikeshed-wise, I don't see much reason to veer from the > Java/Haskell-ish template of: > > import Foo.* // import everything from module Foo > import Foo.(x, y, z as zed) // import x, y, and z from foo, renaming Foo.z to > zed > > -Joe > >> On Jul 18, 2016, at 2:09 PM, Robert Widmann via swift-evolution >> <swift-evolution@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. >> >> The initial impetus was set out in a radar (rdar://17630570) I sent fairly >> early on that didn’t receive a response, so I started a swift-evolution >> 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 or on Github. >> >> Cheers, >> >> ~Robert Widmann >> >> Qualified Imports and Modules >> >> • Proposal: SE-NNNN >> • Authors: Robert Widmann, Harlan Haskins, TJ Usiyan >> • Status: Awaiting review >> • Review manager: TBD >> Introduction >> >> We propose a complete overhaul of the qualified imports syntax and semantics >> and the introduction of a module system. >> >> Motivation >> >> Swift code is modular by default. However, it is not clear how to decompose >> existing modules further into submodules. In addition, it is difficult to >> tell how importing a module affects its export to consumers of a library. >> This leads many to either fake namespaces with enums, attempt to structure >> Swift code with modulemaps, or use a large amount of version-control >> submodules. All of these can be rolled into one complete package in the form >> of a comprehensive rethink of the qualified import system and the >> introduction of a module system. >> >> Proposed solution >> >> Modules will now become an explicit part of working with canonical Swift >> code. The grammar and semantics of qualified imports will change completely >> with the addition of import qualifiers and import directives. We also >> introduce three new contextual keywords: using, hiding, and renaming, to >> facilitate fine-grained usage of module contents. >> >> Detailed design >> >> Qualified import syntax will be revised to the following >> >> module-decl -> module <module-path> >> import-decl -> <access-level-modifier> import <module-path> <(opt) >> import-directive-list> >> module-path -> <identifier> >> -> <identifier>.<import-path> >> import-directive-list -> <import-directive> >> -> <import-directive> <import-directive-list> >> import-directive -> using (<identifier>, ...) >> -> hiding (<identifier>, ...) >> -> renaming (<identifier>, to: <identifier>, ...) >> >> This introduces the concept of an import directive. An import directive is a >> file-local modification of an imported identifier. A directive can be one of >> 3 operations: >> >> 1) using: The using directive is followed by a list of identifiers within >> the imported module that should be exposed to this file. >> >> // The only visible parts of Foundation in this file are >> // Date.init(), Date.hashValue, and Date.description. >> import Foundation.Date using (Date.init(), Date.hashValue, Date.description) >> 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()) >> 3) renaming: The renaming directive is followed by a list of identifiers >> separated by to: that should be exposed to this file but renamed. >> >> // Imports all of Dispatch.DispatchQueue but renames the static member >> // DispatchQueue.main, to DispatchQueue.mainQueue >> import Dispatch.DispatchQueue renaming (DispatchQueue.Type.main to: >> DispatchQueue.Type. >> mainQueue) >> >> // Renaming can also rename modules. All members of UIKit have to be >> qualified with >> // `UI` now. >> import UIKit renaming (UIKit, to: UI) >> Import directives chain to one another and can be used to create a >> fine-grained module import: >> >> // Imports all of Foundation except `DateFormatter` and renames `Cache` to >> `LRUCache` >> import Foundation >> hiding (DateFormatter) renaming (Cache to: LRUCache) >> >> // Imports SCNNode except SCNNode.init(mdlObject:) and renames >> `.description` to >> // `.nodeDescription` >> import SceneKit >> using (SCNNode) >> renaming (SCNNode >> .description, to: SCNNode. >> nodeDescription) >> hiding (SCNNode >> .init(mdlObject:)) >> Directive chaining occurs left-to-right: >> >> // This says to 1) Hide nothing 2) Use nothing 3) rename Int to INT. It is >> invalid >> // because 1) We will show everything 2) Then hide everything 3) Therefore >> Int is unavailable, error. >> import Swift hiding () using () renaming (Int >> , to: INT) >> >> // This says to 1) Use Int 2) Hide String 3) rename Double to Triple. It is >> invalid >> // because 1) Int is available 2) String is not, error. 3) Double is >> unavailable, error. >> import Swift using (Int) hiding (String) renaming (Double >> , to: Triple) >> >> // Valid. This will be merged as `using (Int)` >> import Swift using () using (Int >> ) >> >> // Valid. This will be merged as `hiding (String, Double)` >> import Swift hiding (String) hiding (Double >> ) hiding () >> >> // Valid (if redundant). This will be merged as `using ()` >> import Swift using (String) hiding (String) >> Module scope is delimited by the keyword module followed by a fully >> qualified name and must occur as the first declaration in a file. For >> example: >> >> // ./Math/Integers/Arithmetic.swift >> >> module Math >> .Integers. >> Arithmetic >> >> >> public protocol >> _IntegerArithmetic {} >> >> >> public struct >> _Abs {} >> >> >> @_versioned >> internal func _abs<Args>(_ args: Args) -> >> (_Abs, Args) {} >> >> >> // ./Math/Integers.swift >> >> module Math >> . >> Integers >> >> >> // _abs is visible in this module and all others within the project, >> // but is not exported along with it. >> internal import Math.Integers.Arithmetic >> >> >> >> public protocol IntegerArithmetic : _IntegerArithmetic, Comparable >> {} >> >> public protocol SignedNumber : Comparable >> , ExpressibleByIntegerLiteral {} >> >> >> >> // Math.swift >> >> module Math >> >> >> // Exports the entire public contents of Math.Integers, but nothing in >> // Math.Integers.Arithmetic. >> public import Math.Integers >> 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 >> 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. For example: >> >> // A submodule declaring a `private` class that gets imported with >> // an `internal` qualifier with a `using` directive is an invalid import >> // declaration. >> >> module Foo >> . >> Bar >> >> >> private class >> PrivateThing {} >> >> module Foo >> >> >> // Error: PrivateThing not visible, use `private import` >> import Foo.Bar using (PrivateThing) >> // However, a submodule declaring a `public` struct that gets imported with >> // an `private` qualifier is a valid import declaration. >> >> module Foo >> . >> Bar >> >> >> public class >> PublicThing {} >> >> module Foo >> >> >> // All good! Foo can see Foo.Bar.PrivateThing. >> private import Foo.Bar using (PublicThing) >> 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. >> >> // In this file and this file alone, the directives apply. To the user >> // of this module, it is as though this declaration were simply: >> // public import Foundation.Date >> public import Foundation.Date hiding (Date.init >> ()) >> renaming (Date >> .Type. >> distantPast, >> to: Date >> .Type. >> letsGoLivingInThePast, >> Date >> .Type. >> timeIntervalSinceReferenceDate, >> to: Date >> .Type. >> startOfTheUniverse) >> renaming (Date >> .Type.<, to: Date.Type.<<<<<) >> Impact on existing code >> >> Existing code that is using qualified module import syntax (import >> {func|class|typealias|class|struct|enum|protocol} <qualified-name>) will be >> deprecated. Code that is not organized into modules will remain unaffected >> and organized into one contiguous top-level module. However, it is strongly >> recommended that frameworks be decomposed and reorganized around the new >> module system. >> >> As a case study, the public interface to the standard library appears to >> already be mostly broken down into submodules as described in GroupInfo.json. >> >> Code that is defined in modulemaps already defines a module structure that >> can be imported directly into this scheme. >> >> Alternatives considered >> >> Module export can also be placed on the module declaration itself. The >> relevant parts of the grammar that have changed are below with an example: >> >> module-decl -> <access-level-modifier> module <module-path> >> import-decl -> import <module-path> <(opt) import-directive-list> >> >> private module String.Core. >> Internals >> >> >> // Shh, it's a secret. >> While this style makes it immediately obvious to the library author which >> modules are public or private, it causes the consumer problems because >> submodule exports are no longer explicit and are entirely ad-hoc. In the >> interest of enabling, for one, users of IDEs to drill into public >> submodules, making export local to import seems more appropriate. >> _______________________________________________ >> 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 _______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution