~Robert Widmann

2016/07/20 20:07、Félix Cloutier via swift-evolution <[email protected]> 
のメッセージ:

> My understanding is that we want "using" and "hiding" because we want the 
> ability to either take just a few things OR leave out just a few things. With 
> a unified "import Foo (A = B, C = D, E = _) syntax, we only get the ability 
> to take a few things AND hide a few things.

Again, renaming is not something I want done with the same syntax as 
introducing and removing things from scope because they are distinct 
operations.  This import tells me nothing from a semantic perspective and just 
seems easy to type rather than understand.  Nowhere in the language can you 
find something that resembles this either.

> 
> I've never really been into a case where I badly had to *not* import a name, 
> so while I see why it makes sense from a mathematical perspective to have 
> "hiding", I'm not sure how much I'd miss it if it wasn't there.
> 
> I realize that it solves the ambiguous type problem, but I consider that it's 
> a flawed solution. Instead of specifying from which module you want an 
> import, you have to specify on which modules you don't want it.

You still specify which module you want to import from, so I don't see your 
point here.  Given that Foo and Bar both define a class Baz, here's your import

import Foo using (Baz)
import Bar hiding (Baz)

What's the problem here?  Isn't this exactly what you wanted to say in English 
(or whatever internal monologue you might have) spelled out in code?  It scales 
immediately to multiple ambiguities and we can provide diagnostics to insert or 
remove identifiers in these lists to help the user out when they get stuck with 
an insufficiently inclusive or exclusive import list.  The Python example is 
much more difficult to reason about from my perspective and from the 
perspective of the compiler.  In fact, it's almost the code that's needed today 
to work around this problem - we're trying to fix the need for this here.

