Enhancing access levels without breaking changes


(Tino) #1

Imho there is a simple solution to reach the goals of SE-0169 without breaking compatibility:
Just allow extensions inside type declarations.

class MyVC: UIViewController {
    private let numberOfSections = 0

    extension: UITableViewDataSource {
        // Skipping the class and assume we want to extend the surrounding type
        func numberOfSections(in tableView: UITableView) -> Int {
            return numberOfSections
        }

        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return 0
        }
    }

    private extension {
        // this would contain everything that shoudn't be visible for other extensios

        var secret: Int = 0

        public extension MyFriendClass {
            // oh, well, I make an exception here for a trustworthy type
            func checkSecret(of controller: MyVC) -> Bool {
                return controller.secret > 0
            }
        }

        private extension {
            // this is so secret, I'm not even allowed to copy it
        }
    }

    public func myMethod() {
        print("This is just a boring method")
    }
}

It has the downside of shifting code to the right (you could as well leave those extension-blocks unindented), but lots of advantages:
- No change for private needed
- It can be nested as much as you like to satisfy even the most absurd desires of encapsulation
- It reminds me on operator definitions inside type declarations
- No change for fileprivate needed (but actually, I think there is very little need to keep fileprivate)

I wish this would only be a joke, but writing the example, I actually started liking the concept (but I have a terrible headache right now which might affect my mind) — so either this receives some feedback, or I might start re-proposing this :wink:

- Tino


(Charlie Monroe) #2

This seems like a nice compromise, though it introduces a "horizontal" issue of indentation. Not a huge issue IMHO, though I think some people may see it as a downside.

For me, it's +1, though.

···

On Apr 8, 2017, at 2:03 PM, Tino Heth via swift-evolution <swift-evolution@swift.org> wrote:

Imho there is a simple solution to reach the goals of SE-0169 without breaking compatibility:
Just allow extensions inside type declarations.

class MyVC: UIViewController {
    private let numberOfSections = 0

    extension: UITableViewDataSource {
        // Skipping the class and assume we want to extend the surrounding type
        func numberOfSections(in tableView: UITableView) -> Int {
            return numberOfSections
        }

        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return 0
        }
    }

    private extension {
        // this would contain everything that shoudn't be visible for other extensios

        var secret: Int = 0

        public extension MyFriendClass {
            // oh, well, I make an exception here for a trustworthy type
            func checkSecret(of controller: MyVC) -> Bool {
                return controller.secret > 0
            }
        }

        private extension {
            // this is so secret, I'm not even allowed to copy it
        }
    }

    public func myMethod() {
        print("This is just a boring method")
    }
}

It has the downside of shifting code to the right (you could as well leave those extension-blocks unindented), but lots of advantages:
- No change for private needed
- It can be nested as much as you like to satisfy even the most absurd desires of encapsulation
- It reminds me on operator definitions inside type declarations
- No change for fileprivate needed (but actually, I think there is very little need to keep fileprivate)

I wish this would only be a joke, but writing the example, I actually started liking the concept (but I have a terrible headache right now which might affect my mind) — so either this receives some feedback, or I might start re-proposing this :wink:

- Tino
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Jon Hull) #3

This struck me as a bit odd at first, but the more I think about it, the more I really like the ability to nest extensions/scopes. The one issue I see is sticking that public extension inside a private one. I think you would have to mark ‘secret: Int’ as private instead of the extension itself to allow the effect you are looking for...

What I ultimately want is the ability to declare storage in extensions in the same submodule. Combining that with fileprivate will allow the same tricks without the indentation (together in their own file). This nesting will help in the mean-time (and would still be useful after for those who prefer to organize their code in fewer/longer files). I think it could be helpful in other ways too...

Thanks,
Jon

···

On Apr 8, 2017, at 5:03 AM, Tino Heth via swift-evolution <swift-evolution@swift.org> wrote:

Imho there is a simple solution to reach the goals of SE-0169 without breaking compatibility:
Just allow extensions inside type declarations.

class MyVC: UIViewController {
    private let numberOfSections = 0

    extension: UITableViewDataSource {
        // Skipping the class and assume we want to extend the surrounding type
        func numberOfSections(in tableView: UITableView) -> Int {
            return numberOfSections
        }

        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return 0
        }
    }

    private extension {
        // this would contain everything that shoudn't be visible for other extensios

        var secret: Int = 0

        public extension MyFriendClass {
            // oh, well, I make an exception here for a trustworthy type
            func checkSecret(of controller: MyVC) -> Bool {
                return controller.secret > 0
            }
        }

        private extension {
            // this is so secret, I'm not even allowed to copy it
        }
    }

    public func myMethod() {
        print("This is just a boring method")
    }
}

