> On Feb 21, 2017, at 10:36 PM, Matthew Johnson <[email protected]> wrote:
>
>>
>> On Feb 21, 2017, at 9:28 PM, Robert Widmann via swift-evolution
>> <[email protected] <mailto:[email protected]>> wrote:
>>
>>>
>>> On Feb 21, 2017, at 10:03 PM, Xiaodi Wu <[email protected]
>>> <mailto:[email protected]>> wrote:
>>>
>>> On Tue, Feb 21, 2017 at 8:41 PM, Robert Widmann <[email protected]
>>> <mailto:[email protected]>>wrote:
>>>
>>>> On Feb 21, 2017, at 9:37 PM, Xiaodi Wu <[email protected]
>>>> <mailto:[email protected]>> wrote:
>>>>
>>>> On Tue, Feb 21, 2017 at 8:22 PM, Robert Widmann <[email protected]
>>>> <mailto:[email protected]>>wrote:
>>>>
>>>>> On Feb 21, 2017, at 9:13 PM, Xiaodi Wu <[email protected]
>>>>> <mailto:[email protected]>> wrote:
>>>>>
>>>>> On Tue, Feb 21, 2017 at 7:59 PM, Robert Widmann via swift-evolution
>>>>> <[email protected] <mailto:[email protected]>> wrote:
>>>>>
>>>>>> On Feb 21, 2017, at 7:36 PM, Nevin Brackett-Rozinsky via swift-evolution
>>>>>> <[email protected] <mailto:[email protected]>> 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
>>>>>> [email protected] <mailto:[email protected]>
>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>>>>
>>>>>
>>>>> _______________________________________________
>>>>> swift-evolution mailing list
>>>>> [email protected] <mailto:[email protected]>
>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>> _______________________________________________
>> swift-evolution mailing list
>> [email protected] <mailto:[email protected]>
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution