Why can't Protocols be nested in other Types?

We can nest classes, structs & enums:

class TestClass {
     class OtherClass {}
     struct OtherStruct {}
     enum OtherEnum {}
}


Why can't we also nest protocols?

class TestClass {
     protocol Delegate {}  // error: Declaration is only valid at file scope
}


So far the workaround is to declare it at file scope using and use a typealias instead.

The underscore prefix makes it clear that the global symbol name is not intended for direct use.

class TestClass {
     typealias Delegate = _TestDelegate
}

protocol _TestDelegate {}


Is this just not yet implemented or is there a reason for not supporting that at all?

I'm confused as to why that would be beneficial in the case you outline. The only reason to define a delegate protocol is to allow classes outside the enclosing class's context to implement it.

I think he is interested in namespacing. He wants the type of the delegate protocol to be 'TestClass.Delegate'. Makes sense to me...

Exactly. I'd like to reduce the global namespace pollution and it makes the connection between some types and their related protocols much clearer.

Best example is all the XYZDelegate protocols.

Why are you not using the Swift ways to do that? Private access and frameworks.

One of the main use cases for nesting is to bundle abstractions that belong together. Doing this via frameworks does not scale since frameworks only represent larger software components. Here's an example for two classes each providing their own factory type:


class Foo {
  protocol Factory {
    func newFoo() -> Foo
  }
  ...
}
class Bar {
  protocol Factory {
    func newBar() -> Bar
  }
  ...
}


In Swift, a programmer needs to workaround this by using naming conventions, e.g. `FooFactory` and `BarFactory`.

Frameworks are far too heavy-weight to be practical within a given codebase.


There are plenty of cases where one wants to encapsulate a small bit of collective functionality across multiple types (and multiple files) that absolutely do not warrant a framework. This problem would be easily solved if Swift provided for lighter-weight "namespaces" or "sub-modules" that could be described declaratively. Something like:


namespace Foo

class Foo.Bar { ...

struct Foo.Bast { ...

protocol Foo.Blah { ...


I filed a radar about this back with 1.0 was released, and it was immediately marked as a duplicate, so I have some hope that there might be an answer at some point.


IMHO, it would be even better if 'internal' applied to such a namespace, but I know that's a losing battle. As it stands, in general Swift, I only have one access level (private) to model encapsulation with, because I don't typically build frameworks.

That's a thing I don't get - What is heavy at frameworks? They are easily created and have nearly zero overhead.

You lose optimization opportunities for example. Its like put all the optimizations made with "whole module optimization" in the trash just to organize the code.

Well time to be less theoretical: WHAT should be organized and protected from WHAT? I still believe any sensible design is doable with frameworks and/or private access restrictions. For example helper elements should never leave their source file: in a list file only the list class should be non private, node class etc stay private.

I mean, compiler optimization, for performance reasons. Some sample presented on WWDC increase about ~20 fps only making "in module" optimizations. The compiler should see all code to make the correct assumption with memory management, inline access, etc...

Frameworks just split the code optimization opportunities. Doesn't matter what are you protecting, using Frameworks, you code will be larger and less performatic. So, i dont think is a good idea split the code in a Framework just to get a new namespace.

I see - It's a case of premature optimization … That's the reason for me wanting a direct example what should be seperated from what by namespacing. If the code is so strongly entwined it shouldn't be seperated of course.

Yes, I've been wanting this for the same reason: Namespacing and DRY.


This:

class SomeClass {
  protocol Delegate {
    func someClassDidThis()
  }
  
  var delegate: Delegate

