<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div><br><br>~Robert Widmann</div><div><br>2016/07/21 3:19、Pyry Jahkola via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>&gt; のメッセージ:<br><br></div><blockquote type="cite"><div><meta http-equiv="Content-Type" content="text/html charset=utf-8"><div class="">I think we're getting somewhere.</div><br class=""><div><blockquote type="cite" class=""><div class="">On 21 Jul 2016, at 12:01, Robert Widmann &lt;<a href="mailto:rwidmann@apple.com" class="">rwidmann@apple.com</a>&gt; wrote:</div><div class=""><div dir="auto" class=""><div class=""><blockquote type="cite" class=""><div class=""><div class=""></div></div></blockquote></div></div></div></blockquote><div class=""><div dir="auto" class=""><div class=""><blockquote type="cite" class=""><div class=""><div class=""><br class=""></div></div></blockquote></div></div></div><blockquote type="cite" class=""><blockquote type="cite" class=""><blockquote type="cite" class="">(<a href="https://github.com/CodaFi/swift-evolution/blob/ab091043daa62158bd3337a2a2a467be3e16ff18/proposals/XXXX-qualified-imports.md#detailed-design" class="">An excerpt about the hiding directive</a>)</blockquote></blockquote></blockquote><blockquote type="cite" class=""><blockquote type="cite" class=""><br class=""></blockquote></blockquote><blockquote type="cite" class=""><div dir="auto" class=""><div class=""><blockquote type="cite" class=""><div class=""><div class=""><div class="">4. Hmm, the above design detail is easily missed when reading the proposal. So what you're proposing is that the <i class="">hiding</i> of <font face="Menlo" class="">Date</font> essentially turns&nbsp;<span style="font-family: Menlo;" class="">Date</span>&nbsp;into a type that the code will know almost nothing about, except it's something we can pass to other types' methods that expect a&nbsp;<span style="font-family: Menlo;" class="">Date</span>, am I right?</div><div class=""><br class=""></div><div class="">What's the benefit in that? Do you anticipate it will make importing lighter somehow, possibly improving compilation or library loading speed? You mentioned something along those lines in the Motivation, but I'm not sure if I got it right here.</div></div></div></blockquote><div class=""><br class=""></div><div class="">It is so that use of an API in a framework like Foundation does not necessitate polluting your Swift files with a million using imports - thus defeating the purpose of this proposal.</div></div></div></blockquote><div><br class=""></div><div>You explained further below what else `hiding` imports can be used for. But my comment was motivated by your example of `<b style="font-family: Menlo;" class="">import</b><span style="font-family: Menlo;" class="">&nbsp;Foundation&nbsp;</span><b style="font-family: Menlo;" class="">hiding</b><span style="font-family: Menlo;" class="">&nbsp;(Date)</span>`.&nbsp;</div><div><br class=""></div><div>I fail to see how the lack of `<b class=""><font face="Menlo" class="">hiding</font></b>` imports would imply Swift files with a lot using imports. In my counting, they amount to at most one extra using import. (And I propose ~10 lines below what would get that to zero.)</div><div><br class=""></div><div>The simple reason I could see someone write `<font face="Menlo" class=""><b class="">import</b> Foundation <b class="">hiding</b> (Date)</font>` is because another imported module "<font face="Menlo" class="">Julian</font>" she uses happens to export another <font face="Menlo" class="">Date</font> type which she wants to use instead. And if we could just as well solve that use case by making it so that</div><div><br class=""></div><div><font face="Menlo" class="">&nbsp; &nbsp; <b class="">import</b> Foundation</font></div><div><font face="Menlo" class="">&nbsp; &nbsp; <b class="">import</b> Julian, Julian <b class="">using</b>&nbsp;(Date)</font></div><div><font face="Menlo" class="">&nbsp; &nbsp; assert(Date.self == Julian.Date.self)</font></div><div><br class=""></div><div>brings in both modules but makes Julian.Date the one that Date is shorthand of.</div><div><br class=""></div><div>Besides, Joe and friends offered the use of `<font face="Menlo" class="">*</font>` to mean "and everything else", which is problematic because `<font face="Menlo" class="">*</font>` also happens to be an operator function name. But we could make it so that the underscore imports everything else (without explicit qualification), making the above example exactly equivalent to:</div><div><br class=""></div><div><div><font face="Menlo" class="">&nbsp; &nbsp;&nbsp;<b class="">import</b>&nbsp;Foundation <b class="">using</b> (_) &nbsp; <font color="#919191" class="">// same as `import Foundation`</font></font></div><div><font face="Menlo" class="">&nbsp; &nbsp;&nbsp;<b class="">import</b>&nbsp;Julian&nbsp;<b class="">using</b>&nbsp;(_, Date) <font color="#919191" class="">// bring in Date explicitly and all else implicitly</font></font></div><div class=""><div><font face="Menlo" class="">&nbsp; &nbsp; assert(Date.self == Julian.Date.self)</font></div></div></div></div></div></blockquote><div><br></div><div>Funny, others have been suggesting _ be used as a special namespace to hide identifiers in. &nbsp;It implies you don't care about identifiers, not that you want all of them.</div><br><blockquote type="cite"><div><div><div><div class=""><br class=""></div><div class=""><br class=""></div></div><blockquote type="cite" class=""><div class=""><div dir="auto" class=""><div class=""><div class="">DateFormatter alone needs to know about Date, String, TimeInterval, Calendar, Locale, and TimeZone. &nbsp;Each of those needs to know about additional components. &nbsp;To require an import decl to use these types explicitly would be madness. &nbsp;You'd just wind up importing Foundation anyway.</div></div></div></div></blockquote><div><br class=""></div><div>"<i class="">You'd just wind up importing Foundation anyway</i>" is an argument that doesn't seem imply from the given Motivation section AFAICT.</div></div></div></blockquote><div><br></div><div>I should be more clear: If we requires you to qualified import types without these allowances then you would have to recursively import types out of Foundation until you wind up importing the whole thing anyway. &nbsp;To be able to use <i>DateFormatter </i>you shouldn't have to tell Swift you also want to use Date, String, TimeInterval, etc. &nbsp;We know you want to, we can see all of these identifiers. &nbsp;When the time comes for you to pick a member on Date, then you want a using or hiding import to let us know you want to see it.</div><br><blockquote type="cite"><div><div><div><br class=""></div><div>I can see three kinds of problems here (objective or subjective), caused by importing the whole Foundation:</div><div><ol class=""><li class=""><b class="">Identifier name conflicts</b>, which we could solve with just the `import Module using (name, Name, _)` syntax, essentially indicating which Module should be preferred.<br class=""></li></ol></div></div></div></blockquote><div>The grammar makes no allowances for types to be imported there, only qualified module name. &nbsp;Not sure what you mean.</div><blockquote type="cite"><div><div><div><ol class="" start="1"><li class=""><br class=""></li><li class=""><b class="">Identifier names shadowing module names</b>, where e.g. a `<font face="Menlo" class=""><b class="">private enum</b> Foundation {}</font>` disables the fully qualified access to the Foundation module's API). This remains an unsolved problem, but the introduction of <i class="">qualified module imports</i> `<font face="Menlo" class=""><b class="">import</b> Foundation <b class="">as</b> Foundation</font>` or `<font face="Menlo" class=""><b class="">import</b> Foundation <b class="">as</b> F</font>` (or, heh, `<font face="Menlo" class=""><b class="">import</b> Foundation <b class="">as is</b></font>`) would be one way of going about it.<br class=""></li></ol></div></div></div></blockquote><div><br></div>And additive and can be introduced in a future proposal as a new directive on top of this system. &nbsp;We wanted this, the community had reservations, we backed off.<br><blockquote type="cite"><div><div><div><ol class="" start="2"><li class=""><br class=""></li><li class=""><b class="">Auto-completer "hygiene"</b>, or <b class="">being explicit</b> which part of a large imported API is <b class="">not</b>&nbsp;considered appropriate to use by the author</li></ol></div></div></div></blockquote><blockquote type="cite"><div><div><div>Point 3 is the only problem that `<font face="Menlo" class=""><b class="">hiding</b></font>` imports could be uniquely used for, especially if they can be narrowed down to members of imported types and extensions (e.g.&nbsp;<font face="Menlo" class="">Swift.String.UTF8View</font>, as given in the proposal). But is that worth having?</div></div></div></blockquote><div><br></div><div>We need to be able to disambiguate more than just top-level names, for one. &nbsp;Hiding can do that.</div><br><blockquote type="cite"><div><div><div><br class=""></div><br class=""><blockquote type="cite" class=""><div class=""><div dir="auto" class=""><div class=""><blockquote type="cite" class=""><div class=""><div class=""><div class="">5. These chaining rules do fit on the back of a napkin, but I'm not sure if we need them at all. I'm not convinced we need `<b class=""><font face="Menlo" class="">hiding</font></b>` imports, and without hiding imports, we need no rules for the order of imports.</div></div></div></blockquote><div class=""><br class=""></div>How else are we to allow you to import a using type but not any of its member types?</div></div></div></blockquote><div><br class=""></div><div>I don't know. I'm asking "why?" not "how?"</div></div></div></blockquote><div><br></div>That is why, just rhetorical.<div><br><blockquote type="cite"><div><div><div><br class=""></div><br class=""><blockquote type="cite" class=""><div class=""><div dir="auto" class=""><div class="">How could we support removing APIs related to NSCell in AppKit apps? How about NSStream everywhere else? How else can we allow, in the future, the ability to import NSObject but none of its KVO-related members?</div></div></div></blockquote><div><br class=""></div><div>I'm saying you should explain this in the Motivation. Or consider moving the `<b class=""><font face="Menlo" class="">hiding</font></b>` import syntax into a further proposal.</div></div></div></blockquote><div><br></div><div>Fair.</div><br><blockquote type="cite"><div><div><div><br class=""></div><br class=""><blockquote type="cite" class=""><div class=""><div dir="auto" class=""><div class="">A hiding import is an invariant: It says a particular API should never be considered for use in this file. &nbsp;The very act of 'using' an identifier means you are hiding all others. &nbsp;The very act of 'hiding' an identifier means you are using all others.</div></div></div></blockquote><div><br class=""></div><div>That is very logical. But it would be better if there was a real-world example use case given where the use of `<b class=""><font face="Menlo" class="">hiding</font></b>` was a clear win over a combination of `<font face="Menlo" class=""><b class="">import</b></font>` and `<font face="Menlo" class=""><b class="">import</b> ... <b class="">using</b> (...)</font>`. The current one about Date isn't very convincing because instead of hiding one, it could be solved by highlighting (using) the other.</div></div></div></blockquote><div><br></div><div>I have given one. &nbsp;Show me how to express the "give me String but not String.UTF8View" example without hiding?</div><br><blockquote type="cite"><div><div><div><br class=""></div><div><br class=""></div><blockquote type="cite" class=""><div dir="auto" class=""><div class=""><blockquote type="cite" class=""><div class=""><div class=""><div class="">What I will keep suggesting is that `<font face="Menlo" class=""><b class="">using</b></font>` imports actually take up the name in the file-local scope such that nothing else in the same file's scope — be it another `<font face="Menlo" class=""><b class="">import</b> ...&nbsp;<b class="">using</b> (...)</font>`, a local type declaration, function, or value — can declare the same name with a different meaning. That way, a plain</div><div class=""><font face="Menlo" class=""><b class=""><br class=""></b></font></div><div class=""><font face="Menlo" class=""><b class="">&nbsp; &nbsp; import</b> Foo</font></div><div class=""><br class=""></div><div class="">can import everything from <font face="Menlo" class="">Foo</font>, while another</div><div class=""><font face="Menlo" class=""><b class=""><br class=""></b></font></div><div class=""><font face="Menlo" class=""><b class="">&nbsp; &nbsp; import</b> Foo <b class="">using</b> (Bar)</font></div><div class=""><br class=""></div><div class="">can be used to explicitly choose the <font face="Menlo" class="">Bar</font> the code is about to use.</div></div></div></blockquote><div class=""><br class=""></div>That was the plan. &nbsp;You will receive an "invalid redeclaration" error as always.&nbsp;</div></div></blockquote><br class=""></div><div>👍!</div><div><br class=""></div><div>— Pyry</div><div><br class=""></div></div></blockquote><blockquote type="cite"><div><span>_______________________________________________</span><br><span>swift-evolution mailing list</span><br><span><a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a></span><br><span><a href="https://lists.swift.org/mailman/listinfo/swift-evolution">https://lists.swift.org/mailman/listinfo/swift-evolution</a></span><br></div></blockquote></div></body></html>