> 
> To see if we can get inspiration, I'd like to pitch an imperfect Python-like 
> approach, where you could import a module as a namespace (and then you'd 
> always have to write Module.Class, with modules systematically shadowing 
> classes in the global namespace), or in addition to that, import every 
> top-level name in the module into the file's global namespace. Names defined 
> in multiple modules remain ambiguous unless explicitly shadowed:
> 
>> private typealias OrderedSet = BTree.OrderedSet
>> private var foo: (Int) -> Int = Bar.foo
> 
> You would not be allowed to shadow a module with a class.
> 
> This, however, still does not solve the extension problem. Additionally, 
> given that the default visibility for top-level names is internal, careless 
> users could easily pollute the project's global namespace. Finally, for 
> micro-frameworks that have a class with the same name as a module, you'd 
> always have to write Name.Name, since the class can't shadow the module.
> 
> Félix
> 
>> Le 20 juil. 2016 à 19:01:37, Xiaodi Wu via swift-evolution 
>> <[email protected]> a écrit :
>> 
>> On Wed, Jul 20, 2016 at 8:10 PM, Robert Widmann <[email protected]> wrote:
>>> 
>>>> On Jul 20, 2016, at 5:47 PM, Xiaodi Wu <[email protected]> wrote:
>>>> 
>>>>> On Wed, Jul 20, 2016 at 6:30 PM, Robert Widmann <[email protected]> 
>>>>> wrote:
>>>>> “The Phase Distinction” is a semantic one, not one built into the import 
>>>>> system itself.
>>>> 
>>>> 
>>>> I understand. To rephrase my question: why introduce this semantic 
>>>> distinction to Swift?
>>>> 
>>>> 
>>>>> 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.
>>>> 
>>>> 
>>>> This is, IMO, very complex. I appreciate enormously the conceptual 
>>>> simplicity of the current Swift approach which, for all of its 
>>>> deficiencies, has only one import directive that does what it says on the 
>>>> tin: it exposes identifiers. I'm not bothered if it gains the ability to 
>>>> expose identifiers differently from one file to the next without keywords 
>>>> firewalled from each other to preserve the notion of phases of import.
>>> 
>>> We are not changing the unqualified Swift import system.  Take a gander at 
>>> the proposal again, or even the first draft.  Swift has a particularly 
>>> strange syntax for qualified imports that hasn’t received attention since 
>>> it was first introduced 2 major versions ago.  That thing allows quite a 
>>> variety of senseless variants that can be both completely expressed by and 
>>> subsumed by `using` and `hiding`.
>> 
>> 
>> My sense, which I think has been echoed by others, is that the proposed 
>> solution is syntactically complex, and now that I understand that you're 
>> thinking through a multi-phase concept, also conceptually multilayered. I'm 
>> not arguing that the existing syntax for qualified imports doesn't need 
>> changing, only that there is room for radical simplification of the proposed 
>> solution IMO. As I re-read this proposal once more, it strikes me that the 
>> motivating issues identified (needlessly specific, does not compose, etc.) 
>> don't clearly argue for the specific direction proposed as opposed to 
>> alternatives like Joe's.
>> 
>> 
>>>>> Ne’er the twain shall meet.
>>>> 
>>>> 
>>>> Yes, you explained this concept very clearly as it applies to Agda. But I 
>>>> just don't see why we should care to have this distinction. Yet you are 
>>>> very adamant about it. What am I missing?
>>> 
>>> We should care because that is precisely what the two operations do.  
>>> `using` and `hiding` introduce things or remove things from scope which is 
>>> a very different operation from taking something that is already in scope 
>>> and giving it a new name.
>> 
>> 
>> Perhaps I'm not phrasing my question very cogently. Of course, if we are to 
>> have `using`, `hiding`, and `renaming`, we must observe the distinctions 
>> between them.
>> 
>> 
>>> If you don’t want to think of them as part of the same import process, 
>>> think of them instead in terms of their Swift equivalents today.  
>>> 
>>> import Foundation using (Date) == import struct Foundation.Date
>>> import Foundation hiding (Date) == import Foundation; @unavailable(*, “…") 
>>> typealias Date = Foundation.Date
>>> import Foundation using (TimeInterval) renaming (TimeInterval, to: Time) == 
>>> import typealias Foundation.TimeInterval; typealias Time = 
>>> Foundation.TimeInterval
>>> 
>>> Notice how it takes two declarations to create a renaming? It is not simple 
>>> to drop being explicit about which names are actually in scope and expect a 
>>> renaming to just implicitly slip in a using declaration.  Nor is it simple 
>>> to imagine _ as some magical namespace that you can pack away unwanted 
>>> definitions into.  using and hiding are very physical things and the rules 
>>> for their behavior should be obvious and unambiguous - the proposal 
>>> contains some examples of valid and invalid declarations to help with that.
>> 
>> 
>> The examples worry me, in fact. That we might need to contemplate the 
>> behavior of a statement such as `import Foo using () hiding () hiding () 
>> using () hiding ()` suggests it's perhaps a little over-engineered for the 
>> purpose. Why allow chaining of `using` and `hiding` anyway? The only example 
>> given is of a nested type, which suggests nesting would be the way to go:
>> 
>> ```
>> import Swift using (String hiding (UTF8View), Int, Double)
>> ```
>> 
>> 
>>> 
>>>>> A qualified import is defining a procedure to import a subset of 
>>>>> identifiers.  That’s it.
>>>> 
>>>> 
>>>> Right, and I think an entirely different way of thinking about this would 
>>>> be much easier to learn and teach. Whether using, hiding, and renaming are 
>>>> to be supported now, later, or never, my mental picture of how it fits 
>>>> together is quite simple:
>>>> 
>>>> Analogy--suppose I am a pickle merchant. I import Foo-branded pickles from 
>>>> vendor X. I must re-label them with the right nutritional information 
>>>> before I can sell in this country. I can have labels printed saying that 
>>>> they are Foo-branded pickles. I can have them branded as Bar-branded 
>>>> pickles. Or I can have the labels deliberately misprinted, and then these 
>>>> pickles will never see the light of day. Point is, each of these is an 
>>>> active choice; even if I sell these as Bar-branded pickles, it's not that 
>>>> these pickles reached the domestic market as Foo-branded pickles, after 
>>>> which I scratched out the label with a Sharpie. These pickles had no 
>>>> domestic brand until I gave it one.
>>>> 
>>>> Back to importing modifiers--I import type Foo from module X. In my code, 
>>>> I need to make a choice to call this type Foo, or Bar, or nothing at all. 
>>>> In other words, there is only one directive, importing, and I am importing 
>>>> `Foo as Foo`, `Foo as Bar`, or `Foo as _`. Meanwhile, `import X using Foo` 
>>>> or `import X.Foo` (whatever the color of the bikeshed) would just be a 
>>>> shorthand for `import X using Foo as Foo` or `import X.Foo as Foo`. In 
>>>> this conceptualization, if I choose to import Foo as Bar, it's not that 
>>>> I'm importing Foo into the scope, then changing the identifier to Bar. The 
>>>> only identifier it ever has in this scope is Bar.
>>> 
>>> And I’m the one with the complex semantics? :)
>> 
>> 
>> I'm just trying to put into words what I'm familiar with after working in 
>> other languages such as Python.
>> 
>> 
>>> How about this:
>>> 
>>> Using and Hiding relate to each other the way && and || do for bools.  If 
>>> && can be said to “prefer to return false, but return true given no other 
>>> alternative” and || can be said to “prefer returning true, but return false 
>>> given no other alternative”, then hiding can be said to “prefer importing 
>>> all identifiers unless told not to in specific instances” and using can be 
>>> said to “prefer importing no identifiers unless told to in specific 
>>> instances”.  
>>> 
>>> import Module.Name using (A, B, C, …) === import Module.Name hiding 
>>> (ALL_NAMES - {A, B, C, ...})
>>> import Module.Name hiding (A, B, C, …) === import Module.Name using 
>>> (ALL_NAMES - {A, B, C, ...})
>>> 
>>> That seems a particularly simple explanation to me.  Let me know if 
>>> anything else is unclear.
>> 
>> 
>> Your mental framework is clear. It's one that's just not found in very many 
>> other languages. Many of these have import declarations (or similar) with 
>> simpler syntax, yet they seem to address at least some of the problems that 
>> motivate your proposal. I guess my question in the end is, why have you 
>> chosen Agda as the basis for qualified imports in Swift and not one of these 
>> other languages?
>> 
>> 
>>> 
>>>> 
>>>> 
>>>>>>> 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]> 
>>>>>>> wrote:
>>>>>>> 
>>>>>>>>> On Jul 20, 2016, at 2:52 PM, Robert Widmann via swift-evolution 
>>>>>>>>> <[email protected]> wrote:
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> On Jul 20, 2016, at 2:35 PM, Xiaodi Wu <[email protected]> wrote:
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> On Wed, Jul 20, 2016 at 4:24 PM, Robert Widmann <[email protected]> 
>>>>>>>>> wrote:
>>>>>>>>>> 
>>>>>>>>>>>> On Jul 20, 2016, at 2:19 PM, Xiaodi Wu <[email protected]> wrote:
>>>>>>>>>>>> 
>>>>>>>>>>>> On Wed, Jul 20, 2016 at 4:06 PM, Robert Widmann 
>>>>>>>>>>>> <[email protected]> wrote:
>>>>>>>>>>>> 
>>>>>>>>>>>>>> On Jul 20, 2016, at 2:04 PM, Robert Widmann via swift-evolution 
>>>>>>>>>>>>>> <[email protected]> wrote:
>>>>>>>>>>>>>> 
>>>>>>>>>>>>>> 
>>>>>>>>>>>>>> On Jul 20, 2016, at 1:59 PM, Xiaodi Wu <[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]> 
>>>>>>>>>>>>>>> wrote:
>>>>>>>>>>>>>>> I meant is there any reason for requiring parentheses 
>>>>>>>>>>>>>>> 
>>>>>>>>>>>>>>>> On Jul 20, 2016, at 4:53 PM, Robert Widmann 
>>>>>>>>>>>>>>>> <[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]> 
>>>>>>>>>>>>>>>>> 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]> 
>>>>>>>>>>>>>>>>>> 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]> 
>>>>>>>>>>>>>>>>>>> wrote:
>>>>>>>>>>>>>>>>>>> 
>>>>>>>>>>>>>>>>>>> 
>>>>>>>>>>>>>>>>>>>> On Jul 20, 2016, at 3:08 PM, Xiaodi Wu via swift-evolution 
>>>>>>>>>>>>>>>>>>>> <[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]> 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
>>>>>>>>>>>>>>>>>>>>> [email protected]
>>>>>>>>>>>>>>>>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>>>>>>>>>>>>>>>>>> 
>>>>>>>>>>>>>>>>>>>> _______________________________________________
>>>>>>>>>>>>>>>>>>>> swift-evolution mailing list
>>>>>>>>>>>>>>>>>>>> [email protected]
>>>>>>>>>>>>>>>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>>>>>>>>>>> 
>>>>>>>>>>>>> _______________________________________________
>>>>>>>>>>>>> swift-evolution mailing list
>>>>>>>>>>>>> [email protected]
>>>>>>>>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>>>>>> 
>>>>>>>> _______________________________________________
>>>>>>>> swift-evolution mailing list
>>>>>>>> [email protected]
>>>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> [email protected]
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 
> _______________________________________________
> swift-evolution mailing list
> [email protected]
> https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to