  init(delegate: Delegate) {
    self.delegate = delegate
  }
}


Vs:

class SomeClass {
  var delegate: SomeClassDelegate
  init(delegate: SomeClassDelegate) {
    self.delegate = delegate
  }
}
protocol SomeClassDelegate {
 func someClassDidThis()
}

You're right, probably this kind of code will be never be splitted in two namespaces anyway. But this is just a example, frameworks are not "zero cost", and Swift sometimes (for now) can be very slow without these optimizations, and will never replace tons of c++ codebase for several projects.


But my point is very simple: My only option to create a "subscope" is making a framework? Ok, its easy to create, and easy to maintain, but i really need the "entire" framework infrastructure to avoid XYZDelegate? Doesn't look a big problem, but i think its a good idia make nested protocols like we do for nested types.

Why not simply like that?


protocol Factory {
  typealias bla
  func new() -> bla
}

I'm not sure how this helps bundling abstractions that belong together. You are solving a completely different problem here. Just think of one factory needing two `Int` values as parameters of the constructor, and the other a `String` value.


class Foo {
  protocol Factory {
    func newFoo(x: Int, _ y: Int) -> Foo
  }
  ...
}
class Bar {
  protocol Factory {
    func newBar(string: String) -> Bar
  }
  ...
}

What I fail to understand is why you want to abstract it out of the class the first place. It's just a single method.


And as a second point: protocols are intended, as in Obj-C, to define behaviour like compareable. It is not a poor mans multiple inheritance as interfaces in java or c++.

Concrete example:


I have a project with a large codebase (> 100s of classes/types). One of these types is a Script-Runner class, with public (internal) interfaces, and several internal (private) classes, including a large, complex script parser which runs to nearly 2500 LOC.


Now, the Script-Runner is the only thing that needs access to the parser and its related internal types, but these types are not completely severable from the rest of the application (they need access to various types within the rest of the codebase for utility, context, etc). In current Swift, I have only two unpleasant choices:


  1. pollute the whole application's namespace with many dozens of type names, protocols, methods, variables, etc which serve no purpose outside of this script parsing functionality
  2. put these types in a single file (to make use of 'private') resulting in a massive 4000 LOC file


I've chosen #2 as the least onerous, but that doesn't mean it's a good solution.

I see #2 as the good solution. I never got where that madness of 1 class = 1 file came from. But the problem sounds like a perfect fit for a framework.

Not a good fit because there are cross-dependencies. The private code is not easily factorable into a framework independent of the rest of the application, and trying to extract it would rapidly devolve into a nightmare of framework dependencies.


I'm not super-strict about 1 class = 1 file, but I strongly dislike being forced into using source files to impart syntactical structure. Where does it end? If I need to increase the complexity of the script parser, should I have a 10k-line file? 20k? That's absurd. In a modern language, why should file boundaries be the only viable tool for managing encapsulation?

I think in this case "Factory" can be a nested type, some struct ou some anonymous enum (without case).


class Foo {
  enum Factory {
    static func newFoo(x: Int, _ y: Int) -> Foo {
        //...
        return Foo();
    }
  }
//...
}
class Bar {
  enum Factory {
    static func newBar(string: String) -> Bar {
        //...
        return Bar();
    }
  }
//...
}

var tBar = Bar.Factory.newBar("someString");

It appears from the info you have given, that your code is way to tighly coupled. No form of namespacing will remove that design error.


And why a file as scope? Because it is a natural unit of code. Many languages use file based scope, just not C/C++. Pascal units, Modula/Oberon modules, Python modules etc.

Why not simply so?


class Foo {
  static func new(x: Int, _ y: Int) -> Foo {
    return Foo()
  }
}

class Bar {
  static func new(string: String) -> Bar {
    return Bar()
  }
}

var tBar = Bar.new("something")


And please don't use ; as line ending in Swift 🙂

pontificate if you like, but it's not a design error... its the nature of the problem domain. The script parsing is directly related and tightly coupled to information available from the rest of the application. Just because you don't understand the architecture from my brief description doesn't make it invalid.

That goes against all of my knowlegte of parsing theory - tighlly coupling to the internal data structures sound like a sure way to trouble.


Anyway, if your code is or requieres such tight coupling huge compilation units are the logical result. You have to keep all related stuff together.

This is what generally i do... I dont like the idea to make the FactoryType or similar... But some people like.

Why can't Protocols be nested in other Types?
 
 
Q