<div dir="ltr"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><span class="im" style="font-size:13px">> Modules names are tied to a directory structure that describes their location relative to the current module and it will now be an error to violate this rule. For example:<br></span><span class="im" style="font-size:13px">><br></span><span class="im" style="font-size:13px">> module String // lives in ./String.swift<br></span><span class="im" style="font-size:13px">><br></span><span class="im" style="font-size:13px">> module String.Core // lives in ./String/Core.swift<br></span><span class="im" style="font-size:13px">><br></span><span class="im" style="font-size:13px">> module String.Core.Internals.Do.You.Even.Write // lives in ./String/Core/Internals/Do/You/Even/Write.swift</span><span class="im" style="font-size:13px"><br></span><span style="font-size:13px">I think this is a mistake for several reasons:</span><br style="font-size:13px"><span style="font-size:13px">* You may need to split a single submodule across multiple files, but this rule doesn't allow that.</span></blockquote><div>You can, internally, have several modules and then create one that imports those smaller ones publicly with the name that you desire. </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><br style="font-size:13px"><span style="font-size:13px">* The module declaration and filename contain redundant information, and one of them could get out of sync with the other.</span></blockquote><div><br></div><div>I agree with this point though I am not sure that it is so much of an issue. Diagnostics can handle much of the issue. </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><br style="font-size:13px"><span style="font-size:13px">* Xcode doesn't like to organize things into folders on disk and will fight you tooth and nail.</span> </blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><br style="font-size:13px"><span style="font-size:13px">* Deeply nested folders are a usability issue. Never forget the jury in Oracle v. Google: </span><a href="https://www.geek.com/wp-content/uploads/2016/05/courtroomhijinks.png" rel="noreferrer" target="_blank" style="font-size:13px">https://www.geek.com/wp-content/uploads/2016/05/courtroomhijinks.png</a></blockquote><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Jul 18, 2016 at 7:34 PM, Brent Royal-Gordon via swift-evolution <span dir="ltr"><<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">> On Jul 18, 2016, at 2:09 PM, Robert Widmann via swift-evolution <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>> wrote:<br>
><br>
</span><span class="">> Hello all,<br>
><br>
> TJ Usiyan, Harlan Haskins, and I have been working on a proposal to rework qualified imports and introduce an explicit module system to Swift that we’d like to publish for your viewing pleasure.<br>
<br>
</span>This is really interesting. A few incomplete comments:<br>
<span class=""><br>
> 2) hiding: The hiding directive is followed by a list of identifiers within the imported module that should be hidden from this file.<br>
><br>
> // Imports all of Foundation.Date except `Date.compare()`<br>
> import Foundation.Date hiding (Date.compare())<br>
</span>[snip]<br>
<span class="">> // Exports the entire public contents of Math.Integers, but nothing in<br>
> // Math.Integers.Arithmetic.<br>
> public import Math.Integers<br>
<br>
</span>Would this work?<br>
<br>
module UIKit<br>
<br>
public import UIKit.UIGestureRecognizerSubclass.UIGestureRecognizer<br>
hiding (UIGestureRecognizer.touchesBegan(_:with:), UIGestureRecognizer.touchesMoved(_:with:), …)<br>
<br>
(If so, we'd need a way to hide only the setter of a property, not the getter.)<br>
<span class=""><br>
> Modules names are tied to a directory structure that describes their location relative to the current module and it will now be an error to violate this rule. For example:<br>
><br>
> module String // lives in ./String.swift<br>
><br>
> module String.Core // lives in ./String/Core.swift<br>
><br>
> module String.Core.Internals.Do.You.Even.Write // lives in ./String/Core/Internals/Do/You/Even/Write.swift<br>
<br>
</span>I think this is a mistake for several reasons:<br>
<br>
* You may need to split a single submodule across multiple files, but this rule doesn't allow that.<br>
<br>
* The module declaration and filename contain redundant information, and one of them could get out of sync with the other.<br>
<br>
* Xcode doesn't like to organize things into folders on disk and will fight you tooth and nail.<br>
<br>
* Deeply nested folders are a usability issue. Never forget the jury in Oracle v. Google: <a href="https://www.geek.com/wp-content/uploads/2016/05/courtroomhijinks.png" rel="noreferrer" target="_blank">https://www.geek.com/wp-content/uploads/2016/05/courtroomhijinks.png</a><br>
<br>
At the very least, I would like to see allowances for multi-file submodules—String/Core/Internals/Do/You/Even/Write**.swift. Better would be to use long filenames—String.Core.Internals.Do.You.Even.Write*.swift. Even better would be to just allow freeform naming and trust programmers to organize their projects sanely.<br>
<span class=""><br>
> Existing projects that do not adopt these rules will still retain their implicit module name (usually defined as the name of the framework or application that is being built) and may continue to use whatever directory structure they wish, however they may not declare any explicit modules.<br>
><br>
> This proposal also solves the problem of module export. A module that is imported without an access level modifier will default to an internal import per usual. However, when it is useful to fully expose the public content of submodules to a client, a public modifier can be used. Similarly, when it is useful to access internal or [file]private APIs, but not expose them to clients, those access modifiers may be used. The rule of thumb is: Only identifiers that are at least as visible as the qualifier on the import make for valid import declarations.<br>
<br>
</span>It appears the semantics here are "grab all declarations at level X and above, and expose them in this module as level X". This is bizarre for a number of reasons:<br>
<br>
* Currently, `import` can only access `internal` declarations using `@testable`. This would change that.<br>
<br>
* Currently, `import` can't access `private` and `fileprivate` declarations at all, and it's not clear what it would mean to add that. What happens if two different parts of the module have different `private` members with the same name? Which do you get?<br>
<br>
* Currently, `import` only affects the current file—it's effectively "import `public` members as `fileprivate`". If your default is `internal import`, that would imply that an import statement in one file would, by default, expose the APIs it imported to all files. That's an important change in behavior.<br>
<br>
I think you're mixing two things together that ought not to be. `import` should always import only public APIs (unless you use `@testable`—which might need a bit of renaming to support the additional use case of SPIs between submodules and supermodules—in which case you also get `internal` APIs). An access modifier on the `import` statement controls how they're exposed to the rest of the file/project/world, and `private` is the default. It's a little weird to have `private` be the default on `import` when `internal` is the default on everything else, but the alternative is to change `import`'s behavior in a way that is neither backwards-compatible, nor likely to be correct.<br>
<span class=""><br>
> Because import directives are file-local, they will never be exported along with a public import and will default to exporting the entire contents of the module as though you had never declared them.<br>
<br>
</span>Whoa, wait, what? Why? I think hiding parts of the implementation is a good use case for re-exporting a module. And I think the clear implication of attaching these clauses directly to the import statement is that it controls how the module is imported everywhere that statement makes it visible, not just within the one file. If we're not going to do that, I think these clauses ought to be separated from the `import` statement and turned into something separate.<br>
<span class="HOEnZb"><font color="#888888"><br>
--<br>
Brent Royal-Gordon<br>
Architechies<br>
</font></span><div class="HOEnZb"><div class="h5"><br>
_______________________________________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
</div></div></blockquote></div><br></div>