> 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 > <mailto:devteam.cod...@gmail.com>>wrote: > >> On Feb 21, 2017, at 9:13 PM, Xiaodi Wu <xiaodi...@gmail.com >> <mailto:xiaodi...@gmail.com>> wrote: >> >> On Tue, Feb 21, 2017 at 7:59 PM, Robert Widmann via swift-evolution >> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote: >> >>> On Feb 21, 2017, at 7:36 PM, Nevin Brackett-Rozinsky via swift-evolution >>> <swift-evolution@swift.org <mailto: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. > >> - 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? 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. >> 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 <mailto:swift-evolution@swift.org> >>> https://lists.swift.org/mailman/listinfo/swift-evolution >>> <https://lists.swift.org/mailman/listinfo/swift-evolution> >> >> >> _______________________________________________ >> swift-evolution mailing list >> swift-evolution@swift.org <mailto:swift-evolution@swift.org> >> https://lists.swift.org/mailman/listinfo/swift-evolution >> <https://lists.swift.org/mailman/listinfo/swift-evolution>
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution