[swift-evolution] [Discussion] Namespaces

Tony Allevato allevato at google.com
Fri May 20 11:15:32 CDT 2016


On Fri, May 20, 2016 at 8:48 AM Matthew Johnson <matthew at anandabits.com>
wrote:

> On May 20, 2016, at 10:27 AM, Tony Allevato via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> Another use case to consider: code generation. There, namespaces can be
> vital; they let you isolate code that you may have no real control over
> (for example, data models that correspond to remote services) from the rest
> of your code to avoid collisions. In some cases that can be achieved by
> putting the shared code in its own module, but if that data description
> format has hierarchical namespaces/packages of its own (Google's protocol
> buffers, for example), then the lack of namespaces forces the code
> generator to come up with contrived schemes for naming nested entities
> (like the Objective-C implementation, which uses
> underscore_delimited_names). The result is that Swift code using those
> services would look *very* unnatural.
>
>
> What benefits do namespaces provide that empty enums and / or submodules
> do not?  This isn’t clear to me and I think it is an essential part of the
> case that must be made.
>

> Nobody is arguing that we don’t need a way to isolate names.  The question
> is whether namespaces are the right mechanism for doing that or not.
>

I'm certainly flexible on the way that organization manifests itself. In a
general sense, using structs-with-private-initializers or enums seems like
abuse of those constructs. Generic types also can't be nested yet (but this
is well-known and on the list of things to fix).

Some other concerns from my own experience in the domain of code generation:

I need to be able to define namespaces/organization in the source code, not
as an artifact of the build system, which may prevent submodules from
working as intended. Unless we want to be so prescriptive as to say, this
is the One True Way that you will build your Swift code and nothing else
matters, in which case I could probably generate a companion Swift package
manifest.

Would submodules support circular references between them? If module
Foo.Bar has a type that references something in Foo.Baz, and Foo.Baz has a
type that references something in Foo.Bar, will that import work (they
don't even have to be circular references between two *types*, just
different types within two *modules*)? If it's like regular top-level
modules now, that's not possible, because A can't import B if B imports A.

Structs/enums as faux namespaces also fall apart if you try to link
multiple build artifacts into the same library or executable. Let's say I'm
using a code generator to generate types from a data model that defines a
namespace Foo. Let's go on to say that, due to the way the dependencies of
my project are structured, the code for type Foo.Bar is generated
separately from Foo.Baz. Each run of the code generator needs to be
independent, so in order to do that, it defines an empty Foo struct and
extend it with the types inside that namespace that are generated in that
run. So, in one run I have this:

generated1/Foo.swift:
public struct Foo { private init() {} }

generated1/Foo.Bar.swift:
extension Foo {
  struct Bar { ... }
}

and in another run, I have this:

generated2/Foo.swift:
public struct Foo { private init() {} }

generated2/Foo.Baz.swift:
extension Foo {
  struct Baz { ... }
}

I have two copies of the Foo struct, so I can't easily compile these
sources into object files and then pull them all together to link. Even
though Foo doesn't contain anything other than nested types, the compiler
outputs metadata symbols for Foo itself that causes duplicate link errors.

Swift as it is today already gets me *almost* the whole way there—merging
the .swiftmodules produced from the builds above works fine and results in
a module that defines both Bar and Baz inside Foo. Essentially, my use case
would be solved if I could somehow say "Foo is not actually a type, it's
used for organization and name mangling only, so please don't include any
symbols for it alone in the output binary". Then everything would link
correctly.



>
>
> On Fri, May 20, 2016 at 8:08 AM T.J. Usiyan via swift-evolution <
> swift-evolution at swift.org> wrote:
>
>> +1 for namespaces.
>>
>> On Fri, May 20, 2016 at 10:52 AM, Haravikk via swift-evolution <
>> swift-evolution at swift.org> wrote:
>>
>>>
>>> > On 20 May 2016, at 14:51, Krystof Vasa via swift-evolution <
>>> swift-evolution at swift.org> wrote:
>>> >
>>> > When you have namespaces Car and Animal and each contains a class
>>> called List, IMHO there should be classes CarList and AnimalList. It's more
>>> verbose, but you imediately know which class is being used in opposite of
>>> just using List.
>>>
>>> Why not use Car.List and Animal.List when its unclear from context? With
>>> Swift’s type inference you don’t often need to specify types anyway so your
>>> editor will know which list type you’re using based on how you obtained it.
>>>
>>> That said it does depend on the purpose of each List; do they have any
>>> commonality? They could for example both be generic List implementations,
>>> but were never factored out into a common module. If however they are
>>> specialised constructs specific to cars or animals, then the prefix may
>>> make most sense.
>>>
>>> For example, in the libdispatch thread the naming of
>>> Dispatch.DispatchQueue was queried, however this isn’t a general purpose
>>> queue type, it’s more specialised than that, so a name of “Queue” doesn’t
>>> convoy enough information, just as List might not. But it depends on what
>>> it actually does, which a basic example tends not to include ;)
>>>
>>>
>>> Anyway, I’m +1 for namespaces everywhere, some names can be common. For
>>> example Node could be related to trees, physics engines and all sorts of
>>> constructs. “Node” may be a perfectly fine name for these. That said, these
>>> are sometimes tied to specific types in which case nesting them may make
>>> more sense, which I believe is already being addressed (currently we can’t
>>> nest generic types)? It’s certainly not as simple as it can appear!
>>> _______________________________________________
>>> swift-evolution mailing list
>>> swift-evolution at swift.org
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>
>>
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160520/27ee7a30/attachment.html>


More information about the swift-evolution mailing list