access control proposal


(Ilya Belenkiy) #1

I think the it would help a great deal to have an access level modifier
that is really private and visible only inside the class itself. Right now,
the only way to hide implementation details for a class is to hide the
class code in a separate file, which is very inconvenient for several
reasons:

1) the meaning of the code changes depending on which file the class is in.
It's very easy to accidentally expose class internal details and then call
class elements that are meant to be used only inside the class. Having a
keyword for class internals will allow the compiler to ensure that only the
public API for the class is used from the outside world. The user can check
types on his own, but it's better that the compiler does it automatically.
Similarly, the user can check that only the proper APIs are called, but
it's better that the compiler does it automatically.

2) accessibility by file structure may cause some really short files.

3) It's impossible to group related classes in one file but still hide
implementation details inside each class

I think that it the best solution is to make private keyword do what it
states -- keep the class element private to the class. But if it's really
important to have a separate keyword for backward compatibility, it would
be the next best thing.

···

--
Ilya Belenkiy


(Nikolai Vazquez) #2

I agree that there should be an access level that hides implementation
details from other types in the same file. However, it shouldn’t replace
private, because 1) helper types might benefit from private elements and 2)
like you said, backwards compatibility.

I think the it would help a great deal to have an access level modifier

that is really private and visible only inside the class itself. Right now,
the only way to hide implementation details for a class is to hide the
class code in a separate file, which is very inconvenient for several
reasons:

1) the meaning of the code changes depending on which file the class is
in. It's very easy to accidentally expose class internal details and then
call class elements that are meant to be used only inside the class. Having
a keyword for class internals will allow the compiler to ensure that only
the public API for the class is used from the outside world. The user can
check types on his own, but it's better that the compiler does it
automatically. Similarly, the user can check that only the proper APIs are
called, but it's better that the compiler does it automatically.

2) accessibility by file structure may cause some really short files.

3) It's impossible to group related classes in one file but still hide
implementation details inside each class

I think that it the best solution is to make private keyword do what it
states -- keep the class element private to the class. But if it's really
important to have a separate keyword for backward compatibility, it would
be the next best thing.

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

···

On Sat, Dec 5, 2015 at 11:40 PM Ilya via swift-evolution < swift-evolution@swift.org> wrote:


(John McCall) #3

But on the flip side, with your proposed semantics for private, it would be impossible to write a group of related types, functions, and extensions that do need to refer to each other’s internal details without exposing those details to the entire module. That’s not really acceptable.

The Swift language rule encourages you to put independent definitions in different files. That definitely means that, if you want to enforce very tight separation of concerns, you’ll end up with more and smaller files. You haven’t explained why that’s really a *problem*, though.

John.

···

On Dec 5, 2015, at 8:39 PM, Ilya via swift-evolution <swift-evolution@swift.org> wrote:

I think the it would help a great deal to have an access level modifier that is really private and visible only inside the class itself. Right now, the only way to hide implementation details for a class is to hide the class code in a separate file, which is very inconvenient for several reasons:

1) the meaning of the code changes depending on which file the class is in. It's very easy to accidentally expose class internal details and then call class elements that are meant to be used only inside the class. Having a keyword for class internals will allow the compiler to ensure that only the public API for the class is used from the outside world. The user can check types on his own, but it's better that the compiler does it automatically. Similarly, the user can check that only the proper APIs are called, but it's better that the compiler does it automatically.

2) accessibility by file structure may cause some really short files.

3) It's impossible to group related classes in one file but still hide implementation details inside each class

I think that it the best solution is to make private keyword do what it states -- keep the class element private to the class. But if it's really important to have a separate keyword for backward compatibility, it would be the next best thing.


(David Owens II) #4

I tend to disagree with this whole concept of access modifiers; what we have today is at least somewhat sane and consistent across all constructs.

As for your example, if other code within your file is leveraging these “private” pieces, doesn’t that suggest that your API model is already wrong? After all, those pieces wouldn’t be used if they weren’t needed. I’m also hard pressed to believe that this is solving a problem that isn’t purely academic.

I’d actually prefer the opposite extreme: I want everything public unless it’s prefixed with an _. To me, the _ prefix adds significantly more contextual awareness that I’m venturing into parts of the construct that are not intended for general use. It has the add benefit that it makes these types of uses grepable within the codebase so audits are quite trivial.

    struct F {
        func _privateUsage() {}
        func publicUsage() {}
    }

Right now, I find having to prefix nearly everything with public is extremely annoying.

Humorously enough, I’m actually running into issues with this right now. I’m looking into fixing some of the NSNumber functionality in corelib and the fact that some of the internal state is marked as private means it’s not readably testable nor easy to inspect to validate is doing the right thing.

-David

···

On Dec 5, 2015, at 9:04 PM, Nikolai Vazquez via swift-evolution <swift-evolution@swift.org> wrote:

I agree that there should be an access level that hides implementation details from other types in the same file. However, it shouldn’t replace private, because 1) helper types might benefit from private elements and 2) like you said, backwards compatibility.

On Sat, Dec 5, 2015 at 11:40 PM Ilya via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I think the it would help a great deal to have an access level modifier that is really private and visible only inside the class itself. Right now, the only way to hide implementation details for a class is to hide the class code in a separate file, which is very inconvenient for several reasons:

1) the meaning of the code changes depending on which file the class is in. It's very easy to accidentally expose class internal details and then call class elements that are meant to be used only inside the class. Having a keyword for class internals will allow the compiler to ensure that only the public API for the class is used from the outside world. The user can check types on his own, but it's better that the compiler does it automatically. Similarly, the user can check that only the proper APIs are called, but it's better that the compiler does it automatically.

2) accessibility by file structure may cause some really short files.

3) It's impossible to group related classes in one file but still hide implementation details inside each class

I think that it the best solution is to make private keyword do what it states -- keep the class element private to the class. But if it's really important to have a separate keyword for backward compatibility, it would be the next best thing.

--
Ilya Belenkiy
_______________________________________________
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


(Lily Ballard) #5

You can already use a _ prefix today to mark any function/property that
is not meant for general use, even within the confines of the file.
That's what I do; private methods/properties are fair game (if
accessible), but anything that's considered an implementation detail
gets a _ prefix. Applying your proposed rule would actually remove the
ability to use _ to distinguish things like this (and you'd start seeing
__ instead, which is even uglier).

-Kevin Ballard

···

On Sat, Dec 5, 2015, at 10:59 PM, David Owens II via swift-evolution wrote:

I’d actually prefer the opposite extreme: I want everything public unless it’s prefixed with an _. To me, the _ prefix adds significantly more contextual awareness that I’m venturing into parts of the construct that are not intended for general use. It has the add benefit that it makes these types of uses grepable within the codebase so audits are quite trivial.


(Ilya Belenkiy) #6

My main proposal was not to change the semantics of private (although I
would like that) but to introduce a way to keep class implementation
details inaccessible to anything outside the class. I think that it should
still be possible and useful to have the current level of sharing (I would
just name it differently, given what private usually means in other
languages).

Just as it is convenient to group several related classes that can refer to
each other's implementation details, it is very convenient to have several
classes that don't do this but are still related in other important way,
for example related APIs or classes that are based on the same
implementation idea (like array based data structures).

Having all code in one place rather than jumping through many small files
is a very nice thing to have because it really helps to keep everything
consistent. The more manual work people have to do for consistency, the
more likelihood that it won't be done.

···

--
Ilya Belenkiy
On Mon, Dec 7, 2015 at 12:21 AM John McCall <rjmccall@apple.com> wrote:

> On Dec 5, 2015, at 8:39 PM, Ilya via swift-evolution < > swift-evolution@swift.org> wrote:
>
> I think the it would help a great deal to have an access level modifier
that is really private and visible only inside the class itself. Right now,
the only way to hide implementation details for a class is to hide the
class code in a separate file, which is very inconvenient for several
reasons:
>
> 1) the meaning of the code changes depending on which file the class is
in. It's very easy to accidentally expose class internal details and then
call class elements that are meant to be used only inside the class. Having
a keyword for class internals will allow the compiler to ensure that only
the public API for the class is used from the outside world. The user can
check types on his own, but it's better that the compiler does it
automatically. Similarly, the user can check that only the proper APIs are
called, but it's better that the compiler does it automatically.
>
> 2) accessibility by file structure may cause some really short files.
>
> 3) It's impossible to group related classes in one file but still hide
implementation details inside each class
>
> I think that it the best solution is to make private keyword do what it
states -- keep the class element private to the class. But if it's really
important to have a separate keyword for backward compatibility, it would
be the next best thing.

But on the flip side, with your proposed semantics for private, it would
be impossible to write a group of related types, functions, and extensions
that do need to refer to each other’s internal details without exposing
those details to the entire module. That’s not really acceptable.

The Swift language rule encourages you to put independent definitions in
different files. That definitely means that, if you want to enforce very
tight separation of concerns, you’ll end up with more and smaller files.
You haven’t explained why that’s really a *problem*, though.

John.


(Ilya Belenkiy) #7