It has the downside of shifting code to the right (you could as well leave those extension-blocks unindented), but lots of advantages:
- No change for private needed
- It can be nested as much as you like to satisfy even the most absurd desires of encapsulation
- It reminds me on operator definitions inside type declarations
- No change for fileprivate needed (but actually, I think there is very little need to keep fileprivate)

I wish this would only be a joke, but writing the example, I actually started liking the concept (but I have a terrible headache right now which might affect my mind) — so either this receives some feedback, or I might start re-proposing this :wink:

- Tino
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Tony Arnold) #4

Hi Tino,

···

On 8 Apr 2017, at 22:03, Tino Heth via swift-evolution <swift-evolution@swift.org> wrote:

I wish this would only be a joke, but writing the example, I actually started liking the concept (but I have a terrible headache right now which might affect my mind) — so either this receives some feedback, or I might start re-proposing this :wink:

I’m not sure that this solves anything meaningful (whether in relation to SE-0169 or more generally), does it? What advantage does this provide over just declaring the protocol conformance and those methods as a direct part of the parent type? This seems like it would just introduce more indentation, and more lines of code, for zero benefit.

cheers,

Tony

----------
Tony Arnold
+61 411 268 532
http://thecocoabots.com/

ABN: 14831833541


(Chéyo Jiménez) #5

This struck me as a bit odd at first, but the more I think about it, the more I really like the ability to nest extensions/scopes. The one issue I see is sticking that public extension inside a private one. I think you would have to mark ‘secret: Int’ as private instead of the extension itself to allow the effect you are looking for...

What I ultimately want is the ability to declare storage in extensions in the same submodule. Combining that with fileprivate will allow the same tricks without the indentation (together in their own file). This nesting will help in the mean-time (and would still be useful after for those who prefer to organize their code in fewer/longer files). I think it could be helpful in other ways too…

What do you think of `partial` types like C# but limited to a file?
https://msdn.microsoft.com/en-us/library/wbx7zzdd.aspx

https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170403/035360.html

···

On Apr 9, 2017, at 7:14 PM, Jonathan Hull via swift-evolution <swift-evolution@swift.org> wrote:

Thanks,
Jon

On Apr 8, 2017, at 5:03 AM, Tino Heth via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Imho there is a simple solution to reach the goals of SE-0169 without breaking compatibility:
Just allow extensions inside type declarations.

class MyVC: UIViewController {
    private let numberOfSections = 0

    extension: UITableViewDataSource {
        // Skipping the class and assume we want to extend the surrounding type
        func numberOfSections(in tableView: UITableView) -> Int {
            return numberOfSections
        }

        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return 0
        }
    }

    private extension {
        // this would contain everything that shoudn't be visible for other extensios

        var secret: Int = 0

        public extension MyFriendClass {
            // oh, well, I make an exception here for a trustworthy type
            func checkSecret(of controller: MyVC) -> Bool {
                return controller.secret > 0
            }
        }

        private extension {
            // this is so secret, I'm not even allowed to copy it
        }
    }

    public func myMethod() {
        print("This is just a boring method")
    }
}

It has the downside of shifting code to the right (you could as well leave those extension-blocks unindented), but lots of advantages:
- No change for private needed
- It can be nested as much as you like to satisfy even the most absurd desires of encapsulation
- It reminds me on operator definitions inside type declarations
- No change for fileprivate needed (but actually, I think there is very little need to keep fileprivate)

I wish this would only be a joke, but writing the example, I actually started liking the concept (but I have a terrible headache right now which might affect my mind) — so either this receives some feedback, or I might start re-proposing this :wink:

- Tino
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Tino) #6

The one issue I see is sticking that public extension inside a private one. I think you would have to mark ‘secret: Int’ as private instead of the extension itself to allow the effect you are looking for…

I didn't think that much while writing the example, but this one was actually on purpose:
It's stated in the Swift documentation that the default visibility of members in an extension equals the level of the extension — so this use of extensions is also a way to group all public declarations (the other levels as well), and save some keystrokes.


(Tino) #7

I’m not sure that this solves anything meaningful (whether in relation to SE-0169 or more generally), does it? What advantage does this provide over just declaring the protocol conformance and those methods as a direct part of the parent type? This seems like it would just introduce more indentation, and more lines of code, for zero benefit.

Well, I'm not overwhelmingly convinced of this whole "we put same-module stuff into extensions" anyways, so it's debatable wether proposals like SE-0169 have any meaningful effects at all… do you think that conformances in same-file extensions have a real benefit?

