Defining nested types in a new manner

Hi,
I have and idea about a new way to define nested classes and structs. I'll show it to you by example.

I use nested type a lot to encapsulate strictly related types. Consider this example:

struct Search {
    var settings: Settings

    func performSearch() {
        // Starts searching using setting.
    }

    struct Settings {
        var term: String

        func updateTerm() {

        }
    }
}

I use extensions to separate different functionalities. I break above code into two pieces (sometimes, two files) and define it like this:


struct Search {
    var settings: Settings

    func performSearch() {
        // Starts searching using setting.
    }
}

extension Search {
    struct Settings {
        var term: String

        func updateTerm() {

        }
    }
}

I was wondering if we could define the nested Settings without wrapping it in an extension, like this:

struct Search.Settings {
    var term: String

    func updateTerm() {

    }
}

I believe it's prettier in code appearance because it removes unnecessary indentation. If we add an extension to Settings right below it, the indentation level will be different from the actual Settings definition. But this approach removes the indentation. I think it is also better in readability.

Do you have an opinion about this? Is it reasonable? Can it be implemented in Swift? What are the positive and negative consequences?

24 Likes

Huge +1 from me!

I almost always write a separate extension that has a single nested enum/struct/class declaration, so this would mean a very noticeable code readability benefit for code bases like mine. Also, this seems like a harmless, easy-to-implement and obvious syntactic sugar!

5 Likes

This has been discussed a few times in the past, but I don't believe anyone has taken it as far as writing up an official proposal and implementation. I'd love to see it happen since the syntax would pair nicely with the use of extensions to organize code.

6 Likes

Hi,
First, I'm sorry for the duplicate. I exactly searched for the phrase "nested types" and these topics didn't come up.
I'm not familiar with the process of writing proposals but I'm ready to work on it. There are some parts in the proposal that I need to consult with someone familiar with the topic, such as effects on ABI stability. If anyone can help me with the proposal, I appreciate it.

I wonder if we could use “defer” for this purpose.

enum Enum1 {
    defer struct Struct1
}

struct Enum1.Struct1 {
    // whatever
}

It could work for methods too.

+1. It seems like a small but nice step from the currently possible:

struct Search {
    var settings: Settings

    func performSearch() {
        // Starts searching using setting.
    }
}

extension Search {
    struct Settings {
        var term: String
    }
}

extension Search.Settings {
    func updateTerm() {

    }
}

to the proposed:

struct Search {
    var settings: Settings

    func performSearch() {
        // Starts searching using setting.
    }
}

struct Search.Settings {
    var term: String

    func updateTerm() {

    }
}

I guess it would be a good idea to think about what other things would follow naturally from this. I can just come up with one right now:

typealias Search.Result = String
2 Likes

I've worked in a large codebase that uses nesting extensively for several years now, I can say that IMO the step forward would be larger than it appears.

Agree, typealiases should be supported in addition to types. Other kinds of declarations are probably a step too far:

func Search.doSomething() { }
4 Likes

So I guess you've bumped into this a lot then, unless you started after 5.0.

I agree, what I meant was that the proposed feature seems like a small step conceptually (and perhaps even implementationally) from what's currently possible, but that it is (potentially very) nice for readability etc. : )

We did struggle with that once in a while and it was a PITA. I got pretty good at rearranging files to find the magic order that worked! :slight_smile:

3 Likes