Also, one problem with the current approach is that it's all or nothing.
The classes in one file see everything from the other classes, and it may
be useful to limit that and share only some additional APIs with those
related classes, but not all of the implementation details / internal
state, while still hiding those same APIs from unrelated classes.
Currently, there is no way of doing it, even when splitting code into
separate files (the class state must be all in one place and can't be in an
extension).

···

--
Ilya Belenkiy
On Mon, Dec 7, 2015 at 8:17 AM Ilya <ilya@harmonicsense.com> wrote:

My main proposal was not to change the semantics of private (although I
would like that) but to introduce a way to keep class implementation
details inaccessible to anything outside the class. I think that it should
still be possible and useful to have the current level of sharing (I would
just name it differently, given what private usually means in other
languages).

Just as it is convenient to group several related classes that can refer
to each other's implementation details, it is very convenient to have
several classes that don't do this but are still related in other important
way, for example related APIs or classes that are based on the same
implementation idea (like array based data structures).

Having all code in one place rather than jumping through many small files
is a very nice thing to have because it really helps to keep everything
consistent. The more manual work people have to do for consistency, the
more likelihood that it won't be done.

--
Ilya Belenkiy
On Mon, Dec 7, 2015 at 12:21 AM John McCall <rjmccall@apple.com> wrote:

> On Dec 5, 2015, at 8:39 PM, Ilya via swift-evolution < >> swift-evolution@swift.org> wrote:
>
> I think the it would help a great deal to have an access level modifier
that is really private and visible only inside the class itself. Right now,
the only way to hide implementation details for a class is to hide the
class code in a separate file, which is very inconvenient for several
reasons:
>
> 1) the meaning of the code changes depending on which file the class is
in. It's very easy to accidentally expose class internal details and then
call class elements that are meant to be used only inside the class. Having
a keyword for class internals will allow the compiler to ensure that only
the public API for the class is used from the outside world. The user can
check types on his own, but it's better that the compiler does it
automatically. Similarly, the user can check that only the proper APIs are
called, but it's better that the compiler does it automatically.
>
> 2) accessibility by file structure may cause some really short files.
>
> 3) It's impossible to group related classes in one file but still hide
implementation details inside each class
>
> I think that it the best solution is to make private keyword do what it
states -- keep the class element private to the class. But if it's really
important to have a separate keyword for backward compatibility, it would
be the next best thing.

But on the flip side, with your proposed semantics for private, it would
be impossible to write a group of related types, functions, and extensions
that do need to refer to each other’s internal details without exposing
those details to the entire module. That’s not really acceptable.

The Swift language rule encourages you to put independent definitions in
different files. That definitely means that, if you want to enforce very
tight separation of concerns, you’ll end up with more and smaller files.
You haven’t explained why that’s really a *problem*, though.

John.


(plx) #8

If such an extra-private access-control level (`classified`?) existed, how would it be intended to behave in snippets like below?

    private class Example {
      classified var data: TopSecretData
    }

    extension Example: Equatable {
    }

    func ==(lhs: Example, rhs: Example) -> Bool {
      return lhs.data == rhs.data
      // ^ ??? possible or not?
    }

…(assuming the rest of the language largely behaves as-before).

When such `classified` properties behave like values you could perhaps declare them as `private classified(set) var` but that wouldn’t really add much safety when they behave like references.

···

On Dec 7, 2015, at 7:45 AM, Ilya via swift-evolution <swift-evolution@swift.org> wrote:

Also, one problem with the current approach is that it's all or nothing. The classes in one file see everything from the other classes, and it may be useful to limit that and share only some additional APIs with those related classes, but not all of the implementation details / internal state, while still hiding those same APIs from unrelated classes. Currently, there is no way of doing it, even when splitting code into separate files (the class state must be all in one place and can't be in an extension).

--
Ilya Belenkiy
On Mon, Dec 7, 2015 at 8:17 AM Ilya <ilya@harmonicsense.com <mailto:ilya@harmonicsense.com>> wrote:
My main proposal was not to change the semantics of private (although I would like that) but to introduce a way to keep class implementation details inaccessible to anything outside the class. I think that it should still be possible and useful to have the current level of sharing (I would just name it differently, given what private usually means in other languages).

Just as it is convenient to group several related classes that can refer to each other's implementation details, it is very convenient to have several classes that don't do this but are still related in other important way, for example related APIs or classes that are based on the same implementation idea (like array based data structures).

Having all code in one place rather than jumping through many small files is a very nice thing to have because it really helps to keep everything consistent. The more manual work people have to do for consistency, the more likelihood that it won't be done.

--
Ilya Belenkiy
On Mon, Dec 7, 2015 at 12:21 AM John McCall <rjmccall@apple.com <mailto:rjmccall@apple.com>> wrote:

> On Dec 5, 2015, at 8:39 PM, Ilya via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>
> I think the it would help a great deal to have an access level modifier that is really private and visible only inside the class itself. Right now, the only way to hide implementation details for a class is to hide the class code in a separate file, which is very inconvenient for several reasons:
>
> 1) the meaning of the code changes depending on which file the class is in. It's very easy to accidentally expose class internal details and then call class elements that are meant to be used only inside the class. Having a keyword for class internals will allow the compiler to ensure that only the public API for the class is used from the outside world. The user can check types on his own, but it's better that the compiler does it automatically. Similarly, the user can check that only the proper APIs are called, but it's better that the compiler does it automatically.
>
> 2) accessibility by file structure may cause some really short files.
>
> 3) It's impossible to group related classes in one file but still hide implementation details inside each class
>
> I think that it the best solution is to make private keyword do what it states -- keep the class element private to the class. But if it's really important to have a separate keyword for backward compatibility, it would be the next best thing.

But on the flip side, with your proposed semantics for private, it would be impossible to write a group of related types, functions, and extensions that do need to refer to each other’s internal details without exposing those details to the entire module. That’s not really acceptable.

The Swift language rule encourages you to put independent definitions in different files. That definitely means that, if you want to enforce very tight separation of concerns, you’ll end up with more and smaller files. You haven’t explained why that’s really a *problem*, though.

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


(Matthew Johnson) #9

I was not sure how I felt about Swift's access control when it was first announced but it didn't take long for me to believe it strikes a pretty good balance between complexity and ability to hide implementation details.

It follows a very straightforward scope-driven strategy. If it is extended further I would like to see any enhancements follow the same scope-driven strategy rather than being type-driven as is seen in other languages. Proposals along these lines might be interesting to consider and might be able to accomplish what you are hoping to accomplish while affording additional flexibility.

In a language where distributing the implementation of a type across several extensions sometimes in different files a type-driven access control model doesn't make a lot of sense to me. I think it has a lot of potential to be confusing.

What would it mean to limit access to a member to the type itself in Swift? Would an extensions in the same (or different) files be able to see the member? What about extensions in a different module? And what about subclasses? Subclasses probably wouldn't have visibility to them, but any discussion of something like this will probably lead to discussion of protected as well.

···

Sent from my iPad

On Dec 7, 2015, at 7:45 AM, Ilya via swift-evolution <swift-evolution@swift.org> wrote:

Also, one problem with the current approach is that it's all or nothing. The classes in one file see everything from the other classes, and it may be useful to limit that and share only some additional APIs with those related classes, but not all of the implementation details / internal state, while still hiding those same APIs from unrelated classes. Currently, there is no way of doing it, even when splitting code into separate files (the class state must be all in one place and can't be in an extension).

--
Ilya Belenkiy

On Mon, Dec 7, 2015 at 8:17 AM Ilya <ilya@harmonicsense.com> wrote:
My main proposal was not to change the semantics of private (although I would like that) but to introduce a way to keep class implementation details inaccessible to anything outside the class. I think that it should still be possible and useful to have the current level of sharing (I would just name it differently, given what private usually means in other languages).

Just as it is convenient to group several related classes that can refer to each other's implementation details, it is very convenient to have several classes that don't do this but are still related in other important way, for example related APIs or classes that are based on the same implementation idea (like array based data structures).

Having all code in one place rather than jumping through many small files is a very nice thing to have because it really helps to keep everything consistent. The more manual work people have to do for consistency, the more likelihood that it won't be done.

--
Ilya Belenkiy

On Mon, Dec 7, 2015 at 12:21 AM John McCall <rjmccall@apple.com> wrote:

> On Dec 5, 2015, at 8:39 PM, Ilya via swift-evolution <swift-evolution@swift.org> wrote:
>
> I think the it would help a great deal to have an access level modifier that is really private and visible only inside the class itself. Right now, the only way to hide implementation details for a class is to hide the class code in a separate file, which is very inconvenient for several reasons:
>
> 1) the meaning of the code changes depending on which file the class is in. It's very easy to accidentally expose class internal details and then call class elements that are meant to be used only inside the class. Having a keyword for class internals will allow the compiler to ensure that only the public API for the class is used from the outside world. The user can check types on his own, but it's better that the compiler does it automatically. Similarly, the user can check that only the proper APIs are called, but it's better that the compiler does it automatically.
>
> 2) accessibility by file structure may cause some really short files.
>
> 3) It's impossible to group related classes in one file but still hide implementation details inside each class
>
> I think that it the best solution is to make private keyword do what it states -- keep the class element private to the class. But if it's really important to have a separate keyword for backward compatibility, it would be the next best thing.