If nothing else, nested extensions could save those who actually don't care much about such issues from another breaking change in Swift — and imho it adds consistency:
We can nest types, so why can't we nest extensions?


(David Hart) #8

This struck me as a bit odd at first, but the more I think about it, the more I really like the ability to nest extensions/scopes. The one issue I see is sticking that public extension inside a private one. I think you would have to mark ‘secret: Int’ as private instead of the extension itself to allow the effect you are looking for...

What I ultimately want is the ability to declare storage in extensions in the same submodule. Combining that with fileprivate will allow the same tricks without the indentation (together in their own file). This nesting will help in the mean-time (and would still be useful after for those who prefer to organize their code in fewer/longer files). I think it could be helpful in other ways too…

What do you think of `partial` types like C# but limited to a file?
https://msdn.microsoft.com/en-us/library/wbx7zzdd.aspx

https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170403/035360.html

That's the direction the new proposal (0169) is going towards with extensions in the same file.

···

On 10 Apr 2017, at 05:08, Jose Cheyo Jimenez via swift-evolution <swift-evolution@swift.org> wrote:

On Apr 9, 2017, at 7:14 PM, Jonathan Hull via swift-evolution <swift-evolution@swift.org> wrote:

Thanks,
Jon

On Apr 8, 2017, at 5:03 AM, Tino Heth via swift-evolution <swift-evolution@swift.org> wrote:

Imho there is a simple solution to reach the goals of SE-0169 without breaking compatibility:
Just allow extensions inside type declarations.

class MyVC: UIViewController {
    private let numberOfSections = 0

    extension: UITableViewDataSource {
        // Skipping the class and assume we want to extend the surrounding type
        func numberOfSections(in tableView: UITableView) -> Int {
            return numberOfSections
        }

        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return 0
        }
    }

    private extension {
        // this would contain everything that shoudn't be visible for other extensios

        var secret: Int = 0

        public extension MyFriendClass {
            // oh, well, I make an exception here for a trustworthy type
            func checkSecret(of controller: MyVC) -> Bool {
                return controller.secret > 0
            }
        }

        private extension {
            // this is so secret, I'm not even allowed to copy it
        }
    }

    public func myMethod() {
        print("This is just a boring method")
    }
}

It has the downside of shifting code to the right (you could as well leave those extension-blocks unindented), but lots of advantages:
- No change for private needed
- It can be nested as much as you like to satisfy even the most absurd desires of encapsulation
- It reminds me on operator definitions inside type declarations
- No change for fileprivate needed (but actually, I think there is very little need to keep fileprivate)

I wish this would only be a joke, but writing the example, I actually started liking the concept (but I have a terrible headache right now which might affect my mind) — so either this receives some feedback, or I might start re-proposing this :wink:

- Tino
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Matthew Johnson) #9

I’m not sure that this solves anything meaningful (whether in relation to SE-0169 or more generally), does it? What advantage does this provide over just declaring the protocol conformance and those methods as a direct part of the parent type? This seems like it would just introduce more indentation, and more lines of code, for zero benefit.

Well, I'm not overwhelmingly convinced of this whole "we put same-module stuff into extensions" anyways, so it's debatable wether proposals like SE-0169 have any meaningful effects at all… do you think that conformances in same-file extensions have a real benefit?

I think the primary benefit is organizational. People like having the members that implement a conformance grouped together with the conformance declaration.

···

On Apr 10, 2017, at 10:26 AM, Tino Heth via swift-evolution <swift-evolution@swift.org> wrote:

If nothing else, nested extensions could save those who actually don't care much about such issues from another breaking change in Swift — and imho it adds consistency:
We can nest types, so why can't we nest extensions?
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Tony Allevato) #10

I’m not sure that this solves anything meaningful (whether in relation to
SE-0169 or more generally), does it? What advantage does this provide over
just declaring the protocol conformance and those methods as a direct part
of the parent type? This seems like it would just introduce more
indentation, and more lines of code, for zero benefit.

Well, I'm not overwhelmingly convinced of this whole "we put same-module
stuff into extensions" anyways, so it's debatable wether proposals like
SE-0169 have any meaningful effects at all… do you think that conformances
in same-file extensions have a real benefit?

Yes—as Matthew already stated, it's mostly organizational, but the
flexibility is nice to have. I like being able to group functionality of a
type not solely within a single set of curly braces or a single file, but
sometimes also into separate files if the situation calls for it.

