<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Mar 4, 2017, at 2:54 PM, Matthew Johnson <<a href="mailto:matthew@anandabits.com" class="">matthew@anandabits.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><blockquote type="cite" class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;"><div class=""><br class="Apple-interchange-newline">On Mar 4, 2017, at 9:56 AM, Karim Nassar <<a href="mailto:karim@karimnassar.com" class="">karim@karimnassar.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Mar 3, 2017, at 5:21 PM, Matthew Johnson <<a href="mailto:matthew@anandabits.com" class="">matthew@anandabits.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><blockquote type="cite" class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class="Apple-interchange-newline">On Mar 3, 2017, at 9:24 AM, Karim Nassar via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:<br class=""><br class="">Changes that *are* necessary are:<br class=""><br class="">* Change the spelling of `internal` to `module` (making `module` the new default)<br class="">* Introduce a new modifier `internal` to mean "Internal to the current sub-module and its child-sub-modules”<br class=""></blockquote><br class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><span class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;">Can you give concrete examples of use cases where a descendent submodule needs access to symbols declared by an ancestor? I gave some thought to this when drafting my proposal and came to the conclusion that this runs against the grain of layering and is likely to be a bad idea in practice. If there are use cases I didn’t consider I am very interested in learning about them.</span><br class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"></div></blockquote><div class=""><br class=""></div><div class="">On further reflection and examination of my notes, I think you’re right, and that the `internal` encapsulation should be purely horizontal. Will adjust to reflect that.</div><br class=""><blockquote type="cite" class=""><div class=""><blockquote type="cite" class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;">### Making a Sub-module<br class=""><br class="">To create a sub-module within a Module (or sub-module) is simple: The author creates a directory, and places a "sub-module declaration file" within the directory:<br class=""><br class="">```<br class="">// __submodule.swift<br class=""></blockquote><br class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><span class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;">Why the double underscore prefix? To make it sort to the top in a file browser?</span><br class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><span class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;">Is this file allowed to have any Swift code? Or is it limited to submodule-related declarations only? If the latter, why not use an extension such as `.submodule` or `.swiftmodule` to differentiate it from ordinary Swift files and allow the submodule to be named by the name of this file?</span><br class=""></div></blockquote><div class=""><br class=""></div><div class="">So, my reasoning was that by requiring a specific standard name for the declaration file, we guarantee that any directory can only describe one submodule. Prefixing the proposed name with underscores was simply a way of preventing naming collision with potential “real code” files (and yes, as a side-effect alpha-floating it to the top). Since the `submodule` declaration might expand to include statements & configuration about the sub-module, I see no reason to prohibit Swift code from existing in that sub-module declaration file… Disallowing/controlling that seems to be a style/linter concern.</div><div class=""><br class=""></div><div class="">However, as I mentioned above, all the specific spellings (except `internal`) for the different concepts in this proposal are straw-men awaiting input. I’d say the addition of a new type of file extension raises some concerns for me, but there’s already been a lot of push back on the general idea of using filesystem structures to organize sub-modules, so the whole idea may be moot. </div></div></div></div></blockquote><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">I’ve actually been starting to come around to the idea of using the file system. Not so much because I really like it, but because I have been considering further some of the drawbacks of other approaches. </div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">One big reason is that a submodule should form a scope and scopes should consist of code that is physically adjacent. In practice this means it should reside in close proximity in the file system. Allowing any file in a project to be a part of any submodule partly defeats the purpose of using them to structure a project internally. If we’re going to be organizing the files in a submodule physically anyway maybe we should just take advantage of that fact and prevent a stray file in a distant part of the file system from being part of the submodule.</div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">The second reason is that there is a big problem with placing a simple `submodule Foo` declaration at the top of each file in a submodule. We all make typos from time to time. This method makes it too easy to accidentally type `submodule Fooo` and end up in a submodule you didn’t intend. This mistake would likely be caught relatively quickly but it seems silly to have a system subject to this kind of mistake. This means we would end arbitrarily placing the declaration in one file and saying `extends submodule Foo` in the rest of the files. Your design avoids the need to arbitrarily choose where to place the declaration and avoids the need for a declaration in the rest of the files.</div></div></blockquote><div><br class=""></div>I’m not dead-set on this approach, but as you say, it solves a *lot* of problems that other approaches introduce. I do recognize the reasonableness of the main argument against, that file location shouldn’t have such a dramatic affect on behavior… *but* the fact is (whether by convention or expediency) we already *do* have filesystem location dependencies on our code projects… </div><div><br class=""></div><div>* One can’t willy-nilly move files around the disk and expect a project to build… if you move it somewhere the compiler doesn’t know to look for it, you’re going to break things</div><div>* One can’t just move a file out of your SCM repo root, or you’ll “lose” the file</div><div><div><br class=""></div><div>One might argue that these are pathological cases, but the fact remains that this approach only introduces a new constraint on project structure, not a new *kind* of constraint, and it is one that is purely optional. You don’t *have* to use sub-modules in a project, and if you don’t, there’s no additive burden on you.</div><div><br class=""></div><blockquote type="cite" class=""><div class=""><blockquote type="cite" class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;"><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><div class=""><br class=""></div><div class="">Shortly, I’m going to update the original proposal gist reflecting all the comments I’ve received and part of that will be expanding the proposal section to include multiple alternate strategies for discussion, along with pros/cons for each. I’ll include a discussion on naming options for this file in this section.</div></div></div></div></blockquote><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">I’m going to look at your new draft this afternoon while I’m working on updating my proposal. I think you’ll find it much more to your liking than the original draft. Perhaps we will be able to converge if we keep the discussion going.</div></div></blockquote><div><br class=""></div><div>I’d be happy to cooperate-with/converge-with/withdraw-in-favor-of. I’m mostly interested in a solid, light-weight solution to my use-cases, however that looks. I look forward to seeing your updates!</div><br class=""><blockquote type="cite" class=""><div class=""><blockquote type="cite" class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;"><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><br class=""><blockquote type="cite" class=""><span class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;">If we’re going to use the file system to organize submodules this seems like a reasonable approach. It allows larger submodules to have folder hierarchies within them and also creates a central location for submodule-related declarations.</span><br class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><span class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;">A primary flaw I see in this approach is that Xcode is the dominant IDE for Swift and the way Xcode handles files is not conducive to file-system organization. I really detest the way Xcode handles this and would vastly prefer that it simply reflected the physical file system hierarchy but I don’t think that will change any time soon. On the other hand maybe a file system based submodule system in Swift would motivate the Xcode team to better reflect the physical file system organization.</span></blockquote></div><div class=""><br class=""></div><div class="">My thoughts (hopes?) on this were that should Swift adopt such a mechanism for sub-modules, then part of Xcode’s integration of the feature would be to make it aware of sub-modules in a first-class way, so that the author wouldn’t have to manually manage the project files to take advantage of the feature. </div><div class=""><br class=""></div><div class="">I’d envisioned either a new “Makes Sub-Module” property on Groups or a new “Sub-Module" mechanism alongside Groups & Folders in the project list. This may be wishful thinking on my part.</div></div></div></blockquote><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">The problem with a "Makes Sub-Module” on a group in Xcode is that groups do not mirror the file system. Maybe a file system based submodule feature would motivate the Xcode team to support group structures that do mirror the file system better. I hope that would be the case! Unfortunately I don’t think we’d have a guarantee when reviewing the feature and there are significant practical implications for using the feature in Xcode without that kind of support. We would probably just have to trust Apple to get this right.</div></div></blockquote></div><div class=""><br class=""></div><div class="">Too true. I don’t know how much the Swift team can influence or contribute to Xcode. On the other hand, using Xcode’s “Folder References” feature isn’t so onerous that it would prevent me from getting very large benefit from sub-modules in my projects.</div><div class=""><br class=""></div><div class="">—</div><div class=""><br class=""></div><div class="">As one concrete example, I have a large app that imports a Module (Framework) which represents a kind of domain-specific DOM graph. There is a Query type which must live within that module (both for WMO, and for more esoteric dependency reasons). This Query type has 11 related or sub- types including specialized graph nodes and a parser. Out of these 12 types, the API genuinely exposes 2 types (Query and QueryError) and a grand total of 5 methods/properties outside of the “Query” cluster of types. In order to achieve this encapsulation, I’ve had to lump all of these into a single 2k+ lines-long file with heavy use of fileprivate, which is a real pain to manage in terms of reading, editing, and SCM.</div><div class=""><br class=""></div><div class="">One might say, oh, that’s not so bad, except this is one example of many similar situations in a very large codebase consisting of the Application and 9 subordinate Modules.</div><div class=""><br class=""></div><div class="">With this or similar sub-module system, this code could easily be factored into a tight cluster of specialized files, with no one file being larger than a couple of hundred lines, and most being in the 10–50 line neighborhood—much more manageable.</div><div class=""><br class=""></div><div class="">In fact, I’d go so far as to say that if I had a real sub-module system, many of those Modules would get demoted. The cost of maintaining full frameworks for code that will never be used outside of this application just to achieve encapsulation isn’t trivial. </div><div class=""><br class=""></div><div class="">And another neat thing about a directory-based approach as I’ve proposed is that if I ever do want to “promote” a sub-module to its own Module, it’s very easy to do because I know where *all* the files are, and all of the sub-module’s child sub-modules automatically get “promoted up” one level without any effort. </div><div class=""><br class=""></div><div class="">—Karim</div><div class=""><br class=""></div></body></html>