But on the flip side, with your proposed semantics for private, it would be impossible to write a group of related types, functions, and extensions that do need to refer to each other’s internal details without exposing those details to the entire module. That’s not really acceptable.

The Swift language rule encourages you to put independent definitions in different files. That definitely means that, if you want to enforce very tight separation of concerns, you’ll end up with more and smaller files. You haven’t explained why that’s really a *problem*, though.

John.

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


(Ilya Belenkiy) #10

Classified is a nice name for this.

I think that it would not be accessible from extensions (otherwise it would
be easy to break into the internals that the class wants to make
inaccessible)

···

--
Ilya Belenkiy

On Mon, Dec 7, 2015 at 9:25 AM plx <plxgithub@gmail.com> wrote:

If such an extra-private access-control level (`classified`?) existed, how
would it be intended to behave in snippets like below?

    private class Example {
      classified var data: TopSecretData
    }

    extension Example: Equatable {
    }

    func ==(lhs: Example, rhs: Example) -> Bool {
      return lhs.data == rhs.data
      // ^ ??? possible or not?
    }

…(assuming the rest of the language largely behaves as-before).

When such `classified` properties behave like values you could perhaps
declare them as `private classified(set) var` but that wouldn’t really add
much safety when they behave like references.

On Dec 7, 2015, at 7:45 AM, Ilya via swift-evolution < > swift-evolution@swift.org> wrote:

Also, one problem with the current approach is that it's all or nothing.
The classes in one file see everything from the other classes, and it may
be useful to limit that and share only some additional APIs with those
related classes, but not all of the implementation details / internal
state, while still hiding those same APIs from unrelated classes.
Currently, there is no way of doing it, even when splitting code into
separate files (the class state must be all in one place and can't be in an
extension).

--
Ilya Belenkiy
On Mon, Dec 7, 2015 at 8:17 AM Ilya <ilya@harmonicsense.com> wrote:

My main proposal was not to change the semantics of private (although I
would like that) but to introduce a way to keep class implementation
details inaccessible to anything outside the class. I think that it should
still be possible and useful to have the current level of sharing (I would
just name it differently, given what private usually means in other
languages).

Just as it is convenient to group several related classes that can refer
to each other's implementation details, it is very convenient to have
several classes that don't do this but are still related in other important
way, for example related APIs or classes that are based on the same
implementation idea (like array based data structures).

Having all code in one place rather than jumping through many small files
is a very nice thing to have because it really helps to keep everything
consistent. The more manual work people have to do for consistency, the
more likelihood that it won't be done.

--
Ilya Belenkiy
On Mon, Dec 7, 2015 at 12:21 AM John McCall <rjmccall@apple.com> wrote:

> On Dec 5, 2015, at 8:39 PM, Ilya via swift-evolution < >>> swift-evolution@swift.org> wrote:
>
> I think the it would help a great deal to have an access level
modifier that is really private and visible only inside the class itself.
Right now, the only way to hide implementation details for a class is to
hide the class code in a separate file, which is very inconvenient for
several reasons:
>
> 1) the meaning of the code changes depending on which file the class
is in. It's very easy to accidentally expose class internal details and
then call class elements that are meant to be used only inside the class.
Having a keyword for class internals will allow the compiler to ensure that
only the public API for the class is used from the outside world. The user
can check types on his own, but it's better that the compiler does it
automatically. Similarly, the user can check that only the proper APIs are
called, but it's better that the compiler does it automatically.
>
> 2) accessibility by file structure may cause some really short files.
>
> 3) It's impossible to group related classes in one file but still hide
implementation details inside each class
>
> I think that it the best solution is to make private keyword do what
it states -- keep the class element private to the class. But if it's
really important to have a separate keyword for backward compatibility, it
would be the next best thing.

But on the flip side, with your proposed semantics for private, it would
be impossible to write a group of related types, functions, and extensions
that do need to refer to each other’s internal details without exposing
those details to the entire module. That’s not really acceptable.

The Swift language rule encourages you to put independent definitions in
different files. That definitely means that, if you want to enforce very
tight separation of concerns, you’ll end up with more and smaller files.
You haven’t explained why that’s really a *problem*, though.

John.

_______________________________________________

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


(Ilya Belenkiy) #11

If it is not allowed in extensions or subclasses (and it shouldn't), the
model is still very simple.

I understand the current model, but I think that there is a lot of value in
getting the compiler's help in ensuring that class internals cannot be
broken by anything outside the class.

The current model doesn't solve this problem well. Putting everything in
separate files seems like a very unfortunate workaround.

···

--
Ilya Belenkiy

On Mon, Dec 7, 2015 at 9:41 AM Matthew Johnson <matthew@anandabits.com> wrote:

I was not sure how I felt about Swift's access control when it was first
announced but it didn't take long for me to believe it strikes a pretty
good balance between complexity and ability to hide implementation details.

It follows a very straightforward scope-driven strategy. If it is
extended further I would like to see any enhancements follow the same
scope-driven strategy rather than being type-driven as is seen in other
languages. Proposals along these lines might be interesting to consider
and might be able to accomplish what you are hoping to accomplish while
affording additional flexibility.

In a language where distributing the implementation of a type across
several extensions sometimes in different files a type-driven access
control model doesn't make a lot of sense to me. I think it has a lot of
potential to be confusing.

What would it mean to limit access to a member to the type itself in
Swift? Would an extensions in the same (or different) files be able to see
the member? What about extensions in a different module? And what about
subclasses? Subclasses probably wouldn't have visibility to them, but any
discussion of something like this will probably lead to discussion of
protected as well.

Sent from my iPad

On Dec 7, 2015, at 7:45 AM, Ilya via swift-evolution < > swift-evolution@swift.org> wrote:

Also, one problem with the current approach is that it's all or nothing.
The classes in one file see everything from the other classes, and it may
be useful to limit that and share only some additional APIs with those
related classes, but not all of the implementation details / internal
state, while still hiding those same APIs from unrelated classes.
Currently, there is no way of doing it, even when splitting code into
separate files (the class state must be all in one place and can't be in an
extension).

--
Ilya Belenkiy
On Mon, Dec 7, 2015 at 8:17 AM Ilya <ilya@harmonicsense.com> wrote:

My main proposal was not to change the semantics of private (although I
would like that) but to introduce a way to keep class implementation
details inaccessible to anything outside the class. I think that it should
still be possible and useful to have the current level of sharing (I would
just name it differently, given what private usually means in other
languages).

Just as it is convenient to group several related classes that can refer
to each other's implementation details, it is very convenient to have
several classes that don't do this but are still related in other important
way, for example related APIs or classes that are based on the same
implementation idea (like array based data structures).

Having all code in one place rather than jumping through many small files
is a very nice thing to have because it really helps to keep everything
consistent. The more manual work people have to do for consistency, the
more likelihood that it won't be done.

--
Ilya Belenkiy
On Mon, Dec 7, 2015 at 12:21 AM John McCall <rjmccall@apple.com> wrote:

> On Dec 5, 2015, at 8:39 PM, Ilya via swift-evolution < >>> swift-evolution@swift.org> wrote:
>
> I think the it would help a great deal to have an access level
modifier that is really private and visible only inside the class itself.
Right now, the only way to hide implementation details for a class is to
hide the class code in a separate file, which is very inconvenient for
several reasons:
>
> 1) the meaning of the code changes depending on which file the class
is in. It's very easy to accidentally expose class internal details and
then call class elements that are meant to be used only inside the class.
Having a keyword for class internals will allow the compiler to ensure that
only the public API for the class is used from the outside world. The user
can check types on his own, but it's better that the compiler does it
automatically. Similarly, the user can check that only the proper APIs are
called, but it's better that the compiler does it automatically.
>
> 2) accessibility by file structure may cause some really short files.
>
> 3) It's impossible to group related classes in one file but still hide
implementation details inside each class
>
> I think that it the best solution is to make private keyword do what
it states -- keep the class element private to the class. But if it's
really important to have a separate keyword for backward compatibility, it
would be the next best thing.

But on the flip side, with your proposed semantics for private, it would
be impossible to write a group of related types, functions, and extensions
that do need to refer to each other’s internal details without exposing
those details to the entire module. That’s not really acceptable.

The Swift language rule encourages you to put independent definitions in
different files. That definitely means that, if you want to enforce very
tight separation of concerns, you’ll end up with more and smaller files.
You haven’t explained why that’s really a *problem*, though.

John.

_______________________________________________

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


(thorsten@portableinnovations.de) #12

+1 for the scope based access control of Swift as opposed to the type based access control of other languages and for the nice writeup by Matthew.

I remember type based access control being criticized 20ish years ago to not allow access to internals of related classes. C++ created friends for that, Eiffel had something similar, but I like Swifts scope based model better, especially with respect to extensions.

Putting closely related things in one file and unrelated things in different files seems like a nice solution to me.

And its worth to note that private already means different things in different languages. In Java it means class private, in other languages it means object private (Ruby, I think).

That said I occasionally miss "protected" in the sense of subclass accessible.

-Thorsten

···