For example, in Swift protocol buffers we have a handful of types that are
called "well-known types" that are generated from their .proto file, but to
which we also add a number of convenience initializers/methods. Since the
type itself is generated, extensions in separate files let us do this
without having to hack the generator with special cases to inline the code
into the same file.

But even outside the generated code use cases, it's nice to just be able to
implement helpers or additional "convenience" conformances in separate
files named appropriately (like "Type+Protocol.swift" or
"Type+Helpers.swift"). I find it makes my codebase easier to navigate.

If nothing else, nested extensions could save those who actually don't
care much about such issues from another breaking change in Swift — and
imho it adds consistency:
We can nest types, so why can't we nest extensions?

Because types and extensions are quite different beasts, so something that
applies to one doesn't necessarily apply to the other. Nesting extensions
as you described would seem to be not much different than just flattening
the extension's contents into the type directly or moving them out to
file-level, with the only difference being that it adds a new scope for the
purposes of visibility or getting something like "friend" in C++ (but your
example is even more fine-grained than that).

I don't think that holds its weight. This feels like another case of "let's
try to satisfy everyone who's unhappy with some part of Swift visibility by
changing a completely different feature to make things fall into place",
which I don't think is a sound motivation or design principle. The example
you posted in your initial message weaves multiple types/nesting levels
together in a way that looks *incredibly* difficult to follow/parse to even
an experienced user of the language.

Everyone seems to be striving for a "perfect" level of access control that
lets individual types/members dictate precisely what other types/members
can access them. I'm not sure if that perfection is attainable or not, but
even if it is, I don't think it's something we should strive for. I'd
rather have a simple visibility model that leaks a little than an air-tight
model that allows people to write overly complicated code for the sake of
fine-tuning access.

Let's remember that the core team has limited resources to implement the
things we propose, and if I have to choose between, say, serialization,
reflection, asynchronous constructs, and rehashing visibility levels yet
again, it's clear to me which one I would want dropped on the floor. I
don't want perfect to be the enemy of good.

···

On Mon, Apr 10, 2017 at 8:26 AM Tino Heth via swift-evolution < swift-evolution@swift.org> wrote:

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Tino) #11

What do you think of `partial` types like C# but limited to a file?

