`namespace` keyword

I don’t ever remember ever wanting to nest a protocol inside a struct though I feel like it’s something I might want to do someday. but that has nothing to do with a namespace keyword.

as for syntax if we do namespaces,,, and i’m not saying i think it’s a perfect idea,,, i think it should look like a typealias, not a protocol. getting rid of the braces would mean no more moving all of your code four spaces to the right just to get a namespace

public 
namespace SecondThing

public 
struct SecondThing.MyValue 
{
    let something:MyProtocol
}

public 
protocol SecondThing.MyProtocol { }

let secondValue:SecondThing.MyProtocol

If that’s the biggest flaw, then it seems like you’ve also identified the most straightforward solution here too.

4 Likes

I think the biggest actual flaw with using an enum as a namespace is that it doesn't default to static.

3 Likes

Furthermore submodules does not solve the issue where you may need a namespace in between (sure it's possible with enums, but this is still ugly).

SubModule.Type.Namespace.Type
  • SubModule like always is optional
  • Type.Namespace.Type is required

I think, this isn’t exactly true.

A enum is a type and carries type information with it, a namespace would not do it. Also you could declare it multiple times instead of extending it. e.g.

public enum MyNamespace {
    public static func printName() {
        print("MyNamespace")
    }
}

public extension MyNamespace {
    public struct MyStruct {
        public let value: Int
    }
}

Could become

public namespace MyNamespace {
    public func printName() {
        print("MyNamespace")
    }
}

public namespace MyNamespace {
    public struct MyStruct {
        public let value: Int
    }
}

Of course there are other possible syntaxes which could be used, I also like that, which you have proposed in your topic.

4 Likes

I definitely think namespaces shouldn't be implemented like typealiases. You could have many static functions in the namespace and having to have the namespace name prefixing them would be extremely repetitive.

All that needs to be done is introduce a keyword that does exactly the same as enum except it doesn't allow case statements inside it.

We have namespaces already*, they're just created with a keyword made up of the letters "e", "n", "u" and "m". All we need now is a keyword that makes sense to the human reader.

*Yes ideally the namespace wouldn't be a type. But this seems acceptable to the swift community already when we use enums for namespaces.

1 Like

I disagree, there’s more to talk about. For instance, I would expect all functions and properties be static by default.

1 Like

Well that decision would depend on the decision to make the namespace a type. If it's not a type then the static wouldn't be allowed (same as not being able to have a static function at root level).

However I'd argue that it should be a type as this would allow them to conform to protocols and allow passing around the collection of functions and variables. If this isn't the case then users will still have to revert to using enum's for that scenario.

Alternatively we could add two new keywords, singleton(?) and namespace where the former is a type and the latter isn't. But I don't think this is necessary as there is no reason to restrict a namespace from being passed around.

(ok maybe there's more to talk about :))

I think introducing namespaces is pretty questionable to begin with if it's just because people don't like typing enum, extension and static and would prefer to type namespace and have members be static by default. We should have compelling motivation demonstrating what interesting new capabilities namespaces would offer that empty enums don't already provide.

Given my caution about namespaces in general, I think two new keywords is definitely overkill. If we do introduce namespaces they should absolutely be types that can be generic, can conform to protocols that only have static requirements, etc. Any other design would be unnecessarily crippled IMO.

5 Likes

I agree! What's your reasoning for saying the members should be static by default?

Though I think there should be strong motivation to introduce them so that enum's can stop being misused. There are two distinct use cases and meanings, so there should be two keywords.

I didn't say that, others did. I can see arguments both ways on that topic.

What I said was that they should be able to conform to protocols that only have static requirements. A namespace wouldn't have instances so it couldn't conform to protocols that have instance requirements (unless we went with the singleton design where members would in some sense be both static and instance members).

I don't understand why namespaces should be types at all. A namespace should simply be a lightweight way to group things together so that they don't clutter up autocomplete or slow down type checking and overload resolution with name collisions. One of the benefits of having proper namespaces is that they don't generate extra metadata that has to be stored in the runtime.

That doesn't necessarily mean that you shouldn't be able to get a list of all types and functions declared in a namespace, but there definitely shouldn't be any value or protocol witness tables generated for a namespace.

3 Likes

There certainly wouldn't be value witness tables because you wouldn't be able to create values. But what's the harm in protocol witness tables if it's useful to declare conformances? I have already used empty enums in ways similar to ML modules and any new feature should definitely support that use case.

IIRC @codafi had a submodules proposal that was pretty much "namespaces" done right. I wasn't a huge fan of that proposal because I didn't see enough value over empty enums to justify it defining "submodules" in Swift, particularly since I would prefer to see a submodules go in a somewhat different direction - more similar to Swift's modules but without the overhead of introducing a separate build target.

Why would you want to conform it to a protocol? How is it useful to declare conformances? It's just a visibility barrier. The only reasonable things to do with it are: look up a name, add a name, or remove a name. And that last one only makes sense if we're doing runtime code-generation of a kind that we currently have no tools to support (although they'd be very cool to have).

1 Like

Swift protocols that only have static requirements are roughly equivalent to ML signatures and empty enums in Swift (or namespaces / modules or whatever in the future) are roughly equivalent to ML structures. If you're interested in learning about a different way to use Swift's protocols I recommend reading up on the ML module system. That would answer your question in abundant detail.

1 Like

I would argue that the strength of having a separate namespace construct in the language is what it CAN'T do as opposed to whiz-bang things it can do. For example:

  1. We know it can't be instantiated

  2. We know it can't be generic

That guaranteed simplification means that the design issues that are stopping us from having protocols in enums, etc... just don't happen. In other words, we could have things like that now instead of waiting another 2 swift versions.

I am also looking forward to things like protocols-in-classes and submodules. The question is: Is perfect the enemy of the good here, when we could have many of the practical benefits that these would bring us now?

8 Likes

Where is this subject at now? I've worked on a project with a myriad of enums used everywhere just as namespace and I found it quite confusing in the end. Seriously. It looks like a hack every time.

12 Likes

Good question. Today is 22 of 02 of 2022. And using enum as namespace still looks a hack every time. ;)

7 Likes

I've heard in a parallel univers people will add the scope keyword.

2 Likes