Am 07.12.2015 um 15:41 schrieb Matthew Johnson via swift-evolution <swift-evolution@swift.org>:

I was not sure how I felt about Swift's access control when it was first announced but it didn't take long for me to believe it strikes a pretty good balance between complexity and ability to hide implementation details.

It follows a very straightforward scope-driven strategy. If it is extended further I would like to see any enhancements follow the same scope-driven strategy rather than being type-driven as is seen in other languages. Proposals along these lines might be interesting to consider and might be able to accomplish what you are hoping to accomplish while affording additional flexibility.

In a language where distributing the implementation of a type across several extensions sometimes in different files a type-driven access control model doesn't make a lot of sense to me. I think it has a lot of potential to be confusing.

What would it mean to limit access to a member to the type itself in Swift? Would an extensions in the same (or different) files be able to see the member? What about extensions in a different module? And what about subclasses? Subclasses probably wouldn't have visibility to them, but any discussion of something like this will probably lead to discussion of protected as well.

Sent from my iPad

On Dec 7, 2015, at 7:45 AM, Ilya via swift-evolution <swift-evolution@swift.org> wrote:

Also, one problem with the current approach is that it's all or nothing. The classes in one file see everything from the other classes, and it may be useful to limit that and share only some additional APIs with those related classes, but not all of the implementation details / internal state, while still hiding those same APIs from unrelated classes. Currently, there is no way of doing it, even when splitting code into separate files (the class state must be all in one place and can't be in an extension).

--
Ilya Belenkiy

On Mon, Dec 7, 2015 at 8:17 AM Ilya <ilya@harmonicsense.com> wrote:
My main proposal was not to change the semantics of private (although I would like that) but to introduce a way to keep class implementation details inaccessible to anything outside the class. I think that it should still be possible and useful to have the current level of sharing (I would just name it differently, given what private usually means in other languages).

Just as it is convenient to group several related classes that can refer to each other's implementation details, it is very convenient to have several classes that don't do this but are still related in other important way, for example related APIs or classes that are based on the same implementation idea (like array based data structures).

Having all code in one place rather than jumping through many small files is a very nice thing to have because it really helps to keep everything consistent. The more manual work people have to do for consistency, the more likelihood that it won't be done.

--
Ilya Belenkiy

On Mon, Dec 7, 2015 at 12:21 AM John McCall <rjmccall@apple.com> wrote:

> On Dec 5, 2015, at 8:39 PM, Ilya via swift-evolution <swift-evolution@swift.org> wrote:
>
> I think the it would help a great deal to have an access level modifier that is really private and visible only inside the class itself. Right now, the only way to hide implementation details for a class is to hide the class code in a separate file, which is very inconvenient for several reasons:
>
> 1) the meaning of the code changes depending on which file the class is in. It's very easy to accidentally expose class internal details and then call class elements that are meant to be used only inside the class. Having a keyword for class internals will allow the compiler to ensure that only the public API for the class is used from the outside world. The user can check types on his own, but it's better that the compiler does it automatically. Similarly, the user can check that only the proper APIs are called, but it's better that the compiler does it automatically.
>
> 2) accessibility by file structure may cause some really short files.
>
> 3) It's impossible to group related classes in one file but still hide implementation details inside each class
>
> I think that it the best solution is to make private keyword do what it states -- keep the class element private to the class. But if it's really important to have a separate keyword for backward compatibility, it would be the next best thing.

But on the flip side, with your proposed semantics for private, it would be impossible to write a group of related types, functions, and extensions that do need to refer to each other’s internal details without exposing those details to the entire module. That’s not really acceptable.

The Swift language rule encourages you to put independent definitions in different files. That definitely means that, if you want to enforce very tight separation of concerns, you’ll end up with more and smaller files. You haven’t explained why that’s really a *problem*, though.

John.

_______________________________________________
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) #13

I think what you are really trying to accomplish is to restrict access to a member to the scope in which it is declared, which just happens to be a type declaration.

By looking at it in terms of scope the feature would be come more generally applicable. For example, you could have a 'classified' member in an extension which is only visible inside the body of the extension. This would be useful if the extension contains helper methods as part of its implementation.

I would absolutely support extending Swift's scope-based access control to allow for more granular control of visibility within a file by extending it to syntactic scopes. It seems like a pretty natural enhancement to the existing feature.

···

Sent from my iPad

On Dec 7, 2015, at 11:02 AM, Ilya <ilya@harmonicsense.com> wrote:

If it is not allowed in extensions or subclasses (and it shouldn't), the model is still very simple.

I understand the current model, but I think that there is a lot of value in getting the compiler's help in ensuring that class internals cannot be broken by anything outside the class.

The current model doesn't solve this problem well. Putting everything in separate files seems like a very unfortunate workaround.

--
Ilya Belenkiy

On Mon, Dec 7, 2015 at 9:41 AM Matthew Johnson <matthew@anandabits.com> wrote:
I was not sure how I felt about Swift's access control when it was first announced but it didn't take long for me to believe it strikes a pretty good balance between complexity and ability to hide implementation details.

It follows a very straightforward scope-driven strategy. If it is extended further I would like to see any enhancements follow the same scope-driven strategy rather than being type-driven as is seen in other languages. Proposals along these lines might be interesting to consider and might be able to accomplish what you are hoping to accomplish while affording additional flexibility.

In a language where distributing the implementation of a type across several extensions sometimes in different files a type-driven access control model doesn't make a lot of sense to me. I think it has a lot of potential to be confusing.

What would it mean to limit access to a member to the type itself in Swift? Would an extensions in the same (or different) files be able to see the member? What about extensions in a different module? And what about subclasses? Subclasses probably wouldn't have visibility to them, but any discussion of something like this will probably lead to discussion of protected as well.

Sent from my iPad

On Dec 7, 2015, at 7:45 AM, Ilya via swift-evolution <swift-evolution@swift.org> wrote:

Also, one problem with the current approach is that it's all or nothing. The classes in one file see everything from the other classes, and it may be useful to limit that and share only some additional APIs with those related classes, but not all of the implementation details / internal state, while still hiding those same APIs from unrelated classes. Currently, there is no way of doing it, even when splitting code into separate files (the class state must be all in one place and can't be in an extension).

--
Ilya Belenkiy

On Mon, Dec 7, 2015 at 8:17 AM Ilya <ilya@harmonicsense.com> wrote:
My main proposal was not to change the semantics of private (although I would like that) but to introduce a way to keep class implementation details inaccessible to anything outside the class. I think that it should still be possible and useful to have the current level of sharing (I would just name it differently, given what private usually means in other languages).

Just as it is convenient to group several related classes that can refer to each other's implementation details, it is very convenient to have several classes that don't do this but are still related in other important way, for example related APIs or classes that are based on the same implementation idea (like array based data structures).

Having all code in one place rather than jumping through many small files is a very nice thing to have because it really helps to keep everything consistent. The more manual work people have to do for consistency, the more likelihood that it won't be done.

--
Ilya Belenkiy

On Mon, Dec 7, 2015 at 12:21 AM John McCall <rjmccall@apple.com> wrote:

> On Dec 5, 2015, at 8:39 PM, Ilya via swift-evolution <swift-evolution@swift.org> wrote:
>
> I think the it would help a great deal to have an access level modifier that is really private and visible only inside the class itself. Right now, the only way to hide implementation details for a class is to hide the class code in a separate file, which is very inconvenient for several reasons:
>
> 1) the meaning of the code changes depending on which file the class is in. It's very easy to accidentally expose class internal details and then call class elements that are meant to be used only inside the class. Having a keyword for class internals will allow the compiler to ensure that only the public API for the class is used from the outside world. The user can check types on his own, but it's better that the compiler does it automatically. Similarly, the user can check that only the proper APIs are called, but it's better that the compiler does it automatically.
>
> 2) accessibility by file structure may cause some really short files.
>
> 3) It's impossible to group related classes in one file but still hide implementation details inside each class
>
> I think that it the best solution is to make private keyword do what it states -- keep the class element private to the class. But if it's really important to have a separate keyword for backward compatibility, it would be the next best thing.

But on the flip side, with your proposed semantics for private, it would be impossible to write a group of related types, functions, and extensions that do need to refer to each other’s internal details without exposing those details to the entire module. That’s not really acceptable.

The Swift language rule encourages you to put independent definitions in different files. That definitely means that, if you want to enforce very tight separation of concerns, you’ll end up with more and smaller files. You haven’t explained why that’s really a *problem*, though.

John.

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


(Ilya Belenkiy) #14

Yes, that's a great idea!

···

--
Ilya Belenkiy
On Mon, Dec 7, 2015 at 1:35 PM Matthew Johnson <matthew@anandabits.com> wrote:

I think what you are really trying to accomplish is to restrict access to
a member to the scope in which it is declared, which just happens to be a
type declaration.

By looking at it in terms of scope the feature would be come more
generally applicable. For example, you could have a 'classified' member in
an extension which is only visible inside the body of the extension. This
would be useful if the extension contains helper methods as part of its
implementation.

I would absolutely support extending Swift's scope-based access control to
allow for more granular control of visibility within a file by extending it
to syntactic scopes. It seems like a pretty natural enhancement to the
existing feature.

