I have been using empty enums as "namespaces" and have been pretty pleased with how that has played out. Unfortunately, it leads to undesirable indentation as a level of indentation is required to declare a nested type:
This level of indentation is not required when extending the nested type:
extension Foo.Bar {
}
I have considered experimenting with this layout to eliminate the indentation:
extension Foo { struct Bar {
}}
But I haven't actually done this because it is clunky, somewhat hard to read, and I work on a large team where it may have unintended consequences for code formatting in other contexts.
The best solution would be too just support this relatively obvious syntax:
struct Foo.Bar {
}
Of course this would be supported for enum and class in addition to struct.
While "namespaces" are the most frequent use case where I run into this they are certainly not the only use case. This sugar would increase clarity every time we wish to declare a nested type outside of the declaration of the original type. In addition to reducing indentation, this syntax makes the full name of the type clear in its declaration. It also avoids the need to introduce an unwanted scope where members could be added to the containing type.
Yes please, I always wanted this in Swift. (Of course we would extend this functionality later if nesting were added for protocols). Since I personally use extensions for nested types extensively, I'm really tired of this inconvenience. I can't see how this sugar would prevent Swift from implementing other features. That said this sugar is definitely is the right way to go.
@anandabits please also consider this very old thread, especially the last post.
I'm not sure how I feel about this at the language level yet, but I'll note that this will probably be difficult to implement because of the pervasive use of lexical DeclContexts throughout the compiler, particularly for lookup purposes. That doesn't say whether it's a good or bad feature, of course.
Bummer, not knowing the compiler I was thinking it might be straightforward since there is an obvious de-sugaring of introducing extensions that only contain the declaration.
+1 to this idea. Needing to indent nested types (which I also use a lot) has always felt distracting / messy to me.
I think the long-standing bug of Swift not parsing nested types in the correct order could be fixed at the same time this is implemented. :) That would be great.
I would love to see this, but I would also like to see proper namespaces. I think much this would be alleviated if the language had namespaces/packages/modules (a different kind of "module", where >1 could exist per project)
FWIW, I view namespaces as an orthogonal feature. There are lots of reasons to nest types. Using empty enums to mimic namespaces is just one. Further, if we had namespaces I would still prefer:
namespace Foo {}
struct Foo.Bar {}
over:
namespace Foo {}
extension Foo {
struct Bar {}
}
So I think this syntactic sugar would be extra handy in the presence of namespaces.
Swift 0.00001 (not really a thing, but you get the idea :-) had this and we removed it as a premature syntax optimization pretty early on (~2012?). That said, I still think it makes sense, and I also personally really dislike nesting that comes with namespacy things like extension and namespace{} in C++.
I’m curious if you have the same implementation concerns as Jordan. Does it require major surgery or is there a relatively simple way to implement the de-sugaring?
Okay that would be a convenient way for us to write code, but what would the imported API look like, the same or the old way with extensions? We also need to make sure that people don‘t start misinterpret access modifier on such types.
I am also interested on this feature. I have experienced the same scenario with the namespacing, and thought about the same syntactic sugar. I only see benefits on it, and feels something natural at this point.
I don't know what ASTPrinter does so I can't answer that. If it's supposed to preserve source structure format obviously the former. If not then I don't know. They are semantically equivalent.