[swift-evolution] [Proposal][Discussion] Qualified Imports
Shawn Erickson
shawnce at gmail.com
Thu Jul 21 12:00:45 CDT 2016
I agree with your line of reasoning regarding not needing 'hiding'
(leveraging order of lookup as you noted).
On Thu, Jul 21, 2016 at 12:41 PM Joe Groff via swift-evolution <
swift-evolution at swift.org> wrote:
>
> > On Jul 20, 2016, at 1:59 PM, Xiaodi Wu via swift-evolution <
> swift-evolution at swift.org> wrote:
> >
> > Why is hiding in-scope but renaming out-of-scope? Both are additive to
> Swift, and as has been argued by others, the former is a special case of
> the latter.
>
> Hiding also doesn't seem useful to me at all. The main use case I can see
> is to resolve a name conflict introduced between two import-everything
> declarations, or between an imported and local name, and both of these use
> cases seem better served to me by a name lookup rule that locals are
> favored over qualified imports, which in turn are favored over everything
> imports. 'hiding' puts the import declaration in the wrong place. Consider
> that:
>
> import Foo hiding foo
> import Bar
>
> foo()
>
> declares the un-import of 'foo' next to 'Foo'. The user (or IDE) has to do
> the mental gymnastics to figure out that 'foo()' refers to Bar.foo() by
> omission. This is much clearer expressed with 'using', which puts the
> disambiguation next to the chosen module:
>
> import Foo
> import Bar
> import Bar using foo // favor Bar.foo over Foo.foo
>
> foo()
>
> 'using' is also more resilient against module evolution; as modules gain
> new members, their clients would potentially be forced to play whack-a-mole
> with 'hiding' as new conflicts are introduced. A user who diligently uses
> qualified imports doesn't need to worry about that. I would suggest
> removing 'hiding' in favor of a rule like this.
>
> -Joe
>
> > On Wed, Jul 20, 2016 at 15:55 Brandon Knope <bknope at me.com> wrote:
> > I meant is there any reason for requiring parentheses
> >
> > On Jul 20, 2016, at 4:53 PM, Robert Widmann <rwidmann at apple.com> wrote:
> >
> >> Renaming is out of scope for this proposal, that’s why.
> >>
> >>> On Jul 20, 2016, at 1:26 PM, Brandon Knope <bknope at me.com> wrote:
> >>>
> >>> I prefer this 100x more
> >>>
> >>> Is there any reason why this wouldn't work?
> >>>
> >>> Brandon
> >>>
> >>> On Jul 20, 2016, at 4:13 PM, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
> >>>
> >>>> Yeah, I'd be happy to lose the parentheses as well.
> >>>>
> >>>> In the last thread, my take on simplifying the proposed syntax was:
> >>>>
> >>>> ```
> >>>> import Swift using String, Int
> >>>>
> >>>> // or, for hiding:
> >>>> import Swift using Int as _
> >>>> ```
> >>>>
> >>>> The key simplification here is that hiding doesn't need its own
> contextual keyboard, especially if we support renaming (a huge plus in my
> book), as renaming to anything unused (or explicitly to `_`) is what hiding
> is all about.
> >>>> On Wed, Jul 20, 2016 at 15:01 Brandon Knope <bknope at me.com> wrote:
> >>>>
> >>>>
> >>>> On Jul 20, 2016, at 3:08 PM, Xiaodi Wu via swift-evolution <
> swift-evolution at swift.org> wrote:
> >>>>
> >>>>> As Joe and others mentioned in the previous thread, this syntax
> could be greatly simplified in ways that resemble analogous facilities in
> other languages. In particular I think it's alarmingly asymmetrical that,
> in your proposal, `import Swift using (String)` imports *only* String while
> `import Swift hiding (String)` imports *everything but* String. This
> becomes evident when chained together:
> >>>>>
> >>>>> ```
> >>>>> import Swift using (String, Int)
> >>>>> // imports only String and Int
> >>>>> import Swift using (String, Int) hiding (String)
> >>>>> // imports only Int
> >>>>> import Swift hiding (String, Int)
> >>>>> // imports everything except String and Int
> >>>>> import Swift hiding (String, Int) using (String)
> >>>>> // imports *nothing*? nothing except String? everything except Int?
> confusing.
> >>>>> ```
> >>>>>
> >>>>> By contrast, Joe's proposed syntax (with some riffs) produces
> something much more terse *and* much more clear:
> >>>>>
> >>>>> ```
> >>>>> import Swift.*
> >>>>> import Swift.(Int as MyInt, *)
> >>>>> import Swift.(Int as _, *)
> >>>>> ```
> >>>>
> >>>> I really don't find this much clearer than the proposed one. The
> proposal reads much clearer.
> >>>>
> >>>> Joe's syntax has a lot going on in my opinion.
> >>>>
> >>>> For the proposal, do we really need the parentheses? It makes the
> syntax look heavier
> >>>>
> >>>> Brandon
> >>>>
> >>>>
> >>>>
> >>>>>
> >>>>>
> >>>>> On Wed, Jul 20, 2016 at 1:52 PM, Robert Widmann via swift-evolution <
> swift-evolution at swift.org> wrote:
> >>>>> Hello all,
> >>>>>
> >>>>> I’d like to thank the members of the community that have guided the
> revisions of this proposal. We have decided to heed the advice of the
> community and break down our original proposal on modules and qualified
> imports into source-breaking (qualified imports) and additive (modules)
> proposals. As qualified imports is the change most suited to Swift 3, we
> are pushing that proposal now as our final draft.
> >>>>>
> >>>>> It can be had inline with this email, on Github, or as a gist.
> >>>>>
> >>>>> Thanks,
> >>>>>
> >>>>> ~Robert Widmann
> >>>>>
> >>>>> Qualified Imports Revisited
> >>>>>
> >>>>> • Proposal: SE-NNNN
> >>>>> • Authors: Robert Widmann, TJ Usiyan
> >>>>> • Status: Awaiting review
> >>>>> • Review manager: TBD
> >>>>>
> >>>>> Introduction
> >>>>>
> >>>>> We propose a complete overhaul of the qualified imports syntax and
> semantics.
> >>>>>
> >>>>>
> >>>>> Motivation
> >>>>>
> >>>>> The existing syntax for qualified imports from modules is needlessly
> explicit, does not compose, and has a default semantics that dilutes the
> intended meaning of the very operation itself. Today, a qualified import
> looks something like this
> >>>>>
> >>>>> import class Foundation.Date
> >>>>> This means that clients of Foundation that wish to see only Date
> must know the exact kind of declaration that identifier is. In addition,
> though this import specifies exactly one class be imported from Foundation,
> the actual semantics mean Swift will recursively open all of Foundation's
> submodules so you can see, and use, every other identifier anyway - and
> they are not filtered from code completion. Qualified imports deserve to be
> first-class in Swift, and that is what we intend to make them with this
> proposal.
> >>>>>
> >>>>>
> >>>>> Proposed solution
> >>>>>
> >>>>> The grammar and semantics of qualified imports will change
> completely with the addition of import qualifiers and import directives. We
> also introduce two new contextual keywords: using and hiding, to facilitate
> fine-grained usage of module contents.
> >>>>>
> >>>>>
> >>>>> Detailed design
> >>>>>
> >>>>> Qualified import syntax will be revised to the following
> >>>>>
> >>>>> import-decl -> import <import-path> <(opt) import-directive-list>
> >>>>> import-path -> <identifier>
> >>>>> -> <identifier>.<identifier>
> >>>>> import-directive-list -> <import-directive>
> >>>>> -> <import-directive> <import-directive-list>
> >>>>> import-directive -> using (<identifier>, ...)
> >>>>> -> hiding (<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 2 operations:
> >>>>>
> >>>>> 1) using: The using directive is followed by a list of identifiers
> for non-member nominal declarations within the imported module that should
> be exposed to this file.
> >>>>>
> >>>>> // The only visible parts of Foundation in this file are
> >>>>> // Foundation.Date, Foundation.DateFormatter, and
> Foundation.DateComponents
> >>>>> //
> >>>>> // Previously, this was
> >>>>> // import class Foundation.Date
> >>>>> // import class Foundation.DateFormatter
> >>>>> // import class Foundation.DateComponents
> >>>>> import Foundation using (Date, DateFormatter, DateComponents)
> >>>>> 2) hiding: The hiding directive is followed by a list of identifiers
> for non-member nominal declarations within the imported module that should
> be hidden from this file.
> >>>>>
> >>>>> // Imports all of Foundation except `Date`
> >>>>> import Foundation hiding (Date)
> >>>>> As today, all hidden identifiers do not hide the type, they merely
> hide that type’s members and its declaration. For example, this means
> values of hidden types are still allowed. Unlike the existing
> implementation, using their members is forbidden.
> >>>>>
> >>>>> // Imports `DateFormatter` but the declaration of `Date` is hidden.
> >>>>> import Foundation
> >>>>> using (DateFormatter)
> >>>>>
> >>>>>
> >>>>> var d = DateFormatter().date(from: "...") // Valid
> >>>>> var dt : Date = DateFormatter().date(from: "...") // Invalid: Cannot
> use name of hidden type.
> >>>>>
> >>>>> d
> >>>>> .addTimeInterval(5.0) // Invalid: Cannot use members of hidden type.
> >>>>> Import directives chain to one another and can be used to create a
> fine-grained module import:
> >>>>>
> >>>>> // This imports Swift.Int, Swift.Double, and Swift.String but hides
> Swift.String.UTF8View
> >>>>> import Swift using (String, Int, Double
> >>>>> )
> >>>>> hiding (
> >>>>> String.UTF8View)
> >>>>> Directive chaining occurs left-to-right:
> >>>>>
> >>>>> // 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.
> >>>>> import Swift using (Int) hiding (String
> >>>>> )
> >>>>>
> >>>>> // 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)
> >>>>> Because import directives are file-local, they will never be
> exported along with the module that declares them.
> >>>>>
> >>>>>
> >>>>> 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 and should be removed or migrated.
> >>>>>
> >>>>>
> >>>>> Alternatives considered
> >>>>>
> >>>>> A previous iteration of this proposal introduced an operation to
> allow the renaming of identifiers, especially members. The original intent
> was to allow file-local modifications of APIs consumers felt needed to
> conform to their specific coding style. On review, we felt the feature was
> not as significant as to warrant inclusion and was ripe for abuse in large
> projects.
> >>>>>
> >>>>>
> >>>>> _______________________________________________
> >>>>> swift-evolution mailing list
> >>>>> swift-evolution at swift.org
> >>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
> >>>>>
> >>>>>
> >>>>> _______________________________________________
> >>>>> swift-evolution mailing list
> >>>>> swift-evolution at swift.org
> >>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
> >>
> > _______________________________________________
> > swift-evolution mailing list
> > swift-evolution at swift.org
> > https://lists.swift.org/mailman/listinfo/swift-evolution
>
> _______________________________________________
> 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/20160721/cd45ca9b/attachment.html>
More information about the swift-evolution
mailing list