Sent from my iPad

On Dec 7, 2015, at 11:02 AM, Ilya <ilya@harmonicsense.com> wrote:

If it is not allowed in extensions or subclasses (and it shouldn't), the
model is still very simple.

I understand the current model, but I think that there is a lot of value
in getting the compiler's help in ensuring that class internals cannot be
broken by anything outside the class.

The current model doesn't solve this problem well. Putting everything in
separate files seems like a very unfortunate workaround.

--
Ilya Belenkiy

On Mon, Dec 7, 2015 at 9:41 AM Matthew Johnson <matthew@anandabits.com> > wrote:

I was not sure how I felt about Swift's access control when it was first
announced but it didn't take long for me to believe it strikes a pretty
good balance between complexity and ability to hide implementation details.

It follows a very straightforward scope-driven strategy. If it is
extended further I would like to see any enhancements follow the same
scope-driven strategy rather than being type-driven as is seen in other
languages. Proposals along these lines might be interesting to consider
and might be able to accomplish what you are hoping to accomplish while
affording additional flexibility.

In a language where distributing the implementation of a type across
several extensions sometimes in different files a type-driven access
control model doesn't make a lot of sense to me. I think it has a lot of
potential to be confusing.

What would it mean to limit access to a member to the type itself in
Swift? Would an extensions in the same (or different) files be able to see
the member? What about extensions in a different module? And what about
subclasses? Subclasses probably wouldn't have visibility to them, but any
discussion of something like this will probably lead to discussion of
protected as well.

Sent from my iPad

On Dec 7, 2015, at 7:45 AM, Ilya via swift-evolution < >> swift-evolution@swift.org> wrote:

Also, one problem with the current approach is that it's all or nothing.
The classes in one file see everything from the other classes, and it may
be useful to limit that and share only some additional APIs with those
related classes, but not all of the implementation details / internal
state, while still hiding those same APIs from unrelated classes.
Currently, there is no way of doing it, even when splitting code into
separate files (the class state must be all in one place and can't be in an
extension).

--
Ilya Belenkiy
On Mon, Dec 7, 2015 at 8:17 AM Ilya <ilya@harmonicsense.com> wrote:

My main proposal was not to change the semantics of private (although I
would like that) but to introduce a way to keep class implementation
details inaccessible to anything outside the class. I think that it should
still be possible and useful to have the current level of sharing (I would
just name it differently, given what private usually means in other
languages).

Just as it is convenient to group several related classes that can refer
to each other's implementation details, it is very convenient to have
several classes that don't do this but are still related in other important
way, for example related APIs or classes that are based on the same
implementation idea (like array based data structures).

Having all code in one place rather than jumping through many small
files is a very nice thing to have because it really helps to keep
everything consistent. The more manual work people have to do for
consistency, the more likelihood that it won't be done.

--
Ilya Belenkiy
On Mon, Dec 7, 2015 at 12:21 AM John McCall <rjmccall@apple.com> wrote:

> On Dec 5, 2015, at 8:39 PM, Ilya via swift-evolution < >>>> swift-evolution@swift.org> wrote:
>
> I think the it would help a great deal to have an access level
modifier that is really private and visible only inside the class itself.
Right now, the only way to hide implementation details for a class is to
hide the class code in a separate file, which is very inconvenient for
several reasons:
>
> 1) the meaning of the code changes depending on which file the class
is in. It's very easy to accidentally expose class internal details and
then call class elements that are meant to be used only inside the class.
Having a keyword for class internals will allow the compiler to ensure that
only the public API for the class is used from the outside world. The user
can check types on his own, but it's better that the compiler does it
automatically. Similarly, the user can check that only the proper APIs are
called, but it's better that the compiler does it automatically.
>
> 2) accessibility by file structure may cause some really short files.
>
> 3) It's impossible to group related classes in one file but still
hide implementation details inside each class
>
> I think that it the best solution is to make private keyword do what
it states -- keep the class element private to the class. But if it's
really important to have a separate keyword for backward compatibility, it
would be the next best thing.

But on the flip side, with your proposed semantics for private, it
would be impossible to write a group of related types, functions, and
extensions that do need to refer to each other’s internal details without
exposing those details to the entire module. That’s not really acceptable.

The Swift language rule encourages you to put independent definitions
in different files. That definitely means that, if you want to enforce
very tight separation of concerns, you’ll end up with more and smaller
files. You haven’t explained why that’s really a *problem*, though.

John.

_______________________________________________

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


(Matthew Johnson) #15

Glad you like my reframing! Is anyone planning to write a proposal for this?

···

Sent from my iPad

On Dec 7, 2015, at 1:00 PM, Ilya <ilya@harmonicsense.com> wrote:

Yes, that's a great idea!

--
Ilya Belenkiy

On Mon, Dec 7, 2015 at 1:35 PM Matthew Johnson <matthew@anandabits.com> wrote:
I think what you are really trying to accomplish is to restrict access to a member to the scope in which it is declared, which just happens to be a type declaration.

By looking at it in terms of scope the feature would be come more generally applicable. For example, you could have a 'classified' member in an extension which is only visible inside the body of the extension. This would be useful if the extension contains helper methods as part of its implementation.

I would absolutely support extending Swift's scope-based access control to allow for more granular control of visibility within a file by extending it to syntactic scopes. It seems like a pretty natural enhancement to the existing feature.

Sent from my iPad

On Dec 7, 2015, at 11:02 AM, Ilya <ilya@harmonicsense.com> wrote:

If it is not allowed in extensions or subclasses (and it shouldn't), the model is still very simple.

I understand the current model, but I think that there is a lot of value in getting the compiler's help in ensuring that class internals cannot be broken by anything outside the class.

The current model doesn't solve this problem well. Putting everything in separate files seems like a very unfortunate workaround.

--
Ilya Belenkiy

On Mon, Dec 7, 2015 at 9:41 AM Matthew Johnson <matthew@anandabits.com> wrote:
I was not sure how I felt about Swift's access control when it was first announced but it didn't take long for me to believe it strikes a pretty good balance between complexity and ability to hide implementation details.

It follows a very straightforward scope-driven strategy. If it is extended further I would like to see any enhancements follow the same scope-driven strategy rather than being type-driven as is seen in other languages. Proposals along these lines might be interesting to consider and might be able to accomplish what you are hoping to accomplish while affording additional flexibility.

In a language where distributing the implementation of a type across several extensions sometimes in different files a type-driven access control model doesn't make a lot of sense to me. I think it has a lot of potential to be confusing.

What would it mean to limit access to a member to the type itself in Swift? Would an extensions in the same (or different) files be able to see the member? What about extensions in a different module? And what about subclasses? Subclasses probably wouldn't have visibility to them, but any discussion of something like this will probably lead to discussion of protected as well.

Sent from my iPad

On Dec 7, 2015, at 7:45 AM, Ilya via swift-evolution <swift-evolution@swift.org> wrote:

Also, one problem with the current approach is that it's all or nothing. The classes in one file see everything from the other classes, and it may be useful to limit that and share only some additional APIs with those related classes, but not all of the implementation details / internal state, while still hiding those same APIs from unrelated classes. Currently, there is no way of doing it, even when splitting code into separate files (the class state must be all in one place and can't be in an extension).

--
Ilya Belenkiy

On Mon, Dec 7, 2015 at 8:17 AM Ilya <ilya@harmonicsense.com> wrote:
My main proposal was not to change the semantics of private (although I would like that) but to introduce a way to keep class implementation details inaccessible to anything outside the class. I think that it should still be possible and useful to have the current level of sharing (I would just name it differently, given what private usually means in other languages).

Just as it is convenient to group several related classes that can refer to each other's implementation details, it is very convenient to have several classes that don't do this but are still related in other important way, for example related APIs or classes that are based on the same implementation idea (like array based data structures).

Having all code in one place rather than jumping through many small files is a very nice thing to have because it really helps to keep everything consistent. The more manual work people have to do for consistency, the more likelihood that it won't be done.

--
Ilya Belenkiy

On Mon, Dec 7, 2015 at 12:21 AM John McCall <rjmccall@apple.com> wrote:

> On Dec 5, 2015, at 8:39 PM, Ilya via swift-evolution <swift-evolution@swift.org> wrote:
>
> I think the it would help a great deal to have an access level modifier that is really private and visible only inside the class itself. Right now, the only way to hide implementation details for a class is to hide the class code in a separate file, which is very inconvenient for several reasons:
>
> 1) the meaning of the code changes depending on which file the class is in. It's very easy to accidentally expose class internal details and then call class elements that are meant to be used only inside the class. Having a keyword for class internals will allow the compiler to ensure that only the public API for the class is used from the outside world. The user can check types on his own, but it's better that the compiler does it automatically. Similarly, the user can check that only the proper APIs are called, but it's better that the compiler does it automatically.
>
> 2) accessibility by file structure may cause some really short files.
>
> 3) It's impossible to group related classes in one file but still hide implementation details inside each class
>
> I think that it the best solution is to make private keyword do what it states -- keep the class element private to the class. But if it's really important to have a separate keyword for backward compatibility, it would be the next best thing.