Well, imho it would be better than some alternatives, because it might lay the ground for something that is more useful than current same-file extensions, which offer no guarantee that the extension declaring the conformance adds anything to fulfil them (and because of retroactive conformance, I don't think this will be changed for extensions).

If private isn't restricted to a single scope anymore, imho all the splitting has no practical benefits at all, and even if we keep the old definition, I doubt that it's worth the increased complexity:
A //MARK-comment is much more useful than an extension, and like many developers, I prefer to keep instance variables grouped in a prominent place (above the methods), so most likely wouldn't use the "special power" of partial.


(Tino) #12

But even outside the generated code use cases, it's nice to just be able to implement helpers or additional "convenience" conformances in separate files named appropriately (like "Type+Protocol.swift" or "Type+Helpers.swift"). I find it makes my codebase easier to navigate.

No doubt about the usefulness of having separate files with extensions here

If nothing else, nested extensions could save those who actually don't care much about such issues from another breaking change in Swift — and imho it adds consistency:
We can nest types, so why can't we nest extensions?

Because types and extensions are quite different beasts, so something that applies to one doesn't necessarily apply to the other.

I don't buy this argument at all without an objective explanation why the curly braces of extensions should be treated different than the curly braces of types...

I don't think that holds its weight. This feels like another case of "let's try to satisfy everyone who's unhappy with some part of Swift visibility by changing a completely different feature to make things fall into place", which I don't think is a sound motivation or design principle. The example you posted in your initial message weaves multiple types/nesting levels together in a way that looks *incredibly* difficult to follow/parse to even an experienced user of the language.

Did you noticed that I started this example as mockery? In real life, I would hopefully never nest more than once… and do you think sprinkling parts of class over the project is easier to follow?

Everyone seems to be striving for a "perfect" level of access control that lets individual types/members dictate precisely what other types/members can access them. I'm not sure if that perfection is attainable or not, but even if it is, I don't think it's something we should strive for. I'd rather have a simple visibility model that leaks a little than an air-tight model that allows people to write overly complicated code for the sake of fine-tuning access.

I had no desire to change the model of Swift 2 — but apparently, others thought it wasn't sufficient, and I'd rather prefer a conceptually simple model like nesting over a complicated one with less power.

Let's remember that the core team has limited resources to implement the things we propose, and if I have to choose between, say, serialization, reflection, asynchronous constructs, and rehashing visibility levels yet again, it's clear to me which one I would want dropped on the floor. I don't want perfect to be the enemy of good.

Well, right now, there are several (at least one :wink: proposals that aim for a breaking change of the whole model… nested extensions break nothing, so it can be delayed for as long as the core team likes, without causing any trouble.


(Jean-Daniel) #13

I don’t see how SE-0169 do that more than any other meaning private got until now. This was already the case with the initial meaning of private, and was the case with fileprivate.

And for file splitting and visibility control, we need submodules. Until then, if this proposal is to define the ultimate meaning of private, I rather like this meaning that the SE-0025 one.

···

Le 10 avr. 2017 à 07:15, David Hart via swift-evolution <swift-evolution@swift.org> a écrit :

On 10 Apr 2017, at 05:08, Jose Cheyo Jimenez via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Apr 9, 2017, at 7:14 PM, Jonathan Hull via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

This struck me as a bit odd at first, but the more I think about it, the more I really like the ability to nest extensions/scopes. The one issue I see is sticking that public extension inside a private one. I think you would have to mark ‘secret: Int’ as private instead of the extension itself to allow the effect you are looking for...

What I ultimately want is the ability to declare storage in extensions in the same submodule. Combining that with fileprivate will allow the same tricks without the indentation (together in their own file). This nesting will help in the mean-time (and would still be useful after for those who prefer to organize their code in fewer/longer files). I think it could be helpful in other ways too…

What do you think of `partial` types like C# but limited to a file?
https://msdn.microsoft.com/en-us/library/wbx7zzdd.aspx

https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170403/035360.html

That's the direction the new proposal (0169) is going towards with extensions in the same file.


(Chéyo Jiménez) #14

But even outside the generated code use cases, it's nice to just be able to implement helpers or additional "convenience" conformances in separate files named appropriately (like "Type+Protocol.swift" or "Type+Helpers.swift"). I find it makes my codebase easier to navigate.

No doubt about the usefulness of having separate files with extensions here

If nothing else, nested extensions could save those who actually don't care much about such issues from another breaking change in Swift — and imho it adds consistency:
We can nest types, so why can't we nest extensions?

Because types and extensions are quite different beasts, so something that applies to one doesn't necessarily apply to the other.

I don't buy this argument at all without an objective explanation why the curly braces of extensions should be treated different than the curly braces of types…

Extensions are not Partials.

I don't think that holds its weight. This feels like another case of "let's try to satisfy everyone who's unhappy with some part of Swift visibility by changing a completely different feature to make things fall into place", which I don't think is a sound motivation or design principle. The example you posted in your initial message weaves multiple types/nesting levels together in a way that looks *incredibly* difficult to follow/parse to even an experienced user of the language.

Did you noticed that I started this example as mockery? In real life, I would hopefully never nest more than once… and do you think sprinkling parts of class over the project is easier to follow?

Extensions are not Partials.

Everyone seems to be striving for a "perfect" level of access control that lets individual types/members dictate precisely what other types/members can access them. I'm not sure if that perfection is attainable or not, but even if it is, I don't think it's something we should strive for. I'd rather have a simple visibility model that leaks a little than an air-tight model that allows people to write overly complicated code for the sake of fine-tuning access.

I had no desire to change the model of Swift 2 — but apparently, others thought it wasn't sufficient, and I'd rather prefer a conceptually simple model like nesting over a complicated one with less power.

Let's remember that the core team has limited resources to implement the things we propose, and if I have to choose between, say, serialization, reflection, asynchronous constructs, and rehashing visibility levels yet again, it's clear to me which one I would want dropped on the floor. I don't want perfect to be the enemy of good.

Well, right now, there are several (at least one :wink: proposals that aim for a breaking change of the whole model… nested extensions break nothing, so it can be delayed for as long as the core team likes, without causing any trouble.

Partials limited to the same scope can do the same with out having to give extension special nesting powers :slight_smile:

···

On Apr 10, 2017, at 9:49 AM, Tino Heth via swift-evolution <swift-evolution@swift.org> wrote:
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Tony Allevato) #15

But even outside the generated code use cases, it's nice to just be able
to implement helpers or additional "convenience" conformances in separate
files named appropriately (like "Type+Protocol.swift" or
"Type+Helpers.swift"). I find it makes my codebase easier to navigate.

No doubt about the usefulness of having separate files with extensions here

If nothing else, nested extensions could save those who actually don't
care much about such issues from another breaking change in Swift — and
imho it adds consistency:
We can nest types, so why can't we nest extensions?

Because types and extensions are quite different beasts, so something that
applies to one doesn't necessarily apply to the other.

I don't buy this argument at all without an objective explanation why the
curly braces of extensions should be treated different than the curly
braces of types...

They shouldn't be. That's why I don't support SE-0169 either, because it
would allow extensions to extend the *scope* rather than the *type*, but
only within the same file. I think that's fundamentally broken.

But my comment wasn't about curly braces—it was about types vs. extensions.
For example, you can declare local types within a function, but you can't
extend a type within a function (nor do I think it would be a good idea).

I don't think that holds its weight. This feels like another case of
"let's try to satisfy everyone who's unhappy with some part of Swift
visibility by changing a completely different feature to make things fall
into place", which I don't think is a sound motivation or design principle.
The example you posted in your initial message weaves multiple
types/nesting levels together in a way that looks *incredibly* difficult to
follow/parse to even an experienced user of the language.

Did you noticed that I started this example as mockery? In real life, I
would hopefully never nest more than once… and do you think sprinkling
parts of class over the project is easier to follow?

Depending on the type, yes. I wouldn't sprinkle the *fundamental/core*
parts of a type across the project, but if there's some kind of "aside"
functionality that doesn't depend on private knowledge of the type, then I
find it to be a nice feature to have. It requires me to have reasonable
names to my source files, but that's not a significant burden.

···

On Mon, Apr 10, 2017 at 9:49 AM Tino Heth <2th@gmx.de> wrote:

Everyone seems to be striving for a "perfect" level of access control that
lets individual types/members dictate precisely what other types/members
can access them. I'm not sure if that perfection is attainable or not, but
even if it is, I don't think it's something we should strive for. I'd
rather have a simple visibility model that leaks a little than an air-tight
model that allows people to write overly complicated code for the sake of
fine-tuning access.

I had no desire to change the model of Swift 2 — but apparently, others
thought it wasn't sufficient, and I'd rather prefer a conceptually simple
model like nesting over a complicated one with less power.

Let's remember that the core team has limited resources to implement the
things we propose, and if I have to choose between, say, serialization,
reflection, asynchronous constructs, and rehashing visibility levels yet
again, it's clear to me which one I would want dropped on the floor. I
don't want perfect to be the enemy of good.

Well, right now, there are several (at least one :wink: proposals that aim
for a breaking change of the whole model… nested extensions break nothing,
so it can be delayed for as long as the core team likes, without causing
any trouble.


(Tino) #16

I don't buy this argument at all without an objective explanation why the curly braces of extensions should be treated different than the curly braces of types…

Extensions are not Partials.

do you think sprinkling parts of class over the project is easier to follow?

Extensions are not Partials.

I can't see how statement and answer(?) are related to the original post… or did I miss that this topic is about partials? :slight_smile:

it can be delayed for as long as the core team likes, without causing any trouble.

Partials limited to the same scope can do the same

That is true… so can we agree that nothing should change now, so that something can be added later? :wink:

with out having to give extension special nesting powers :slight_smile:

I would say there's no doubt that extensions are withhold the common nesting powers of all other, similar constructs in Swift: Classes can be nested, Structs can be nested, Enums can be nested, functions can be nested, protocols… I haven't tried yet, but associated objects are something comparable :wink:


(Ricardo Parada) #17

I have not voted in favor or against the proposal. I have been reading a lot of responses but I agree with Tony.

When I started reading the proposal everything was more or less fine half way through the proposal because it was reverting private to fileprivate between the type and its extensions within the same file. I said, if you think of the type and its extensions as a unit then it makes sense. I can explain that.

Then it started describing a different behavior among the extensions located in a file separate from the file containing the definition of the type. That just started a whole debate inside my head and I understand the passionate responses on both sides.

But then I imagined myself explaining this to someone new to Swift and it just doesn't seem right. If it becomes convoluted then that's a red flag that it does not belong in Swift.

I agree fileprivate may be ugly to some and it may be more popular than private. But I think fileprivate is very clear. I know what it does from its name without having to ask. And private behaves the way private works in other languages.

Regards

···

On Apr 10, 2017, at 1:35 PM, Tony Allevato via swift-evolution <swift-evolution@swift.org> wrote:

On Mon, Apr 10, 2017 at 9:49 AM Tino Heth <2th@gmx.de> wrote:

But even outside the generated code use cases, it's nice to just be able to implement helpers or additional "convenience" conformances in separate files named appropriately (like "Type+Protocol.swift" or "Type+Helpers.swift"). I find it makes my codebase easier to navigate.

No doubt about the usefulness of having separate files with extensions here

If nothing else, nested extensions could save those who actually don't care much about such issues from another breaking change in Swift — and imho it adds consistency:
We can nest types, so why can't we nest extensions?

Because types and extensions are quite different beasts, so something that applies to one doesn't necessarily apply to the other.

I don't buy this argument at all without an objective explanation why the curly braces of extensions should be treated different than the curly braces of types...

They shouldn't be. That's why I don't support SE-0169 either, because it would allow extensions to extend the *scope* rather than the *type*, but only within the same file. I think that's fundamentally broken.

But my comment wasn't about curly braces—it was about types vs. extensions. For example, you can declare local types within a function, but you can't extend a type within a function (nor do I think it would be a good idea).

I don't think that holds its weight. This feels like another case of "let's try to satisfy everyone who's unhappy with some part of Swift visibility by changing a completely different feature to make things fall into place", which I don't think is a sound motivation or design principle. The example you posted in your initial message weaves multiple types/nesting levels together in a way that looks *incredibly* difficult to follow/parse to even an experienced user of the language.

Did you noticed that I started this example as mockery? In real life, I would hopefully never nest more than once… and do you think sprinkling parts of class over the project is easier to follow?

Depending on the type, yes. I wouldn't sprinkle the *fundamental/core* parts of a type across the project, but if there's some kind of "aside" functionality that doesn't depend on private knowledge of the type, then I find it to be a nice feature to have. It requires me to have reasonable names to my source files, but that's not a significant burden.

Everyone seems to be striving for a "perfect" level of access control that lets individual types/members dictate precisely what other types/members can access them. I'm not sure if that perfection is attainable or not, but even if it is, I don't think it's something we should strive for. I'd rather have a simple visibility model that leaks a little than an air-tight model that allows people to write overly complicated code for the sake of fine-tuning access.

I had no desire to change the model of Swift 2 — but apparently, others thought it wasn't sufficient, and I'd rather prefer a conceptually simple model like nesting over a complicated one with less power.

Let's remember that the core team has limited resources to implement the things we propose, and if I have to choose between, say, serialization, reflection, asynchronous constructs, and rehashing visibility levels yet again, it's clear to me which one I would want dropped on the floor. I don't want perfect to be the enemy of good.

Well, right now, there are several (at least one :wink: proposals that aim for a breaking change of the whole model… nested extensions break nothing, so it can be delayed for as long as the core team likes, without causing any trouble.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(David Hart) #18

This struck me as a bit odd at first, but the more I think about it, the more I really like the ability to nest extensions/scopes. The one issue I see is sticking that public extension inside a private one. I think you would have to mark ‘secret: Int’ as private instead of the extension itself to allow the effect you are looking for...

What I ultimately want is the ability to declare storage in extensions in the same submodule. Combining that with fileprivate will allow the same tricks without the indentation (together in their own file). This nesting will help in the mean-time (and would still be useful after for those who prefer to organize their code in fewer/longer files). I think it could be helpful in other ways too…

What do you think of `partial` types like C# but limited to a file?
https://msdn.microsoft.com/en-us/library/wbx7zzdd.aspx

https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170403/035360.html

That's the direction the new proposal (0169) is going towards with extensions in the same file.

I don’t see how SE-0169 do that more than any other meaning private got until now. This was already the case with the initial meaning of private, and was the case with fileprivate.

The current semantics of private don’t give any support for partial types like in C# because the accessibility is restricted to the current scope. With SE-0169’s private, extensions in the same file as the type share that scope. Plus, the Alternatives Considered section of the proposal discusses potential future directions where those extensions could look even more like C# partials :slight_smile:

···

On 10 Apr 2017, at 08:21, Jean-Daniel <mailing@xenonium.com> wrote:

Le 10 avr. 2017 à 07:15, David Hart via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> a écrit :
On 10 Apr 2017, at 05:08, Jose Cheyo Jimenez via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Apr 9, 2017, at 7:14 PM, Jonathan Hull via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

And for file splitting and visibility control, we need submodules. Until then, if this proposal is to define the ultimate meaning of private, I rather like this meaning that the SE-0025 one.


(Chéyo Jiménez) #19

I don't buy this argument at all without an objective explanation why the curly braces of extensions should be treated different than the curly braces of types…

Extensions are not Partials.

do you think sprinkling parts of class over the project is easier to follow?

Extensions are not Partials.

I can't see how statement and answer(?) are related to the original post… or did I miss that this topic is about partials? :slight_smile:

I am partial to partials. :slight_smile:

it can be delayed for as long as the core team likes, without causing any trouble.

Partials limited to the same scope can do the same

That is true… so can we agree that nothing should change now, so that something can be added later? :wink:

Same page.

···

On Apr 10, 2017, at 10:22 AM, Tino Heth <2th@gmx.de> wrote:

with out having to give extension special nesting powers :slight_smile:

I would say there's no doubt that extensions are withhold the common nesting powers of all other, similar constructs in Swift: Classes can be nested, Structs can be nested, Enums can be nested, functions can be nested, protocols… I haven't tried yet, but associated objects are something comparable :wink:


(David Hart) #20

I have not voted in favor or against the proposal. I have been reading a lot of responses but I agree with Tony.

When I started reading the proposal everything was more or less fine half way through the proposal because it was reverting private to fileprivate between the type and its extensions within the same file. I said, if you think of the type and its extensions as a unit then it makes sense. I can explain that.

Then it started describing a different behavior among the extensions located in a file separate from the file containing the definition of the type. That just started a whole debate inside my head and I understand the passionate responses on both sides.

But then I imagined myself explaining this to someone new to Swift and it just doesn't seem right. If it becomes convoluted then that's a red flag that it does not belong in Swift.

I understand what you are saying and I wouldn't be against relaxing that requirement (not talking for Chris here).

The model would change from "Types share scopes with their extensions in the same file the type was defined" to "Types and their extensions share the same scope in each file".

···

Sent from my iPhone

On 11 Apr 2017, at 01:37, Ricardo Parada via swift-evolution <swift-evolution@swift.org> wrote:

I agree fileprivate may be ugly to some and it may be more popular than private. But I think fileprivate is very clear. I know what it does from its name without having to ask. And private behaves the way private works in other languages.

Regards

On Apr 10, 2017, at 1:35 PM, Tony Allevato via swift-evolution <swift-evolution@swift.org> wrote:

On Mon, Apr 10, 2017 at 9:49 AM Tino Heth <2th@gmx.de> wrote:

But even outside the generated code use cases, it's nice to just be able to implement helpers or additional "convenience" conformances in separate files named appropriately (like "Type+Protocol.swift" or "Type+Helpers.swift"). I find it makes my codebase easier to navigate.

No doubt about the usefulness of having separate files with extensions here

If nothing else, nested extensions could save those who actually don't care much about such issues from another breaking change in Swift — and imho it adds consistency:
We can nest types, so why can't we nest extensions?

Because types and extensions are quite different beasts, so something that applies to one doesn't necessarily apply to the other.

I don't buy this argument at all without an objective explanation why the curly braces of extensions should be treated different than the curly braces of types...

They shouldn't be. That's why I don't support SE-0169 either, because it would allow extensions to extend the *scope* rather than the *type*, but only within the same file. I think that's fundamentally broken.

But my comment wasn't about curly braces—it was about types vs. extensions. For example, you can declare local types within a function, but you can't extend a type within a function (nor do I think it would be a good idea).

I don't think that holds its weight. This feels like another case of "let's try to satisfy everyone who's unhappy with some part of Swift visibility by changing a completely different feature to make things fall into place", which I don't think is a sound motivation or design principle. The example you posted in your initial message weaves multiple types/nesting levels together in a way that looks *incredibly* difficult to follow/parse to even an experienced user of the language.

Did you noticed that I started this example as mockery? In real life, I would hopefully never nest more than once… and do you think sprinkling parts of class over the project is easier to follow?

Depending on the type, yes. I wouldn't sprinkle the *fundamental/core* parts of a type across the project, but if there's some kind of "aside" functionality that doesn't depend on private knowledge of the type, then I find it to be a nice feature to have. It requires me to have reasonable names to my source files, but that's not a significant burden.

Everyone seems to be striving for a "perfect" level of access control that lets individual types/members dictate precisely what other types/members can access them. I'm not sure if that perfection is attainable or not, but even if it is, I don't think it's something we should strive for. I'd rather have a simple visibility model that leaks a little than an air-tight model that allows people to write overly complicated code for the sake of fine-tuning access.

I had no desire to change the model of Swift 2 — but apparently, others thought it wasn't sufficient, and I'd rather prefer a conceptually simple model like nesting over a complicated one with less power.

Let's remember that the core team has limited resources to implement the things we propose, and if I have to choose between, say, serialization, reflection, asynchronous constructs, and rehashing visibility levels yet again, it's clear to me which one I would want dropped on the floor. I don't want perfect to be the enemy of good.

Well, right now, there are several (at least one :wink: proposals that aim for a breaking change of the whole model… nested extensions break nothing, so it can be delayed for as long as the core team likes, without causing any trouble.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution