On Thu, Jul 21, 2016 at 11:14 AM, Robert Widmann <[email protected]> wrote:
> > > ~Robert Widmann > > 2016/07/21 8:23、Xiaodi Wu <[email protected]> のメッセージ: > > On Thu, Jul 21, 2016 at 2:02 AM, Robert Widmann <[email protected]> > wrote: > >> >> On Jul 20, 2016, at 11:56 PM, Xiaodi Wu <[email protected]> wrote: >> >> On Thu, Jul 21, 2016 at 1:40 AM, Robert Widmann <[email protected]> >> wrote: >> >>> >>> On Jul 20, 2016, at 10:04 PM, Xiaodi Wu <[email protected]> wrote: >>> >>> On Wed, Jul 20, 2016 at 10:33 PM, Robert Widmann < >>> [email protected]> wrote: >>> >>>> >>>> >>>> ~Robert Widmann >>>> >>>> 2016/07/20 19:01、Xiaodi Wu via swift-evolution < >>>> [email protected]> のメッセージ: >>>> >>>> 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. >>>> >>>> >>>> Perhaps they need to reread the proposal. Syntactically complex how? >>>> We're introducing two keywords and using tuple syntax. Our grammar changes >>>> are laid bare and take up 7 lines. I think there might be a general air of >>>> confusing semantics changes with syntax changes. >>>> >>> >>> >>> I can't speak for the general air, but putting on my disinterested >>> reader hat, I can see why the confusion might arise-- >>> >>> The Motivation section begins: >>> "The existing syntax for qualified imports..." >>> >>> And the Proposed Solution begins: >>> "The grammar and semantics of qualified imports..." >>> >>> But the Detailed Design begins: >>> "Qualified import syntax will be revised..." >>> >>> It's neither here nor there in terms of the proposal content, but >>> suffice it to say that if one strings together the topic sentences in your >>> proposal, the overarching narrative to be gleaned here is: "The current >>> syntax for qualified imports is no good; therefore, we revise the semantics >>> of qualified imports by changing the syntax." Sure. >>> >>> >>> 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: >>>> >>>> >>>> We allow chaining specifically to avoid that nesting behavior. Let's >>>> break up that chained import line by line to see why >>>> >>>> import Swift using (String, Int, Double, Character) >>>> hiding (String.UTF8View) >>>> >>>> import Swift // Scope contains {all identifiers in Swift} >>>> using (String, Int, Double, Character) // Scope contains {String.*, >>>> Int.*, Double.*, Character.*} >>>> hiding (String.UTF8View) // Scope contains >>>> {{String.* - String.UTF8View.*}, Int.*, Double.*, Character.*} >>>> >>> >>>> We express the exact same example in a much more human-readable way. >>>> You can read this out loud in plain English if you don't believe me: >>>> "import everything in Swift that is in String, Int, Double, and Character >>>> except String.UTF8View" >>>> >>>> >>> >>> I have to disagree with your reasoning here. Unless I'm mistaken, the >>> readability we're most concerned with is that of the written text, not its >>> spoken form. >>> >>> Nesting is an almost exclusively _visual_ way of organizing text and it >>> adds real clarity on the page. Of course, if your litmus test for >>> readability is literally trying to read it out loud, you would conclude >>> that nesting is inferior. However, you'd make that same conclusion about so >>> many other choices in Swift syntax (take, for instance, `:` instead of >>> `extends` or `->` instead of `returns`). I conclude, on the other hand, >>> that Swift is clearly not aiming to be AppleScript-like in this respect. >>> >>> >>> I disagree. Standard Library Swift reads left to right in a very >>> carefully chosen and consistent manner - it has been refined on this list >>> and by the team quite a lot to get it that way. You seem to think I’m >>> arguing verbosity is the end goal (AppleScript?): I’m not. Clarity is the >>> goal. It is unambiguous what you mean when you say >>> >>> import Swift using (String, Int, Double) hiding (String.UTF8View) >>> >> >> Is it ambiguous to say `import Swift using (String hiding (UTF8View), >> Int, Double)`? >> >> >> What happens when it is time to extend this proposal to members? >> > > > Short answer: don't. > > Long answer: I've been studying documentation for the Agda model on which > you're basing this proposal. I like it a lot, and it doesn't have any of > these issues we're discussing. > > First: there's the distinction in Agda between `import` and `open`. It's > `open` that allows you to hide and "re-"name, and these operations only > concern the short, unqualified names that are exposed, never changing > what's imported. Thus, none of this is mutating the API. By contrast, I > see Agda offers `as` for importing something as something else, just like > what's has been suggested in this thread and the last. All of this--the > distinction between import and open, the distinction between `import ... > as` and what's essentially typealiasing--reflects very closely the > semantics found in other languages which I was trying to describe to you > (poorly) yesterday. > > I don't see any facility in Agda where qualified names for definitions can > be vaporized post-hoc by `hiding`. [Yes, I know that technically you're not > making anything disappear, etc.; but the point is that when I'm hiding > frobnicate() from Foo the original Foo.frobnicate() is no longer in the way > of whatever I want to do.] Can you give an example where this is permitted > in any other language? Why would you want to be able to do this to > individual members? As discussed in the previous thread, it seems a recipe > for some really nasty stuff. > > > That was renaming. That is out of scope for this proposal. > And correctly so, IMO. What I'm saying is, let's make renaming of members out of scope for *Swift*. > > Second: Agda explicitly prohibits chaining `using` and `hiding`. In fact, > one piece of documentation said that the reason for this prohibition was > "obvious." > > > Agda doesn't permit using and hiding to be chained because they have a > proper module system that encourages hiding by nesting modules to any depth > and qualified importing or hiding their contents. We have no such > facility, and I don't anticipate its inclusion in Swift, so I recovered > that same power here. > If recovering that same power does not absolutely necessitate a source-breaking change, then this could be postponed until we have a full discussion on modules and any alternatives. Put another way, I can see why you might *want* chaining as a way of recovering more power, but the source-breaking changes that need to be made by next week surely do not require chaining. > > If we're to go down the road of taking inspiration from Agda, I think your > proposal is missing some of the key things that make it work well. In that > language, a sharp distinction is drawn between import and open, and we > could do well to observe the same. I've always thought it problematic that > `import Foundation` in Swift does both so that we're stuck with unqualified > names for everything in Foundation. It would probably be too late to make > that distinction past Swift 3. > > > That is a function of a module system and relevant to the second > proposal. As qualified imports today make no distinction between open and > imported modules, we felt it wasn't necessary to include it here. We want > this. We want it badly. But this isn't the right place to ask for it. > Fine. But let's roll chaining and hiding into the same future discussion. It's inextricably linked to a more complex vision and seems out of place in this proposal. Moreover, I'd seriously reconsider for the future whether facilities to > hide members are appropriate for import statements, and whether trying to > accommodate such facilities now is worthwhile. And I'd consider why it is > that Agda prohibits freeform chaining of using, hiding and renaming, and > whether Swift needs it for anything. It is not ideal to have to explain > what `hiding (String) using (String)` does; it shouldn't be possible to > write such a thing. > > > Then, as I've said before, we'll use diagnostics to make this case > better. This is a case that is explicitly spelled out in the proposal. If > it would remove this case, you could argue that directives may not refer to > unqualified identifiers from earlier directives. That seems unnecessarily > artificial just to remove something that has completely valid semantics. > > > > This syntax fits well with the overall direction of the language itself. >>> For example, I use whitespace here out of habit but here’s nothing stopping >>> you from making these look like the (meta)function invocations they really >>> are >>> >>> import Swift >>> using(String, Int, Double) >>> hiding(String.UTF8View) >>> >>> >>> In the comments you've used the nested notation `{{String.* - >>> String.UTF8View.*}, Int.*, Double.*, Character.*}` to explain what it is >>> your proposed syntax means. I really do find that, with all the punctuation >>> in it, clearer than the chained notation. Of course, written `(String >>> hiding UTF8View), Int, Double, Character`, it would be clearer still. >>> >>> Critically, it eliminates the possibility of absurd chains of `hiding () >>> using () hiding () using ()`, which create many more ways to represent the >>> same subset of imports than can a nested syntax. >>> >>> >>> >>> If you wish to express this, why should the language stop you? >>> >> >> Given two options for syntax, one where expressing this chain is never >> necessary or even possible, and another where it is possible and perhaps >> even necessary, the former wins in terms of clarity, no? >> >> >> Yours does not exclude this possibility, it merely shuffles it around >> (unless you plan on banning the empty tuple. In which case, why?) >> > > The first part answers the second :) > I wouldn't use tuples at all. Moreover, since you seem to be requiring > parentheses around single elements, you're not even really using tuples > here, but rather argument lists. As Brandon mentioned above, I don't see > the need to try to use either tuples or argument lists: > > ``` > import Swift using String, Int, Double > import Swift using (String hiding UTF8View), Int, Double > ``` > > >> import Swift using (String using(UTF8View hiding ()), Int hiding (), >> Double hiding()) >> >> At this point we’re just circling around an edge case described in the >> proposal as ripe for a merge-by-diagnostic. >> > > The point I'm making is that chaining is inelegant in general, the edge > case being only an extreme example of where it goes off the rails. In other > words, the edge case is an argument ad absurdum for a larger issue. Of > course, the edge case itself can be flagged by a diagnostic. There > shouldn't have to be a need for it. > > Or better yet: we can offer diagnostics about this case just as we can >>> offer diagnostics for doubled imports or improperly nested imports. A big >>> part of why this proposal exists is because the existing diagnostics around >>> qualified imports are uninformative and unhelpful. >>> >>> Now reread the chaining example in the proposal. >>>> >>>> >>>> ``` >>>> 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. >>>> >>>> >>>> Python may not be the right mindset for this. Their import story is >>>> much simpler because of their module system and generally simpler >>>> programming model. >>>> >>>> >>>> >>>> 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? >>>> >>>> >>>> I chose Agda because it's the only major language I could find that >>>> treated identifiers like notation and used its module system for *real* >>>> organization of code; it's just a name, it can change if you want it >>>> to. The entire language is flexible. You can redefine functions with just >>>> an =, you can give new syntactic transformations without having to write >>>> crazy macros or worrying about hygiene. You get so much support from the >>>> type system too that all of these features just work together and you can >>>> sit back and feel satisfied that your tools pushed you to write *good >>>> code. *I wrote it with Agda in mind because they took the time to >>>> think about the interactions between modules, code, and scope in a way we >>>> just haven't had the time to yet. >>>> >>>> Many of these imports have simpler syntax but don't chain so lose >>>> expressiveness (Java). Or may have simpler surface syntax but don't >>>> properly interact with a moduleless system (Python, Java). Or may have a >>>> simpler syntax and give way to ambiguities (Python) when used in Swift. >>>> Agda is unambiguous, scalable, extensible, and simple. >>>> >>>> Please don't confuse what's new with what's complex. But at the same >>>> time if there are any unexplainable loopholes we should know about them. I >>>> just haven't heard much I couldn't point to the proposal about yet so I >>>> don't see a reason to change. >>>> >>>> >>> >>> Thanks for this insight. It's clear that you're aiming at a far richer >>> system in the future. However, it's hard to gauge how far Swift will >>> eventually scale/extend what you're proposing here. I don't think there's >>> any denying that the solution you've chosen introduces more involved >>> semantics and a more verbose syntax than what's strictly necessary to >>> address the specific motivating problem you give in this particular >>> instance. Without a better sense of the outer bounds of how far this system >>> will eventually be pushed, it's hard to judge whether the eventual payoff >>> will be "worth it." And without any mention of the grander plan, I suspect >>> the feedback you're going to get will continue along the path of trying to >>> tear away whatever you're trying to put in place for the future which is >>> not discernibly necessary for solving the immediate problem at hand. >>> >>> >>> If you believe this proposal is not extensible then cite a particular >>> example, otherwise I can only say that I can’t tell the future. The syntax >>> presented here is inspired by a tiny, tiny fragment of a language with an >>> incredibly rich import mechanism and module system. It’s unclear how much >>> of that system fits with Swift current - we already tried to formalize >>> quite a bit in the first draft. For right now, *this* proposal is >>> trying to clean up a long-neglected part of the language. If you feel that >>> we’ve failed in that regard then tell me. Otherwise I’m fine with my >>> syntax being pulled in a different direction in future additive proposals. >>> I just want to fix this part of the language before the window on >>> source-breaking changes closes for a while. >>> >>> >>> >>>> >>>> >>>>> >>>>> >>>>> 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 >>>>>>>>>>>> <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.DateComponentsimport 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: "...") // Validvar 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.UTF8Viewimport 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] >>>>>>>>>>>> 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