But on the flip side, with your proposed semantics for private, it would be impossible to write a group of related types, functions, and extensions that do need to refer to each other’s internal details without exposing those details to the entire module. That’s not really acceptable.

The Swift language rule encourages you to put independent definitions in different files. That definitely means that, if you want to enforce very tight separation of concerns, you’ll end up with more and smaller files. You haven’t explained why that’s really a *problem*, though.

John.

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


(Ilya Belenkiy) #16

Hi Matthew,

Maybe you could write the proposal? I'd be happy to do it, but it was your
idea. Also, I think that you will express it better.

···

--
Ilya Belenkiy
On Mon, Dec 7, 2015 at 2:11 PM Matthew Johnson <matthew@anandabits.com> wrote:

Glad you like my reframing! Is anyone planning to write a proposal for
this?

Sent from my iPad

On Dec 7, 2015, at 1:00 PM, Ilya <ilya@harmonicsense.com> wrote:

Yes, that's a great idea!

--
Ilya Belenkiy
On Mon, Dec 7, 2015 at 1:35 PM Matthew Johnson <matthew@anandabits.com> > wrote:

I think what you are really trying to accomplish is to restrict access to
a member to the scope in which it is declared, which just happens to be a
type declaration.

By looking at it in terms of scope the feature would be come more
generally applicable. For example, you could have a 'classified' member in
an extension which is only visible inside the body of the extension. This
would be useful if the extension contains helper methods as part of its
implementation.

I would absolutely support extending Swift's scope-based access control
to allow for more granular control of visibility within a file by extending
it to syntactic scopes. It seems like a pretty natural enhancement to the
existing feature.

Sent from my iPad

On Dec 7, 2015, at 11:02 AM, Ilya <ilya@harmonicsense.com> wrote:

If it is not allowed in extensions or subclasses (and it shouldn't), the
model is still very simple.

I understand the current model, but I think that there is a lot of value
in getting the compiler's help in ensuring that class internals cannot be
broken by anything outside the class.

The current model doesn't solve this problem well. Putting everything in
separate files seems like a very unfortunate workaround.

--
Ilya Belenkiy

On Mon, Dec 7, 2015 at 9:41 AM Matthew Johnson <matthew@anandabits.com> >> wrote:

I was not sure how I felt about Swift's access control when it was first
announced but it didn't take long for me to believe it strikes a pretty
good balance between complexity and ability to hide implementation details.

It follows a very straightforward scope-driven strategy. If it is
extended further I would like to see any enhancements follow the same
scope-driven strategy rather than being type-driven as is seen in other
languages. Proposals along these lines might be interesting to consider
and might be able to accomplish what you are hoping to accomplish while
affording additional flexibility.

In a language where distributing the implementation of a type across
several extensions sometimes in different files a type-driven access
control model doesn't make a lot of sense to me. I think it has a lot of
potential to be confusing.

What would it mean to limit access to a member to the type itself in
Swift? Would an extensions in the same (or different) files be able to see
the member? What about extensions in a different module? And what about
subclasses? Subclasses probably wouldn't have visibility to them, but any
discussion of something like this will probably lead to discussion of
protected as well.

Sent from my iPad

On Dec 7, 2015, at 7:45 AM, Ilya via swift-evolution < >>> swift-evolution@swift.org> wrote:

Also, one problem with the current approach is that it's all or nothing.
The classes in one file see everything from the other classes, and it may
be useful to limit that and share only some additional APIs with those
related classes, but not all of the implementation details / internal
state, while still hiding those same APIs from unrelated classes.
Currently, there is no way of doing it, even when splitting code into
separate files (the class state must be all in one place and can't be in an
extension).

--
Ilya Belenkiy
On Mon, Dec 7, 2015 at 8:17 AM Ilya <ilya@harmonicsense.com> wrote:

My main proposal was not to change the semantics of private (although I
would like that) but to introduce a way to keep class implementation
details inaccessible to anything outside the class. I think that it should
still be possible and useful to have the current level of sharing (I would
just name it differently, given what private usually means in other
languages).

Just as it is convenient to group several related classes that can
refer to each other's implementation details, it is very convenient to have
several classes that don't do this but are still related in other important
way, for example related APIs or classes that are based on the same
implementation idea (like array based data structures).

Having all code in one place rather than jumping through many small
files is a very nice thing to have because it really helps to keep
everything consistent. The more manual work people have to do for
consistency, the more likelihood that it won't be done.

--
Ilya Belenkiy
On Mon, Dec 7, 2015 at 12:21 AM John McCall <rjmccall@apple.com> wrote:

> On Dec 5, 2015, at 8:39 PM, Ilya via swift-evolution < >>>>> swift-evolution@swift.org> wrote:
>
> I think the it would help a great deal to have an access level
modifier that is really private and visible only inside the class itself.
Right now, the only way to hide implementation details for a class is to
hide the class code in a separate file, which is very inconvenient for
several reasons:
>
> 1) the meaning of the code changes depending on which file the class
is in. It's very easy to accidentally expose class internal details and
then call class elements that are meant to be used only inside the class.
Having a keyword for class internals will allow the compiler to ensure that
only the public API for the class is used from the outside world. The user
can check types on his own, but it's better that the compiler does it
automatically. Similarly, the user can check that only the proper APIs are
called, but it's better that the compiler does it automatically.
>
> 2) accessibility by file structure may cause some really short files.
>
> 3) It's impossible to group related classes in one file but still
hide implementation details inside each class
>
> I think that it the best solution is to make private keyword do what
it states -- keep the class element private to the class. But if it's
really important to have a separate keyword for backward compatibility, it
would be the next best thing.

But on the flip side, with your proposed semantics for private, it
would be impossible to write a group of related types, functions, and
extensions that do need to refer to each other’s internal details without
exposing those details to the entire module. That’s not really acceptable.

The Swift language rule encourages you to put independent definitions
in different files. That definitely means that, if you want to enforce
very tight separation of concerns, you’ll end up with more and smaller
files. You haven’t explained why that’s really a *problem*, though.

John.

_______________________________________________

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


(Matthew Johnson) #17

I would be happy to do it, but I would like to know how broad the interest in exploring this is first, and especially whether this is something the core team is willing to consider for Swift 3 (depending on details of course).

···

Sent from my iPhone

On Dec 8, 2015, at 7:37 AM, Ilya <ilya@harmonicsense.com> wrote:

Hi Matthew,

Maybe you could write the proposal? I'd be happy to do it, but it was your idea. Also, I think that you will express it better.

--
Ilya Belenkiy

On Mon, Dec 7, 2015 at 2:11 PM Matthew Johnson <matthew@anandabits.com> wrote:
Glad you like my reframing! Is anyone planning to write a proposal for this?

Sent from my iPad

On Dec 7, 2015, at 1:00 PM, Ilya <ilya@harmonicsense.com> wrote:

Yes, that's a great idea!

--
Ilya Belenkiy

On Mon, Dec 7, 2015 at 1:35 PM Matthew Johnson <matthew@anandabits.com> wrote:
I think what you are really trying to accomplish is to restrict access to a member to the scope in which it is declared, which just happens to be a type declaration.

By looking at it in terms of scope the feature would be come more generally applicable. For example, you could have a 'classified' member in an extension which is only visible inside the body of the extension. This would be useful if the extension contains helper methods as part of its implementation.

I would absolutely support extending Swift's scope-based access control to allow for more granular control of visibility within a file by extending it to syntactic scopes. It seems like a pretty natural enhancement to the existing feature.

Sent from my iPad

On Dec 7, 2015, at 11:02 AM, Ilya <ilya@harmonicsense.com> wrote:

If it is not allowed in extensions or subclasses (and it shouldn't), the model is still very simple.

I understand the current model, but I think that there is a lot of value in getting the compiler's help in ensuring that class internals cannot be broken by anything outside the class.

The current model doesn't solve this problem well. Putting everything in separate files seems like a very unfortunate workaround.

--
Ilya Belenkiy

On Mon, Dec 7, 2015 at 9:41 AM Matthew Johnson <matthew@anandabits.com> wrote:
I was not sure how I felt about Swift's access control when it was first announced but it didn't take long for me to believe it strikes a pretty good balance between complexity and ability to hide implementation details.

It follows a very straightforward scope-driven strategy. If it is extended further I would like to see any enhancements follow the same scope-driven strategy rather than being type-driven as is seen in other languages. Proposals along these lines might be interesting to consider and might be able to accomplish what you are hoping to accomplish while affording additional flexibility.

In a language where distributing the implementation of a type across several extensions sometimes in different files a type-driven access control model doesn't make a lot of sense to me. I think it has a lot of potential to be confusing.

What would it mean to limit access to a member to the type itself in Swift? Would an extensions in the same (or different) files be able to see the member? What about extensions in a different module? And what about subclasses? Subclasses probably wouldn't have visibility to them, but any discussion of something like this will probably lead to discussion of protected as well.

Sent from my iPad

On Dec 7, 2015, at 7:45 AM, Ilya via swift-evolution <swift-evolution@swift.org> wrote:

Also, one problem with the current approach is that it's all or nothing. The classes in one file see everything from the other classes, and it may be useful to limit that and share only some additional APIs with those related classes, but not all of the implementation details / internal state, while still hiding those same APIs from unrelated classes. Currently, there is no way of doing it, even when splitting code into separate files (the class state must be all in one place and can't be in an extension).

