Well put. As for me, it is not the syntactic delta with which I am concerned. It is just a canary for the organizational delta.
There are certain freedoms enabled not by the _lack_ of constraints but rather their judicious application. Swift has in the past--and it is your burden to justify why it shouldn't continue to in the future--judged the file-based approach to be one such judicious constraint. On Tue, Feb 21, 2017 at 21:42 Robert Widmann <devteam.cod...@gmail.com> wrote: > On Feb 21, 2017, at 10:36 PM, Matthew Johnson <matt...@anandabits.com> > wrote: > > > On Feb 21, 2017, at 9:28 PM, Robert Widmann via swift-evolution < > swift-evolution@swift.org> wrote: > > > On Feb 21, 2017, at 10:03 PM, Xiaodi Wu <xiaodi...@gmail.com> wrote: > > On Tue, Feb 21, 2017 at 8:41 PM, Robert Widmann <devteam.cod...@gmail.com> > wrote: > > > On Feb 21, 2017, at 9:37 PM, Xiaodi Wu <xiaodi...@gmail.com> wrote: > > On Tue, Feb 21, 2017 at 8:22 PM, Robert Widmann <devteam.cod...@gmail.com> > wrote: > > > On Feb 21, 2017, at 9:13 PM, Xiaodi Wu <xiaodi...@gmail.com> wrote: > > On Tue, Feb 21, 2017 at 7:59 PM, Robert Widmann via swift-evolution < > swift-evolution@swift.org> wrote: > > > On Feb 21, 2017, at 7:36 PM, Nevin Brackett-Rozinsky via swift-evolution < > swift-evolution@swift.org> wrote: > > To my mind, any submodule system for Swift should be designed to relieve > the pressure for long files, and make it easy to group tightly related > files into a single unit with shared visibility. That way developers can > easily organize their code into smaller files while utilizing Swift’s > pattern of providing protocol conformances in extensions and keeping > implementation details hidden from the rest of the module at large. > > > Wonderful, because that’s absolutely supported by this proposal. To group > tightly related files into a single unit, simply declare a submodule for > them and extend it in each of your related files. > > > It's supported, but it isn't first-class. By this I mean: there are two > distinguishable uses supported by your proposal, lumped together by the > fact that they are both about grouping units of code together. Put crudely, > one use case is grouping lines of code, while the other is about grouping > files of code. The merits of supporting both have already been debated in > this discussion. The issue I'll touch on is supporting both with the same > syntax. The chief drawbacks here are: > > > What exactly would be required to *make* it first class? Referencing > file names in the module declaration? > > > See below. > > - It makes sense to use braces to group lines of code, but it makes no > sense to use braces to group files of code; this just causes entire files > to be indented. > > > If braces aren’t used to demarcate scopes, nesting modules becomes > ambiguous. > > > Again, let's observe the distinction about grouping files vs. grouping > lines. > > Grouping files does not require braces: if the intended use of your > feature were to label files X, Y, and Z as belonging to one submodule and > A, B, and C to another, it would not matter if X, Y, and Z belonged to > Foo.Bar and A, B, and C to Foo.Bar.Baz: your syntax would not require > braces. > > > It’s important to note that indentation is one particular style. LLVM > code style, in particular, chooses not to indent after namespace > declarations. This issue also crops up when dealing with nested type > declarations, and I distinctly remember it not being a big enough deal to > "fix this" at the time when a proposal to “flatten” these declaration was > brought up. > > > Mine is not a critique of the syntax itself; I don't particularly care > about indents, nor do I mind not indenting namespaces. > > What I'm saying is, you would not have chosen to require braces if your > proposed feature were aimed at making the grouping of files into submodules > as simple as possible. You chose to accommodate grouping lines using the > same syntax as grouping files over the simplest design for grouping files. > Make no mistake, this promotes one use over another. > > > Ah, I see. Yes, one of the stated goals is to become > filesystem-independent. We certainly cannot do that by encouraging the > alternative. > > > Swift's current design is deliberately not file system-independent. A > submodule design built on top of Swift could preserve that. Your draft > proposal makes two changes: it introduces a design for submodules; and, it > eliminates files as a unit of code by default (not least by declaring > `fileprivate` redundant). To my mind, you have presented no justification > for the second change other than to say that it is a stated goal--but why? > > > > > > - fileprivate access can be recreated by creating a private "utility > submodule" containing declarations of at most internal access. > > > > > - Because some lines of code necessarily precede some other lines of code, > it makes sense to declare the first group using `module` and to extend that > with the second group using `extension`. However, because a file of code > does not necessarily precede another file of code, it is arbitrary which > file is surrounded with a `module` declaration and which one is surrounded > with an `extension` declaration. > > > Absolutely. But it is similarly arbitrary which public APIs are exposed > in a type declaration and which are exposed in an extension declaration. > > > Not entirely, no. Stored properties must be in the type declaration. Enum > cases must be in the type declaration. Perhaps you regard these as > temporary inconveniences of the current grammar; I see them as quite > reasonable ways to give some consistency as to what's written where in a > language where types can be retroactively extended. In a very real sense, > you must read the type declaration before you read the extensions in order > to understand the latter. By comparison, there is nothing that must be in > your proposed module declaration. > > > My hope is that the module declaration itself will become the > one-stop-shop for re-exports and general public bookkeeping just as > aggregate declarations are today. Module extensions exist to accommodate > users that wish to break related functionality across files or into > separate independent regions within the same file for the same reasons type > extensions exist. > > > Indeed, that you phrase it this way supports Nevin's argument. _Module > extensions_ exist to accommodate his use case; however, his use case > (which, mind you, is what I think most people are thinking of when it comes > to submodules, given previous threads on this topic) isn't the raison > d'etre for your submodule proposal. Quite simply, a syntax that > accommodates both grouping lines and grouping files cannot make the latter > first class, because the former necessarily requires more ceremony. > > > Okay, but the question still stands: what do we need to make Nevin's > use-case first class? > > > We need to have either *two* spellings for a submodule feature that > supports both grouping files and grouping lines of code, or we need to have > *two* features, one for grouping files and another for grouping lines of > code. In any case, the spelling for grouping files should: > - Not require braces > - Not require one file to be a `module` and another to be an `extension` > > The simplest such spelling would be: > > File A: > ``` > module Foo > // rest of file > ``` > > File B: > ``` > module Foo > // rest of file > ``` > > > This was mentioned earlier, so I will quote my response to the last poster: > > That is a valid spelling (Rust, IIRC, allows that spelling), but one that > is easy to miss sitting in a file and makes it confusing to introduce > submodules. If you include the annotation then define a submodule later > down in the file, suddenly you have to remember whether you annotated the > file or whether the submodule you’ve just written is going into the > top-level module. See: > > // -module-name=Foo > // module Foo { > module Bar; // Shorthand for “This file defines Foo.Bar” > > /* Code */ > > // This defines “Foo.Bar.Baz”, but would you know that if it appeared > below the fold? > module Baz {} > //} > > > But that reply was oriented towards a “why can’t we have nested modules > and a shorthand too?” Here, you’re referring more to the > one-module-one-file language restrictions, so I will quote another response: > > For one-file-per-module, that kind of restriction represents a particular > way of organizing code and is a design pattern that is supported under this > proposal. We just happen to not enforce that particular pattern, and feel > that it is the job of a linter to do so. Really, this kind of restriction > is to ease the mental burden on compiler writers who use it to build > compilation unit dependency graphs. Swift already considers all files when > building its modules because you can extend any type (and now, any module) > from any one of them so it doesn’t buy us anything other than an arbitrary > restriction. > > Realistically, the only difference between the proposal’s syntax and this > one is two characters (the braces) and maybe some tabs if you decide to > enforce that style. There are few objective organizational benefits from > your style, and it creates a bureaucratic rule where none need exist. > Subjectively, of course, people may prefer this way, or they may prefer a > more ad-hoc approach. But we designed for both cases and showed our hand > by favoring non-physical organization because it is a subset of possible > organizational styles available to users. > > > Your earlier post argues that your syntax is better because with the > alternative approach it’s too easy to forget whether there is a module > statement at the top of the file or not. Now you’re arguing that the > difference is just two braces and that they’re relatively insignificant. > You can’t have it both ways. > > > Now I’m context switching… I will clarify: Syntactically the delta between > the proposal and Xiaodi’s syntax is two braces. Organizationally it means > the difference between Java-style packages that divide named modules into > files and approaches that allow for freedom by ignoring this constraint. > > > > > > To my mind, we’ve offered a syntax and semantics internal to the language > that supports file-only aggregation because file-only aggregation enables a > subset of the actual use cases of this module system. We aren’t enforcing > this by compiler-fiat because it is a stylistic choice that can be enforced > by a linter. > > > It's not enough to offer a syntax and semantics that supports it; if it is > the intended major use case, the design ought to reflect that by making > that use case no less cumbersome than necessary. > > > See above for aesthetic concerns. > > > Any variables defined with `internal` access will be visible across those > files to those extensions and only those extensions (see the section on > access control and modules). Any variables declared fileprivate or private > will, obviously, not be visible across these files. As an example: > > // FooUtilities.swift > // > // -module-name=Foo > // module Foo { > // Defines Foo.Utilities > module Utilities { > public func exportableOutsideThisSubmodule() {} > func visibleInThisSubmodule() {} > private func invisibleToOtherFiles() {} > } > //} > > // FooUtilities+MoreUtilities.swift > extension Utilities { > private func privateHelper() { > visibleInThisSubmodule() > } > } > > I’m not sure where you got the impression that we were just trying to make > another fileprivate happen. > > > Nevin > _______________________________________________ > swift-evolution mailing list > swift-evolution@swift.org > https://lists.swift.org/mailman/listinfo/swift-evolution > > > > _______________________________________________ > swift-evolution mailing list > swift-evolution@swift.org > https://lists.swift.org/mailman/listinfo/swift-evolution > > > _______________________________________________ > swift-evolution mailing list > swift-evolution@swift.org > https://lists.swift.org/mailman/listinfo/swift-evolution > >
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution