> 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

Reply via email to