--
Ilya Belenkiy

On Mon, Dec 7, 2015 at 8:17 AM Ilya <ilya@harmonicsense.com> wrote:
My main proposal was not to change the semantics of private (although I would like that) but to introduce a way to keep class implementation details inaccessible to anything outside the class. I think that it should still be possible and useful to have the current level of sharing (I would just name it differently, given what private usually means in other languages).

Just as it is convenient to group several related classes that can refer to each other's implementation details, it is very convenient to have several classes that don't do this but are still related in other important way, for example related APIs or classes that are based on the same implementation idea (like array based data structures).

Having all code in one place rather than jumping through many small files is a very nice thing to have because it really helps to keep everything consistent. The more manual work people have to do for consistency, the more likelihood that it won't be done.

--
Ilya Belenkiy

On Mon, Dec 7, 2015 at 12:21 AM John McCall <rjmccall@apple.com> wrote:

> On Dec 5, 2015, at 8:39 PM, Ilya via swift-evolution <swift-evolution@swift.org> wrote:
>
> I think the it would help a great deal to have an access level modifier that is really private and visible only inside the class itself. Right now, the only way to hide implementation details for a class is to hide the class code in a separate file, which is very inconvenient for several reasons:
>
> 1) the meaning of the code changes depending on which file the class is in. It's very easy to accidentally expose class internal details and then call class elements that are meant to be used only inside the class. Having a keyword for class internals will allow the compiler to ensure that only the public API for the class is used from the outside world. The user can check types on his own, but it's better that the compiler does it automatically. Similarly, the user can check that only the proper APIs are called, but it's better that the compiler does it automatically.
>
> 2) accessibility by file structure may cause some really short files.
>
> 3) It's impossible to group related classes in one file but still hide implementation details inside each class
>
> I think that it the best solution is to make private keyword do what it states -- keep the class element private to the class. But if it's really important to have a separate keyword for backward compatibility, it would be the next best thing.

But on the flip side, with your proposed semantics for private, it would be impossible to write a group of related types, functions, and extensions that do need to refer to each other’s internal details without exposing those details to the entire module. That’s not really acceptable.

The Swift language rule encourages you to put independent definitions in different files. That definitely means that, if you want to enforce very tight separation of concerns, you’ll end up with more and smaller files. You haven’t explained why that’s really a *problem*, though.

John.

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


(Jordan Rose) #18

As the primary implementer of the Swift access model when it first went in, I don't think we need something like "classified". The purpose of access control is to make sure implementation details stay hidden from other parts of the program. If you're in the same file, you're not in another part of the program. (If your files are big enough that you are in another part of the program, maybe you should split things up into more files.)

I am glad that you're not treating extensions as "just part of the type". A lot of people say "oh, of course my 'just for the type' modifier allows extensions to see things", forgetting that extensions be added in any file in the program, including outside the module. You can even add extensions for the sole purpose of accessing these members, and therefore there's no protection at all.

This doesn't mean you can't submit a proposal officially to the swift-evolution repo, or even that it won't get reviewed. (I'm not on the core team, and even core team members can be overruled by the rest of the team.) It just means I'm against it. :slight_smile: I am glad people are thinking about it, though!

As for "Swift 3" specifically, I'll repeat Chris's canned message: the schedule for Swift 3 is already pretty full with our documented goals, so there's really no guarantee about what will or won't get engineering time for that release.

Best,
Jordan

···

On Dec 8, 2015, at 8:07, Matthew Johnson via swift-evolution <swift-evolution@swift.org> wrote:

I would be happy to do it, but I would like to know how broad the interest in exploring this is first, and especially whether this is something the core team is willing to consider for Swift 3 (depending on details of course).

Sent from my iPhone

On Dec 8, 2015, at 7:37 AM, Ilya <ilya@harmonicsense.com <mailto:ilya@harmonicsense.com>> wrote:

Hi Matthew,

Maybe you could write the proposal? I'd be happy to do it, but it was your idea. Also, I think that you will express it better.

--
Ilya Belenkiy
On Mon, Dec 7, 2015 at 2:11 PM Matthew Johnson <matthew@anandabits.com <mailto:matthew@anandabits.com>> wrote:
Glad you like my reframing! Is anyone planning to write a proposal for this?

Sent from my iPad

On Dec 7, 2015, at 1:00 PM, Ilya <ilya@harmonicsense.com <mailto:ilya@harmonicsense.com>> wrote:

Yes, that's a great idea!

--
Ilya Belenkiy
On Mon, Dec 7, 2015 at 1:35 PM Matthew Johnson <matthew@anandabits.com <mailto:matthew@anandabits.com>> wrote:
I think what you are really trying to accomplish is to restrict access to a member to the scope in which it is declared, which just happens to be a type declaration.

By looking at it in terms of scope the feature would be come more generally applicable. For example, you could have a 'classified' member in an extension which is only visible inside the body of the extension. This would be useful if the extension contains helper methods as part of its implementation.

I would absolutely support extending Swift's scope-based access control to allow for more granular control of visibility within a file by extending it to syntactic scopes. It seems like a pretty natural enhancement to the existing feature.

Sent from my iPad

On Dec 7, 2015, at 11:02 AM, Ilya <ilya@harmonicsense.com <mailto:ilya@harmonicsense.com>> wrote:

If it is not allowed in extensions or subclasses (and it shouldn't), the model is still very simple.

I understand the current model, but I think that there is a lot of value in getting the compiler's help in ensuring that class internals cannot be broken by anything outside the class.

The current model doesn't solve this problem well. Putting everything in separate files seems like a very unfortunate workaround.

--
Ilya Belenkiy

On Mon, Dec 7, 2015 at 9:41 AM Matthew Johnson <matthew@anandabits.com <mailto:matthew@anandabits.com>> wrote:
I was not sure how I felt about Swift's access control when it was first announced but it didn't take long for me to believe it strikes a pretty good balance between complexity and ability to hide implementation details.

It follows a very straightforward scope-driven strategy. If it is extended further I would like to see any enhancements follow the same scope-driven strategy rather than being type-driven as is seen in other languages. Proposals along these lines might be interesting to consider and might be able to accomplish what you are hoping to accomplish while affording additional flexibility.

In a language where distributing the implementation of a type across several extensions sometimes in different files a type-driven access control model doesn't make a lot of sense to me. I think it has a lot of potential to be confusing.

What would it mean to limit access to a member to the type itself in Swift? Would an extensions in the same (or different) files be able to see the member? What about extensions in a different module? And what about subclasses? Subclasses probably wouldn't have visibility to them, but any discussion of something like this will probably lead to discussion of protected as well.

Sent from my iPad

On Dec 7, 2015, at 7:45 AM, Ilya via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Also, one problem with the current approach is that it's all or nothing. The classes in one file see everything from the other classes, and it may be useful to limit that and share only some additional APIs with those related classes, but not all of the implementation details / internal state, while still hiding those same APIs from unrelated classes. Currently, there is no way of doing it, even when splitting code into separate files (the class state must be all in one place and can't be in an extension).

--
Ilya Belenkiy
On Mon, Dec 7, 2015 at 8:17 AM Ilya <ilya@harmonicsense.com <mailto:ilya@harmonicsense.com>> wrote:
My main proposal was not to change the semantics of private (although I would like that) but to introduce a way to keep class implementation details inaccessible to anything outside the class. I think that it should still be possible and useful to have the current level of sharing (I would just name it differently, given what private usually means in other languages).

Just as it is convenient to group several related classes that can refer to each other's implementation details, it is very convenient to have several classes that don't do this but are still related in other important way, for example related APIs or classes that are based on the same implementation idea (like array based data structures).

Having all code in one place rather than jumping through many small files is a very nice thing to have because it really helps to keep everything consistent. The more manual work people have to do for consistency, the more likelihood that it won't be done.

--
Ilya Belenkiy
On Mon, Dec 7, 2015 at 12:21 AM John McCall <rjmccall@apple.com <mailto:rjmccall@apple.com>> wrote:

> On Dec 5, 2015, at 8:39 PM, Ilya via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>
> I think the it would help a great deal to have an access level modifier that is really private and visible only inside the class itself. Right now, the only way to hide implementation details for a class is to hide the class code in a separate file, which is very inconvenient for several reasons:
>
> 1) the meaning of the code changes depending on which file the class is in. It's very easy to accidentally expose class internal details and then call class elements that are meant to be used only inside the class. Having a keyword for class internals will allow the compiler to ensure that only the public API for the class is used from the outside world. The user can check types on his own, but it's better that the compiler does it automatically. Similarly, the user can check that only the proper APIs are called, but it's better that the compiler does it automatically.
>
> 2) accessibility by file structure may cause some really short files.
>
> 3) It's impossible to group related classes in one file but still hide implementation details inside each class
>
> I think that it the best solution is to make private keyword do what it states -- keep the class element private to the class. But if it's really important to have a separate keyword for backward compatibility, it would be the next best thing.

