> 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 <mailto:swift-evolution@swift.org>> wrote: >> >>> >>> On Feb 21, 2017, at 10:03 PM, Xiaodi Wu <xiaodi...@gmail.com >>> <mailto:xiaodi...@gmail.com>> wrote: >>> >>> On Tue, Feb 21, 2017 at 8:41 PM, Robert Widmann <devteam.cod...@gmail.com >>> <mailto:devteam.cod...@gmail.com>>wrote: >>> >>>> On Feb 21, 2017, at 9:37 PM, Xiaodi Wu <xiaodi...@gmail.com >>>> <mailto: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. >>> >>> 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 <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 <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