“The Phase Distinction” is a semantic one, not one built into the import system itself. What I meant is that even the system I’m modeling this on makes a distinction between import directives that actually expose identifiers to modules and import directives that modify identifiers that are already in scope. Ne’er the twain shall meet. A qualified import is defining a procedure to import a subset of identifiers. That’s it.
> On Jul 20, 2016, at 4:17 PM, Xiaodi Wu <[email protected]> wrote: > > On Wed, Jul 20, 2016 at 4:57 PM, Robert Widmann <[email protected] > <mailto:[email protected]>> wrote: > >> On Jul 20, 2016, at 2:52 PM, Robert Widmann via swift-evolution >> <[email protected] <mailto:[email protected]>> wrote: >> >>> >>> On Jul 20, 2016, at 2:35 PM, Xiaodi Wu <[email protected] >>> <mailto:[email protected]>> wrote: >>> >>> >>> >>> On Wed, Jul 20, 2016 at 4:24 PM, Robert Widmann <[email protected] >>> <mailto:[email protected]>> wrote: >>> >>>> On Jul 20, 2016, at 2:19 PM, Xiaodi Wu <[email protected] >>>> <mailto:[email protected]>> wrote: >>>> >>>> On Wed, Jul 20, 2016 at 4:06 PM, Robert Widmann <[email protected] >>>> <mailto:[email protected]>> wrote: >>>> >>>>> On Jul 20, 2016, at 2:04 PM, Robert Widmann via swift-evolution >>>>> <[email protected] <mailto:[email protected]>> wrote: >>>>> >>>>>> >>>>>> On Jul 20, 2016, at 1:59 PM, Xiaodi Wu <[email protected] >>>>>> <mailto:[email protected]>> wrote: >>>>>> >>>>>> Why is hiding in-scope but renaming out-of-scope? >>>>> >>>>> >>>>> Because hiding and renaming can be used in combination to subset out >>>>> APIs, not alter them. >>>>> >>>> >>>> I mistyped. Should be "Because hiding and using can be used in >>>> combination to subset out APIs, not alter them." >>>> >>>> >>>> Sure, I buy that. >>>> >>>>>> Both are additive to Swift, >>>>> >>>>> As part of this proposal, both are source-breaking. >>>> >>>> >>>> I don't see how. If hiding were cut from the proposal, adding it later >>>> with even the exact syntax you propose should break no pre-existing >>>> code--am I wrong? >>> >>> Renaming the way we originally laid it out would certainly be additive. >>> The way you have it laid out would overlap a bit with hiding, sure, but it >>> is still additive and (IMO, but I’m probably among a tiny minority of users >>> that has used a proof assistant’s syntax as the basis for a proposal!) a >>> good thing to have. >>> >>> >>> Sorry, I fear I've incorrectly communicated the point I was trying to make. >>> I'm not advocating here for inclusion of renaming as part of this proposal. >>> I simply think that--even though I buy your claim that hiding and using >>> both subset out APIs--hiding has more affinity with renaming and the two >>> facilities probably ought to be considered together, whenever that is. >>> >>> Thus, I'm suggesting that it would be feasible to postpone discussion of >>> hiding until such future time as a fully fleshed out renaming scheme is >>> proposed. A revamped source-breaking import syntax without either hiding or >>> renaming could be put in place now, and future addition of hiding and/or >>> renaming would not have to be source-breaking. Is there something wrong >>> with this argument? >>> >> >> There is still a useful to distinction to be made between explicitly >> renaming an API and explicitly hiding an API. Scala’s syntax to rename to >> underbar is a convenient notation for that kind of thing, but it goes >> against making qualified imports explicit and it means that renaming >> necessarily has to import identifiers into scope as well as rename them. >> What the OP (maybe it was you, sorry if it was) meant by “equivalent” missed >> the point that >> >> import Swift hiding (String) >> >> doesn’t translate into >> >> import Swift renaming (String, to: _) >> >> it translates into >> >> import Swift hiding () renaming (String, to: _) >> >> Renaming introducing identifiers into scope seems like a phase-shift and is >> not something the verb “rename” implies should happen here. It’s an >> interesting little hole in Agda’s module system that you can use >> >> open A hiding (xs) renaming (ys to zs) >> >> to mean >> >> open A using (A; xs; ys) renaming (ys to zs) >> > > Actually, scratch that. Their documentation explicitly mentions that hiding > and renaming may not be mixed because of the phase distinction and recommend > the using translation above as the way to go. > > > This is very illuminating. I think I've rather misunderstood what it is > you're proposing. I wonder if others did also. > > The syntax you proposed seemed cumbersome to me because my mental model of > importing (informed by my probably superficial understanding of vanilla > procedural programming languages) has only one phase: importing. This is why > I proposed radically simplifying the spelling. To me, all of these operations > are just sugar on a single import phase, where "stuff" from outside the > module is "brought into" the module, either with the same name ("using"), a > different name ("renaming"), or no name ("hiding"). > > But what you're saying here--if I understand correctly--is that you're > proposing a multi-phase import system, where the possible phases, which can > be composed in varying orders, are "using", "hiding", and "renaming". This is > much, much more elaborate than I had contemplated. So beyond the bikeshedding > of syntax, I'd ask: why do we need this multi-phase model of importing? > > > >>> >>> >>>> >>>>>> and as has been argued by others, the former is a special case of the >>>>>> latter. >>>>> >>>>> A special case that cannot cause large-scale file-relative changes to >>>>> APIs. Renaming is primarily used in other languages that treat free >>>>> functions as more canonical than we do, or allow operator definitions >>>>> that can be used as notation. >>>> >>>> >>>> I don't know about 'primary use,' but the most common use I've experienced >>>> in Python, for example, is the mundane task of importing module Foo2 as >>>> Foo. >>>> >>> >>> And I still want that kind of syntax. I just want to get the breaking >>> changes out of the way to make room for it in the future. >>> >>> >>> Right. See above about my argument as to which parts of your proposal have >>> to be source-breaking, and which don't. >>> >>> >>> >>>>> In those cases, you often have your own notation you’d like to use. In >>>>> Swift, such changes should be rare enough that if you can’t solve them >>>>> with a disambiguating qualified import then you can just redeclare the >>>>> identifier some other way (typealias, top-level let, wrapper class, >>>>> whatever). >>>> >>>> >>>> You've already stripped out renaming of members from the proposal. I agree >>>> wholeheartedly. The only flavor of renaming I'm thinking of here is >>>> equivalent to a fileprivate typealias and hiding, which cannot be done in >>>> this version of the proposal because hiding always comes before >>>> typealiasing and you can't typealias what isn't imported. It isn't about >>>> altering APIs any more than a fileprivate typealias can be thought of as >>>> altering APIs. >>> >>> In the sense that you can’t use the original identifier if you rename it, >>> it is an alteration. John brought up a great point about exporting these >>> things and how it could be a potentially dangerous thing. Even used >>> locally, there’s the potential for people to specify 500 lines of import >>> renaming crap that has to be copypasta’d throughout the codebase to >>> maintain that particular style - not a use-case I’ve ever seen, but the >>> potential is there. >>> >>> >>> This is, I think, a spurious argument. I can equally have 500 lines of >>> private typealiased crap that has to be copypasta'd. >>> >>> >>> >>>> >>>>>> On Wed, Jul 20, 2016 at 15:55 Brandon Knope <[email protected] >>>>>> <mailto:[email protected]>> wrote: >>>>>> I meant is there any reason for requiring parentheses >>>>>> >>>>>> On Jul 20, 2016, at 4:53 PM, Robert Widmann <[email protected] >>>>>> <mailto:[email protected]>> wrote: >>>>>> >>>>>>> Renaming is out of scope for this proposal, that’s why. >>>>>>> >>>>>>>> On Jul 20, 2016, at 1:26 PM, Brandon Knope <[email protected] >>>>>>>> <mailto:[email protected]>> 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 <[email protected] >>>>>>>> <mailto:[email protected]>> 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 <[email protected] >>>>>>>>> <mailto:[email protected]>> wrote: >>>>>>>>> >>>>>>>>> >>>>>>>>> On Jul 20, 2016, at 3:08 PM, Xiaodi Wu via swift-evolution >>>>>>>>> <[email protected] <mailto:[email protected]>> 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 >>>>>>>>>> <[email protected] <mailto:[email protected]>> 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 >>>>>>>>>> <https://github.com/apple/swift-evolution/pull/440>, or as a gist >>>>>>>>>> <https://gist.github.com/CodaFi/42e5e5e94d857547abc381d9a9d0afd6>. >>>>>>>>>> >>>>>>>>>> Thanks, >>>>>>>>>> >>>>>>>>>> ~Robert Widmann >>>>>>>>>> >>>>>>>>>> Qualified Imports Revisited >>>>>>>>>> >>>>>>>>>> Proposal: SE-NNNN >>>>>>>>>> <https://gist.github.com/CodaFi/NNNN-first-class-qualified-imports.md> >>>>>>>>>> Authors: Robert Widmann <https://github.com/codafi>, TJ Usiyan >>>>>>>>>> <https://github.com/griotspeak> >>>>>>>>>> Status: Awaiting review >>>>>>>>>> Review manager: TBD >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> <https://gist.github.com/CodaFi/42e5e5e94d857547abc381d9a9d0afd6#introduction>Introduction >>>>>>>>>> >>>>>>>>>> We propose a complete overhaul of the qualified imports syntax and >>>>>>>>>> semantics. >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> <https://gist.github.com/CodaFi/42e5e5e94d857547abc381d9a9d0afd6#motivation>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. >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> <https://gist.github.com/CodaFi/42e5e5e94d857547abc381d9a9d0afd6#proposed-solution>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. >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> <https://gist.github.com/CodaFi/42e5e5e94d857547abc381d9a9d0afd6#detailed-design>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. >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> <https://gist.github.com/CodaFi/42e5e5e94d857547abc381d9a9d0afd6#impact-on-existing-code>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. >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> <https://gist.github.com/CodaFi/42e5e5e94d857547abc381d9a9d0afd6#alternatives-considered>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 >>>>>>>>>> [email protected] <mailto:[email protected]> >>>>>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution >>>>>>>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> _______________________________________________ >>>>>>>>>> swift-evolution mailing list >>>>>>>>>> [email protected] <mailto:[email protected]> >>>>>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution >>>>>>>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution> >>>>>>> >>>>> >>>>> _______________________________________________ >>>>> swift-evolution mailing list >>>>> [email protected] <mailto:[email protected]> >>>>> https://lists.swift.org/mailman/listinfo/swift-evolution >>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution> >> _______________________________________________ >> swift-evolution mailing list >> [email protected] <mailto:[email protected]> >> https://lists.swift.org/mailman/listinfo/swift-evolution >> <https://lists.swift.org/mailman/listinfo/swift-evolution>
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