But on the flip side, with your proposed semantics for private, it would be impossible to write a group of related types, functions, and extensions that do need to refer to each other’s internal details without exposing those details to the entire module. That’s not really acceptable.

The Swift language rule encourages you to put independent definitions in different files. That definitely means that, if you want to enforce very tight separation of concerns, you’ll end up with more and smaller files. You haven’t explained why that’s really a *problem*, though.

John.

_______________________________________________
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 <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution


(Amir Michail) #19

Swift is a safe language after all. Moreover, it is all too easy to accidentally type “assert” when you mean “precondition”.


(Ilya Belenkiy) #20

Hi Jordan,

Thank you, I understand your reasoning. The current model is simple to
describe and implement. It’s a good solution for access control across
modules. That being said, it doesn’t solve the problem of hiding
implementation details at a smaller scale, which is also important. The
suggestion to put each class (or part of the class) in a separate file
works for large pieces of code but isn’t practical for smaller pieces. An
analogy: putting each chapter of a book into a separate file makes sense
but putting every paragraph in a separate file does not.

I think that Matthew had a great idea: add a scope based access control.
Swift already has some support for it: local functions. I actually use it a
lot and put functions into other functions to hide implementation details.
It’s not possible to use it everywhere, but when it is possible, it’s
great. If we could have a “local” access modifier that limited the entity
only to the scope in which it’s defined, that would allow much less
nesting, and it would make it possible to hide many more code.structures.

For me, hiding implementation details is a fundamental feature of the
language / compiler. It is possible to get by without it with coding by
convention, but it’s also possible to get by without a strong type system.
Having a way to hide implementation details that is enforced by the
language will help to have clearly defined interfaces and limit hacks and
mistakes for misusing APIs that are meant to be private.

I appreciate what you said about an official proposal. I’ll ask Matthew
again (since access by scope was his idea). If he is not up to it, I’ll
submit a proposal myself. For me, this issue was one of the driving forces
to join the mailing list.

···


Ilya Belenkiy

On Dec 8, 2015, at 6:49 PM, Jordan Rose <jordan_rose@apple.com> wrote:

As the primary implementer of the Swift access model when it first went in,
I don't think we need something like "classified". The purpose of access
control is to make sure implementation details stay hidden from other parts
of the program. If you're in the same file, you're not in another part of
the program. (If your files are big enough that you *are* in another part
of the program, maybe you should split things up into more files.)

I *am* glad that you're not treating extensions as "just part of the type".
A lot of people say "oh, of course my 'just for the type' modifier allows
extensions to see things", forgetting that extensions be added in any file
in the program, including outside the module. You can even add extensions
for the sole purpose of accessing these members, and therefore there's no
protection at all.

This doesn't mean you can't submit a proposal officially to the
swift-evolution repo, or even that it won't get reviewed. (I'm not on the
core team, and even core team members can be overruled by the rest of the
team.) It just means I'm against it. :slight_smile: I am glad people are thinking
about it, though!

As for "Swift 3" specifically, I'll repeat Chris's canned message: the
schedule for Swift 3 is already pretty full with our documented goals, so
there's really no guarantee about what will or won't get engineering time
for that release.

Best,
Jordan

On Dec 8, 2015, at 8:07, Matthew Johnson via swift-evolution < swift-evolution@swift.org> wrote:

I would be happy to do it, but I would like to know how broad the interest
in exploring this is first, and especially whether this is something the
core team is willing to consider for Swift 3 (depending on details of
course).

Sent from my iPhone

On Dec 8, 2015, at 7:37 AM, Ilya <ilya@harmonicsense.com> wrote:

Hi Matthew,

Maybe you could write the proposal? I'd be happy to do it, but it was your
idea. Also, I think that you will express it better.

--
Ilya Belenkiy
On Mon, Dec 7, 2015 at 2:11 PM Matthew Johnson <matthew@anandabits.com> wrote:

Glad you like my reframing! Is anyone planning to write a proposal for
this?

Sent from my iPad

On Dec 7, 2015, at 1:00 PM, Ilya <ilya@harmonicsense.com> wrote:

Yes, that's a great idea!

--
Ilya Belenkiy
On Mon, Dec 7, 2015 at 1:35 PM Matthew Johnson <matthew@anandabits.com> > wrote:

I think what you are really trying to accomplish is to restrict access to
a member to the scope in which it is declared, which just happens to be a
type declaration.

By looking at it in terms of scope the feature would be come more
generally applicable. For example, you could have a 'classified' member in
an extension which is only visible inside the body of the extension. This
would be useful if the extension contains helper methods as part of its
implementation.

I would absolutely support extending Swift's scope-based access control
to allow for more granular control of visibility within a file by extending
it to syntactic scopes. It seems like a pretty natural enhancement to the
existing feature.

Sent from my iPad

On Dec 7, 2015, at 11:02 AM, Ilya <ilya@harmonicsense.com> wrote:

If it is not allowed in extensions or subclasses (and it shouldn't), the
model is still very simple.

I understand the current model, but I think that there is a lot of value
in getting the compiler's help in ensuring that class internals cannot be
broken by anything outside the class.

The current model doesn't solve this problem well. Putting everything in
separate files seems like a very unfortunate workaround.

--
Ilya Belenkiy

On Mon, Dec 7, 2015 at 9:41 AM Matthew Johnson <matthew@anandabits.com> >> wrote:

I was not sure how I felt about Swift's access control when it was first
announced but it didn't take long for me to believe it strikes a pretty
good balance between complexity and ability to hide implementation details.

It follows a very straightforward scope-driven strategy. If it is
extended further I would like to see any enhancements follow the same
scope-driven strategy rather than being type-driven as is seen in other
languages. Proposals along these lines might be interesting to consider
and might be able to accomplish what you are hoping to accomplish while
affording additional flexibility.

In a language where distributing the implementation of a type across
several extensions sometimes in different files a type-driven access
control model doesn't make a lot of sense to me. I think it has a lot of
potential to be confusing.

What would it mean to limit access to a member to the type itself in
Swift? Would an extensions in the same (or different) files be able to see
the member? What about extensions in a different module? And what about
subclasses? Subclasses probably wouldn't have visibility to them, but any
discussion of something like this will probably lead to discussion of
protected as well.

Sent from my iPad

On Dec 7, 2015, at 7:45 AM, Ilya via swift-evolution < >>> swift-evolution@swift.org> wrote:

Also, one problem with the current approach is that it's all or nothing.
The classes in one file see everything from the other classes, and it may
be useful to limit that and share only some additional APIs with those
related classes, but not all of the implementation details / internal
state, while still hiding those same APIs from unrelated classes.
Currently, there is no way of doing it, even when splitting code into
separate files (the class state must be all in one place and can't be in an
extension).

--
Ilya Belenkiy
On Mon, Dec 7, 2015 at 8:17 AM Ilya <ilya@harmonicsense.com> wrote:

My main proposal was not to change the semantics of private (although I
would like that) but to introduce a way to keep class implementation
details inaccessible to anything outside the class. I think that it should
still be possible and useful to have the current level of sharing (I would
just name it differently, given what private usually means in other
languages).

Just as it is convenient to group several related classes that can
refer to each other's implementation details, it is very convenient to have
several classes that don't do this but are still related in other important
way, for example related APIs or classes that are based on the same
implementation idea (like array based data structures).

Having all code in one place rather than jumping through many small
files is a very nice thing to have because it really helps to keep
everything consistent. The more manual work people have to do for
consistency, the more likelihood that it won't be done.

--
Ilya Belenkiy
On Mon, Dec 7, 2015 at 12:21 AM John McCall <rjmccall@apple.com> wrote:

> On Dec 5, 2015, at 8:39 PM, Ilya via swift-evolution < >>>>> swift-evolution@swift.org> wrote:
>
> I think the it would help a great deal to have an access level
modifier that is really private and visible only inside the class itself.
Right now, the only way to hide implementation details for a class is to
hide the class code in a separate file, which is very inconvenient for
several reasons:
>
> 1) the meaning of the code changes depending on which file the class
is in. It's very easy to accidentally expose class internal details and
then call class elements that are meant to be used only inside the class.
Having a keyword for class internals will allow the compiler to ensure that
only the public API for the class is used from the outside world. The user
can check types on his own, but it's better that the compiler does it
automatically. Similarly, the user can check that only the proper APIs are
called, but it's better that the compiler does it automatically.
>
> 2) accessibility by file structure may cause some really short files.
>
> 3) It's impossible to group related classes in one file but still
hide implementation details inside each class
>
> I think that it the best solution is to make private keyword do what
it states -- keep the class element private to the class. But if it's
really important to have a separate keyword for backward compatibility, it
would be the next best thing.

But on the flip side, with your proposed semantics for private, it
would be impossible to write a group of related types, functions, and
extensions that do need to refer to each other’s internal details without
exposing those details to the entire module. That’s not really acceptable.

The Swift language rule encourages you to put independent definitions
in different files. That definitely means that, if you want to enforce
very tight separation of concerns, you’ll end up with more and smaller
files. You haven’t explained why that’s really a *problem*, though.

John.

_______________________________________________

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