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.
- 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.
Any variables defined with `internal` access will be visible across those
···
On Tue, Feb 21, 2017 at 8:22 PM, Robert Widmann <devteam.codafi@gmail.com> wrote:
On Feb 21, 2017, at 9:13 PM, Xiaodi Wu <xiaodi.wu@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:
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