Class scoped access level


(Tom Bates) #1

There is currently no way of accessing "shared code" from extensions
declared outside the base .swift file

I would love to see along side the new fileprivate access level a
classprivate access level that would allow any extension declared outside
of the original .swift file to access these properties and functions in an
attempt to reuse code.

an example is below...

···

=================
//MyClass.swift
public class MyClass {

classprivate func sharedFunction() {
  self.function1()
  self.function2()
}

fileprivate func function1() {}
fileprivate func function2() {}
}

=================
//MyClass+Save.swift
extension MyClass {

public func save() {
  self.someFunction()
  self.sharedFunction()
}

fileprivate func someFunction() {}
}

Currently to achieve anything like this you would have to make the "core"
functions public or internal or write the whole thing in a single file
which as I understand it is not optimal for the compile speed and can get
unmanageable for large classes. This would allow a more managed file
structure and the separation of related functions from the core declaration.

There would be no migration needed I don't think as the impact on current
code would be zero until the developer adopts the new access level

Regards,
Tom


(Adrian Zubarev) #2

There must be a better solution to this problem, because you might also extend value types from different files. That would mean, we'd need `structprivate` `protocolprivate` etc.

How about: `internal(class)` etc. ? Or something like `internal(private)` to rule them all (I don't like the last name, but something that would rule them all would be nice to have)!

···

--
Adrian Zubarev
Sent with Airmail

Am 9. September 2016 um 17:49:29, Tom Bates via swift-evolution (swift-evolution@swift.org(mailto:swift-evolution@swift.org)) schrieb:

There is currently no way of accessing "shared code" from extensions declared outside the base .swift file

I would love to see along side the new fileprivate access level a classprivate access level that would allow any extension declared outside of the original .swift file to access these properties and functions in an attempt to reuse code.

an example is below...

=================
//MyClass.swift
public class MyClass {

classprivate func sharedFunction() {
self.function1()
self.function2()
}

fileprivate func function1() {}
fileprivate func function2() {}
}

=================
//MyClass+Save.swift
extension MyClass {

public func save() {
self.someFunction()
self.sharedFunction()
}

fileprivate func someFunction() {}
}

Currently to achieve anything like this you would have to make the "core" functions public or internal or write the whole thing in a single file which as I understand it is not optimal for the compile speed and can get unmanageable for large classes. This would allow a more managed file structure and the separation of related functions from the core declaration.

There would be no migration needed I don't think as the impact on current code would be zero until the developer adopts the new access level

Regards,
Tom

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


(Xiaodi Wu) #3

Isn't the general solution to this problem submodules? In any case, seems
like it'd be out of scope for Swift 4 phase 1.

···

On Fri, Sep 9, 2016 at 11:34 AM, Adrian Zubarev via swift-evolution < swift-evolution@swift.org> wrote:

There must be a better solution to this problem, because you might also
extend value types from different files. That would mean, we'd need
`structprivate` `protocolprivate` etc.

How about: `internal(class)` etc. ? Or something like `internal(private)`
to rule them all (I don't like the last name, but something that would rule
them all would be nice to have)!

--
Adrian Zubarev
Sent with Airmail

Am 9. September 2016 um 17:49:29, Tom Bates via swift-evolution (
swift-evolution@swift.org) schrieb:

There is currently no way of accessing "shared code" from extensions
declared outside the base .swift file

I would love to see along side the new fileprivate access level a
classprivate access level that would allow any extension declared outside
of the original .swift file to access these properties and functions in an
attempt to reuse code.

an example is below...

=================
//MyClass.swift
public class MyClass {

classprivate func sharedFunction() {
  self.function1()
  self.function2()
}

fileprivate func function1() {}
fileprivate func function2() {}
}

=================
//MyClass+Save.swift
extension MyClass {

public func save() {
  self.someFunction()
  self.sharedFunction()
}

fileprivate func someFunction() {}
}

Currently to achieve anything like this you would have to make the "core"
functions public or internal or write the whole thing in a single file
which as I understand it is not optimal for the compile speed and can get
unmanageable for large classes. This would allow a more managed file
structure and the separation of related functions from the core declaration.

There would be no migration needed I don't think as the impact on current
code would be zero until the developer adopts the new access level

Regards,
Tom
_______________________________________________
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


(Adrian Zubarev) #4

I don't think submodules would solve it nicely. Each module/submodule will require it's own namespace + it feels like an overkill to create submodules for a few types. `internal(xyz)` seems to me like a better solution. And yes this is purely additional and nothing for phase 1.

···

--
Adrian Zubarev
Sent with Airmail

Am 9. September 2016 um 19:09:12, Xiaodi Wu (xiaodi.wu@gmail.com(mailto:xiaodi.wu@gmail.com)) schrieb:

Isn't the general solution to this problem submodules? In any case, seems like it'd be out of scope for Swift 4 phase 1.

On Fri, Sep 9, 2016 at 11:34 AM, Adrian Zubarev via swift-evolution <swift-evolution@swift.org(mailto:swift-evolution@swift.org)> wrote:
> There must be a better solution to this problem, because you might also extend value types from different files. That would mean, we'd need `structprivate` `protocolprivate` etc.
>
> How about: `internal(class)` etc. ? Or something like `internal(private)` to rule them all (I don't like the last name, but something that would rule them all would be nice to have)!
>
>
> --
> Adrian Zubarev
> Sent with Airmail
>
> Am 9. September 2016 um 17:49:29, Tom Bates via swift-evolution (swift-evolution@swift.org(mailto:swift-evolution@swift.org)) schrieb:
>
>
>
> >
> > There is currently no way of accessing "shared code" from extensions declared outside the base .swift file
> >
> > I would love to see along side the new fileprivate access level a classprivate access level that would allow any extension declared outside of the original .swift file to access these properties and functions in an attempt to reuse code.
> >
> > an example is below...
> >
> > =================
> > //MyClass.swift
> > public class MyClass {
> >
> > classprivate func sharedFunction() {
> > self.function1()
> > self.function2()
> > }
> >
> > fileprivate func function1() {}
> > fileprivate func function2() {}
> > }
> > =================
> >
> > =================
> > //MyClass+Save.swift
> > extension MyClass {
> >
> > public func save() {
> > self.someFunction()
> > self.sharedFunction()
> > }
> >
> > fileprivate func someFunction() {}
> > }
> > =================
> >
> > Currently to achieve anything like this you would have to make the "core" functions public or internal or write the whole thing in a single file which as I understand it is not optimal for the compile speed and can get unmanageable for large classes. This would allow a more managed file structure and the separation of related functions from the core declaration.
> >
> > There would be no migration needed I don't think as the impact on current code would be zero until the developer adopts the new access level
> >
> > Regards,
> > Tom
> >
> >
> >
> >
> >
> > _______________________________________________
> > 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
>


(Tom Bates) #5

I agree that classprivate would probably not work, maybe constructprivate?
but then you are leaving our enum etc.
With the `internal(class)` suggestion, if declaring a var such as `
internal(set) var name: String?` would this become `internal(class, set) var
name: String?`
Also there would need to be some kind of compile check either way because
if you declared an enum for example outside of a constructor you would not
be able to mark it as our new constructor only access level or it would
become inaccessible throughout the project.

Re: submodules, they are indeed overkill for this. As you would need a
separate submodule for each class you wanted to do this with and then run
the risk of inter coupling lots of different really small submodules.

Suggestions so far:
`classprivate`
`constructprivate`
`private(instance)`, `private(instance, set)` - problem -> how would this
work? `public private(instance, set)`
`internal(class)`

Personally I think a name like `classprivate` or `constructprivate`,
although not particularly well named would reduce complexities with private
setters syntax and keep migrations much simpler.

···

On Sat, 10 Sep 2016 at 07:09 Adrian Zubarev via swift-evolution < swift-evolution@swift.org> wrote:

I don't think submodules would solve it nicely. Each module/submodule will
require it's own namespace + it feels like an overkill to create submodules
for a few types. `internal(xyz)` seems to me like a better solution. And
yes this is purely additional and nothing for phase 1.

--
Adrian Zubarev
Sent with Airmail

Am 9. September 2016 um 19:09:12, Xiaodi Wu (xiaodi.wu@gmail.com) schrieb:

Isn't the general solution to this problem submodules? In any case, seems
like it'd be out of scope for Swift 4 phase 1.

On Fri, Sep 9, 2016 at 11:34 AM, Adrian Zubarev via swift-evolution < >> swift-evolution@swift.org> wrote:

There must be a better solution to this problem, because you might also
extend value types from different files. That would mean, we'd need
`structprivate` `protocolprivate` etc.

How about: `internal(class)` etc. ? Or something like
`internal(private)` to rule them all (I don't like the last name, but
something that would rule them all would be nice to have)!

--
Adrian Zubarev
Sent with Airmail

Am 9. September 2016 um 17:49:29, Tom Bates via swift-evolution (
swift-evolution@swift.org) schrieb:

There is currently no way of accessing "shared code" from extensions
declared outside the base .swift file

I would love to see along side the new fileprivate access level a
classprivate access level that would allow any extension declared outside
of the original .swift file to access these properties and functions in an
attempt to reuse code.

an example is below...

=================
//MyClass.swift
public class MyClass {

classprivate func sharedFunction() {
  self.function1()
  self.function2()
}

fileprivate func function1() {}
fileprivate func function2() {}
}

=================
//MyClass+Save.swift
extension MyClass {

public func save() {
  self.someFunction()
  self.sharedFunction()
}

fileprivate func someFunction() {}
}

Currently to achieve anything like this you would have to make the
"core" functions public or internal or write the whole thing in a single
file which as I understand it is not optimal for the compile speed and can
get unmanageable for large classes. This would allow a more managed file
structure and the separation of related functions from the core declaration.

There would be no migration needed I don't think as the impact on
current code would be zero until the developer adopts the new access level

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

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

_______________________________________________

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


(TJ Usiyan) #6

I am firmly against this. The 5 levels that we have cover us well and have
enough complexity already.

···

On Sat, Sep 10, 2016 at 5:23 AM, Tom Bates via swift-evolution < swift-evolution@swift.org> wrote:

I agree that classprivate would probably not work, maybe constructprivate?
but then you are leaving our enum etc.
With the `internal(class)` suggestion, if declaring a var such as `
internal(set) var name: String?` would this become `internal(class, set)
var name: String?`
Also there would need to be some kind of compile check either way because
if you declared an enum for example outside of a constructor you would not
be able to mark it as our new constructor only access level or it would
become inaccessible throughout the project.

Re: submodules, they are indeed overkill for this. As you would need a
separate submodule for each class you wanted to do this with and then run
the risk of inter coupling lots of different really small submodules.

Suggestions so far:
`classprivate`
`constructprivate`
`private(instance)`, `private(instance, set)` - problem -> how would this
work? `public private(instance, set)`
`internal(class)`

Personally I think a name like `classprivate` or `constructprivate`,
although not particularly well named would reduce complexities with private
setters syntax and keep migrations much simpler.

On Sat, 10 Sep 2016 at 07:09 Adrian Zubarev via swift-evolution < > swift-evolution@swift.org> wrote:

I don't think submodules would solve it nicely. Each module/submodule
will require it's own namespace + it feels like an overkill to create
submodules for a few types. `internal(xyz)` seems to me like a better
solution. And yes this is purely additional and nothing for phase 1.

--
Adrian Zubarev
Sent with Airmail

Am 9. September 2016 um 19:09:12, Xiaodi Wu (xiaodi.wu@gmail.com)
schrieb:

Isn't the general solution to this problem submodules? In any case,
seems like it'd be out of scope for Swift 4 phase 1.

On Fri, Sep 9, 2016 at 11:34 AM, Adrian Zubarev via swift-evolution < >>> swift-evolution@swift.org> wrote:

There must be a better solution to this problem, because you might also
extend value types from different files. That would mean, we'd need
`structprivate` `protocolprivate` etc.

How about: `internal(class)` etc. ? Or something like
`internal(private)` to rule them all (I don't like the last name, but
something that would rule them all would be nice to have)!

--
Adrian Zubarev
Sent with Airmail

Am 9. September 2016 um 17:49:29, Tom Bates via swift-evolution (
swift-evolution@swift.org) schrieb:

There is currently no way of accessing "shared code" from extensions
declared outside the base .swift file

I would love to see along side the new fileprivate access level a
classprivate access level that would allow any extension declared outside
of the original .swift file to access these properties and functions in an
attempt to reuse code.

an example is below...

=================
//MyClass.swift
public class MyClass {

classprivate func sharedFunction() {
  self.function1()
  self.function2()
}

fileprivate func function1() {}
fileprivate func function2() {}
}

=================
//MyClass+Save.swift
extension MyClass {

public func save() {
  self.someFunction()
  self.sharedFunction()
}

fileprivate func someFunction() {}
}

Currently to achieve anything like this you would have to make the
"core" functions public or internal or write the whole thing in a single
file which as I understand it is not optimal for the compile speed and can
get unmanageable for large classes. This would allow a more managed file
structure and the separation of related functions from the core declaration.

There would be no migration needed I don't think as the impact on
current code would be zero until the developer adopts the new access level

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

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

_______________________________________________

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

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


(Tom Bates) #7

Reading between the line of what T.J has said I can see he is keen to see
this become reality!

It is very easy to come across examples where the current access level do
NOT work well and are inhibiting clean, readable code. Which, in my
opinion, when considering any kind of scale is probably the most important
thing to be able to maintain, extend and ultimately reduce bugs.

I agree that the obvious concern would be complexity.
One solution that would eliminate any extra complexity would be to allow
extensions to access all private variables and functions from it's initial
declaration.
This would only be the case when the extension's declaration is within the
defining module (prevents people accessing private variables when using
submodules)
To restrict access to extensions of the class you would use the
`fileprivate` access control.
If you want access to a var or func outside the defining module then it has
to be public as is the case now.

Again, this would require no migrations to existing code that I can see.

···

On Sat, 10 Sep 2016 at 13:17 T.J. Usiyan <griotspeak@gmail.com> wrote:

I am firmly against this. The 5 levels that we have cover us well and have
enough complexity already.

On Sat, Sep 10, 2016 at 5:23 AM, Tom Bates via swift-evolution < > swift-evolution@swift.org> wrote:

I agree that classprivate would probably not work, maybe
constructprivate? but then you are leaving our enum etc.
With the `internal(class)` suggestion, if declaring a var such as `
internal(set) var name: String?` would this become `internal(class, set)
var name: String?`
Also there would need to be some kind of compile check either way because
if you declared an enum for example outside of a constructor you would not
be able to mark it as our new constructor only access level or it would
become inaccessible throughout the project.

Re: submodules, they are indeed overkill for this. As you would need a
separate submodule for each class you wanted to do this with and then run
the risk of inter coupling lots of different really small submodules.

Suggestions so far:
`classprivate`
`constructprivate`
`private(instance)`, `private(instance, set)` - problem -> how would this
work? `public private(instance, set)`
`internal(class)`

Personally I think a name like `classprivate` or `constructprivate`,
although not particularly well named would reduce complexities with private
setters syntax and keep migrations much simpler.

On Sat, 10 Sep 2016 at 07:09 Adrian Zubarev via swift-evolution < >> swift-evolution@swift.org> wrote:

I don't think submodules would solve it nicely. Each module/submodule
will require it's own namespace + it feels like an overkill to create
submodules for a few types. `internal(xyz)` seems to me like a better
solution. And yes this is purely additional and nothing for phase 1.

--
Adrian Zubarev
Sent with Airmail

Am 9. September 2016 um 19:09:12, Xiaodi Wu (xiaodi.wu@gmail.com)
schrieb:

Isn't the general solution to this problem submodules? In any case,
seems like it'd be out of scope for Swift 4 phase 1.

On Fri, Sep 9, 2016 at 11:34 AM, Adrian Zubarev via swift-evolution < >>>> swift-evolution@swift.org> wrote:

There must be a better solution to this problem, because you might
also extend value types from different files. That would mean, we'd need
`structprivate` `protocolprivate` etc.

How about: `internal(class)` etc. ? Or something like
`internal(private)` to rule them all (I don't like the last name, but
something that would rule them all would be nice to have)!

--
Adrian Zubarev
Sent with Airmail

Am 9. September 2016 um 17:49:29, Tom Bates via swift-evolution (
swift-evolution@swift.org) schrieb:

There is currently no way of accessing "shared code" from extensions
declared outside the base .swift file

I would love to see along side the new fileprivate access level a
classprivate access level that would allow any extension declared outside
of the original .swift file to access these properties and functions in an
attempt to reuse code.

an example is below...

=================
//MyClass.swift
public class MyClass {

classprivate func sharedFunction() {
  self.function1()
  self.function2()
}

fileprivate func function1() {}
fileprivate func function2() {}
}

=================
//MyClass+Save.swift
extension MyClass {

public func save() {
  self.someFunction()
  self.sharedFunction()
}

fileprivate func someFunction() {}
}

Currently to achieve anything like this you would have to make the
"core" functions public or internal or write the whole thing in a single
file which as I understand it is not optimal for the compile speed and can
get unmanageable for large classes. This would allow a more managed file
structure and the separation of related functions from the core declaration.

There would be no migration needed I don't think as the impact on
current code would be zero until the developer adopts the new access level

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

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

_______________________________________________

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

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


(Goffredo Marocchi) #8

I am not fully sure all of this was worth it over protected, private, public... we will see ;).

···

Sent from my iPhone

On 10 Sep 2016, at 13:16, T.J. Usiyan via swift-evolution <swift-evolution@swift.org> wrote:

I am firmly against this. The 5 levels that we have cover us well and have enough complexity already.

On Sat, Sep 10, 2016 at 5:23 AM, Tom Bates via swift-evolution <swift-evolution@swift.org> wrote:
I agree that classprivate would probably not work, maybe constructprivate? but then you are leaving our enum etc.
With the `internal(class)` suggestion, if declaring a var such as `internal(set) var name: String?` would this become `internal(class, set) var name: String?`
Also there would need to be some kind of compile check either way because if you declared an enum for example outside of a constructor you would not be able to mark it as our new constructor only access level or it would become inaccessible throughout the project.

Re: submodules, they are indeed overkill for this. As you would need a separate submodule for each class you wanted to do this with and then run the risk of inter coupling lots of different really small submodules.

Suggestions so far:
`classprivate`
`constructprivate`
`private(instance)`, `private(instance, set)` - problem -> how would this work? `public private(instance, set)`
`internal(class)`

Personally I think a name like `classprivate` or `constructprivate`, although not particularly well named would reduce complexities with private setters syntax and keep migrations much simpler.

On Sat, 10 Sep 2016 at 07:09 Adrian Zubarev via swift-evolution <swift-evolution@swift.org> wrote:
I don't think submodules would solve it nicely. Each module/submodule will require it's own namespace + it feels like an overkill to create submodules for a few types. `internal(xyz)` seems to me like a better solution. And yes this is purely additional and nothing for phase 1.

--
Adrian Zubarev
Sent with Airmail
Am 9. September 2016 um 19:09:12, Xiaodi Wu (xiaodi.wu@gmail.com) schrieb:

Isn't the general solution to this problem submodules? In any case, seems like it'd be out of scope for Swift 4 phase 1.

On Fri, Sep 9, 2016 at 11:34 AM, Adrian Zubarev via swift-evolution <swift-evolution@swift.org> wrote:
There must be a better solution to this problem, because you might also extend value types from different files. That would mean, we'd need `structprivate` `protocolprivate` etc.

How about: `internal(class)` etc. ? Or something like `internal(private)` to rule them all (I don't like the last name, but something that would rule them all would be nice to have)!

--
Adrian Zubarev
Sent with Airmail
Am 9. September 2016 um 17:49:29, Tom Bates via swift-evolution (swift-evolution@swift.org) schrieb:

There is currently no way of accessing "shared code" from extensions declared outside the base .swift file

I would love to see along side the new fileprivate access level a classprivate access level that would allow any extension declared outside of the original .swift file to access these properties and functions in an attempt to reuse code.

an example is below...

=================
//MyClass.swift
public class MyClass {

classprivate func sharedFunction() {
  self.function1()
  self.function2()
}

fileprivate func function1() {}
fileprivate func function2() {}
}

=================
//MyClass+Save.swift
extension MyClass {

public func save() {
  self.someFunction()
  self.sharedFunction()
}

fileprivate func someFunction() {}
}

Currently to achieve anything like this you would have to make the "core" functions public or internal or write the whole thing in a single file which as I understand it is not optimal for the compile speed and can get unmanageable for large classes. This would allow a more managed file structure and the separation of related functions from the core declaration.

There would be no migration needed I don't think as the impact on current code would be zero until the developer adopts the new access level

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

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

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

_______________________________________________
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


(Karl) #9

You can say that again! It seems the compiler has become much stricter about it very recently.

I was recently writing a Tab-bar UIViewcontroller and because I like to keep my internal API clean, I’ve had to stick 4 massive related classes and various extensions in the same file. It’s an unreadable, unmaintainable nightmare.
I would support abolishing the ‘fileprivate’ level for some kind of more loosely-defined virtual scope, such as friend classes or submodules.

OP is correct that Swift is currently incongruous - on the one hand, we have extensions allowing you to break up definitions in to relatable groups, and on the other hand we force you to jam everything in to one file if you want a clean internal API. It feels like they are pulling in opposite directions.

···

On 10 Sep 2016, at 14:16, T.J. Usiyan via swift-evolution <swift-evolution@swift.org> wrote:

I am firmly against this. The 5 levels that we have cover us well and have enough complexity already.


(Rien) #10

I am firmly against this. The 5 levels that we have cover us well and have enough complexity already.

Agree.

···

On 10 Sep 2016, at 14:16, T.J. Usiyan via swift-evolution <swift-evolution@swift.org> wrote:

On Sat, Sep 10, 2016 at 5:23 AM, Tom Bates via swift-evolution <swift-evolution@swift.org> wrote:
I agree that classprivate would probably not work, maybe constructprivate? but then you are leaving our enum etc.
With the `internal(class)` suggestion, if declaring a var such as `internal(set) var name: String?` would this become `internal(class, set) var name: String?`
Also there would need to be some kind of compile check either way because if you declared an enum for example outside of a constructor you would not be able to mark it as our new constructor only access level or it would become inaccessible throughout the project.

Re: submodules, they are indeed overkill for this. As you would need a separate submodule for each class you wanted to do this with and then run the risk of inter coupling lots of different really small submodules.

Suggestions so far:
`classprivate`
`constructprivate`
`private(instance)`, `private(instance, set)` - problem -> how would this work? `public private(instance, set)`
`internal(class)`

Personally I think a name like `classprivate` or `constructprivate`, although not particularly well named would reduce complexities with private setters syntax and keep migrations much simpler.

On Sat, 10 Sep 2016 at 07:09 Adrian Zubarev via swift-evolution <swift-evolution@swift.org> wrote:
I don't think submodules would solve it nicely. Each module/submodule will require it's own namespace + it feels like an overkill to create submodules for a few types. `internal(xyz)` seems to me like a better solution. And yes this is purely additional and nothing for phase 1.

--
Adrian Zubarev
Sent with Airmail
Am 9. September 2016 um 19:09:12, Xiaodi Wu (xiaodi.wu@gmail.com) schrieb:

Isn't the general solution to this problem submodules? In any case, seems like it'd be out of scope for Swift 4 phase 1.

On Fri, Sep 9, 2016 at 11:34 AM, Adrian Zubarev via swift-evolution <swift-evolution@swift.org> wrote:
There must be a better solution to this problem, because you might also extend value types from different files. That would mean, we'd need `structprivate` `protocolprivate` etc.

How about: `internal(class)` etc. ? Or something like `internal(private)` to rule them all (I don't like the last name, but something that would rule them all would be nice to have)!

--
Adrian Zubarev
Sent with Airmail
Am 9. September 2016 um 17:49:29, Tom Bates via swift-evolution (swift-evolution@swift.org) schrieb:

There is currently no way of accessing "shared code" from extensions declared outside the base .swift file

I would love to see along side the new fileprivate access level a classprivate access level that would allow any extension declared outside of the original .swift file to access these properties and functions in an attempt to reuse code.

an example is below...

=================
//MyClass.swift
public class MyClass {

classprivate func sharedFunction() {
  self.function1()
  self.function2()
}

fileprivate func function1() {}
fileprivate func function2() {}
}

=================
//MyClass+Save.swift
extension MyClass {

public func save() {
  self.someFunction()
  self.sharedFunction()
}

fileprivate func someFunction() {}
}

Currently to achieve anything like this you would have to make the "core" functions public or internal or write the whole thing in a single file which as I understand it is not optimal for the compile speed and can get unmanageable for large classes. This would allow a more managed file structure and the separation of related functions from the core declaration.

There would be no migration needed I don't think as the impact on current code would be zero until the developer adopts the new access level

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

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

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

_______________________________________________
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


#11

Indeed, I find it rather less convenient to write “fileprivate” in many
places I previously would use “private”, and unfortunate that I must choose
between aggregating many pieces into a single lengthy file or else
polluting the module scope with implementation details.

I agree with Xiaodi that submodules are a far cleaner design, and I would
very much like to replace “fileprivate” with a short word that implies
“private to the submodule”. Then by default each file could be its own
submodule, and a developer could opt into having more files in a submodule
if they so desire.

Count me as opposed to any sort of “class scoped” access level.

Nevin

···

On Sat, Sep 10, 2016 at 10:01 AM, Rien via swift-evolution < swift-evolution@swift.org> wrote:

> On 10 Sep 2016, at 14:16, T.J. Usiyan via swift-evolution < > swift-evolution@swift.org> wrote:
>
> I am firmly against this. The 5 levels that we have cover us well and
have enough complexity already.

Agree.

> On Sat, Sep 10, 2016 at 5:23 AM, Tom Bates via swift-evolution < > swift-evolution@swift.org> wrote:
> I agree that classprivate would probably not work, maybe
constructprivate? but then you are leaving our enum etc.
> With the `internal(class)` suggestion, if declaring a var such as
`internal(set) var name: String?` would this become `internal(class, set)
var name: String?`
> Also there would need to be some kind of compile check either way
because if you declared an enum for example outside of a constructor you
would not be able to mark it as our new constructor only access level or it
would become inaccessible throughout the project.
>
> Re: submodules, they are indeed overkill for this. As you would need a
separate submodule for each class you wanted to do this with and then run
the risk of inter coupling lots of different really small submodules.
>
> Suggestions so far:
> `classprivate`
> `constructprivate`
> `private(instance)`, `private(instance, set)` - problem -> how would
this work? `public private(instance, set)`
> `internal(class)`
>
> Personally I think a name like `classprivate` or `constructprivate`,
although not particularly well named would reduce complexities with private
setters syntax and keep migrations much simpler.
>
>
> On Sat, 10 Sep 2016 at 07:09 Adrian Zubarev via swift-evolution < > swift-evolution@swift.org> wrote:
> I don't think submodules would solve it nicely. Each module/submodule
will require it's own namespace + it feels like an overkill to create
submodules for a few types. `internal(xyz)` seems to me like a better
solution. And yes this is purely additional and nothing for phase 1.
>
> --
> Adrian Zubarev
> Sent with Airmail
> Am 9. September 2016 um 19:09:12, Xiaodi Wu (xiaodi.wu@gmail.com)
schrieb:
>
>> Isn't the general solution to this problem submodules? In any case,
seems like it'd be out of scope for Swift 4 phase 1.
>>
>>
>> On Fri, Sep 9, 2016 at 11:34 AM, Adrian Zubarev via swift-evolution < > swift-evolution@swift.org> wrote:
>> There must be a better solution to this problem, because you might also
extend value types from different files. That would mean, we'd need
`structprivate` `protocolprivate` etc.
>>
>> How about: `internal(class)` etc. ? Or something like
`internal(private)` to rule them all (I don't like the last name, but
something that would rule them all would be nice to have)!
>>
>>
>> --
>> Adrian Zubarev
>> Sent with Airmail
>> Am 9. September 2016 um 17:49:29, Tom Bates via swift-evolution (
swift-evolution@swift.org) schrieb:
>>
>>> There is currently no way of accessing "shared code" from extensions
declared outside the base .swift file
>>>
>>> I would love to see along side the new fileprivate access level a
classprivate access level that would allow any extension declared outside
of the original .swift file to access these properties and functions in an
attempt to reuse code.
>>>
>>> an example is below...
>>>
>>> =================
>>> //MyClass.swift
>>> public class MyClass {
>>>
>>> classprivate func sharedFunction() {
>>> self.function1()
>>> self.function2()
>>> }
>>>
>>> fileprivate func function1() {}
>>> fileprivate func function2() {}
>>> }
>>> =================
>>>
>>> =================
>>> //MyClass+Save.swift
>>> extension MyClass {
>>>
>>> public func save() {
>>> self.someFunction()
>>> self.sharedFunction()
>>> }
>>>
>>> fileprivate func someFunction() {}
>>> }
>>> =================
>>>
>>> Currently to achieve anything like this you would have to make the
"core" functions public or internal or write the whole thing in a single
file which as I understand it is not optimal for the compile speed and can
get unmanageable for large classes. This would allow a more managed file
structure and the separation of related functions from the core declaration.
>>>
>>> There would be no migration needed I don't think as the impact on
current code would be zero until the developer adopts the new access level
>>>
>>> Regards,
>>> Tom
>>> _______________________________________________
>>> swift-evolution mailing list
>>> swift-evolution@swift.org
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
>>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

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


(Xiaodi Wu) #12

Agreed.

Swift's access levels are deliberately defined in terms of contiguous
blocks of written code [this is inelegantly phrased, but I think you see
what I mean]. As such, neither a "class scoped" level nor a level shared
between a type and its extensions would fit in such a scheme.

Such an addition would fundamentally counter the existing design of Swift,
open the door for compensating features such as "friend classes" that
(IIUC) were deliberately avoided, and fails to compose with existing access
levels as inevitably there will be proposals to do. By that I mean, why
should a "class scoped" member always be limited in visibility to the same
module? This satisfies your particular motivating use case, but someone
else will want the same kind of class scoping but also allow a member to be
accessed by extensions outside the module (classpublic, if you will); still
others will want a member to be overridable outside the module (classopen);
for good measure, some will want access limited to only extensions and not
other types in the same file (classfileprivate; it is not out of the
question for someone to raise this point, since it is a close cousin of the
argument for distinguishing private and fileprivate).

If I had my druthers, it'd be nice to have exactly something like Nevin's
idea, a terse way to group related files into submodules, and a keyword
like `subinternal` that restricts visibility to that group of files. It
would satisfy the motivating use case here while preserving the deliberate
design decision that Swift access levels do not pick and choose
non-contiguous chunks of multiple files.

In any case, let's postpone this discussion until it comes into scope at a
later phase of Swift evolution. The core team and other experts would no
doubt have much to contribute at that time.

···

On Sat, Sep 10, 2016 at 09:31 Nevin Brackett-Rozinsky via swift-evolution < swift-evolution@swift.org> wrote:

Indeed, I find it rather less convenient to write “fileprivate” in many
places I previously would use “private”, and unfortunate that I must choose
between aggregating many pieces into a single lengthy file or else
polluting the module scope with implementation details.

I agree with Xiaodi that submodules are a far cleaner design, and I would
very much like to replace “fileprivate” with a short word that implies
“private to the submodule”. Then by default each file could be its own
submodule, and a developer could opt into having more files in a submodule
if they so desire.

Count me as opposed to any sort of “class scoped” access level.

Nevin

On Sat, Sep 10, 2016 at 10:01 AM, Rien via swift-evolution < > swift-evolution@swift.org> wrote:

> On 10 Sep 2016, at 14:16, T.J. Usiyan via swift-evolution < >> swift-evolution@swift.org> wrote:
>
> I am firmly against this. The 5 levels that we have cover us well and
have enough complexity already.

Agree.

> On Sat, Sep 10, 2016 at 5:23 AM, Tom Bates via swift-evolution < >> swift-evolution@swift.org> wrote:
> I agree that classprivate would probably not work, maybe
constructprivate? but then you are leaving our enum etc.
> With the `internal(class)` suggestion, if declaring a var such as
`internal(set) var name: String?` would this become `internal(class, set)
var name: String?`
> Also there would need to be some kind of compile check either way
because if you declared an enum for example outside of a constructor you
would not be able to mark it as our new constructor only access level or it
would become inaccessible throughout the project.
>
> Re: submodules, they are indeed overkill for this. As you would need a
separate submodule for each class you wanted to do this with and then run
the risk of inter coupling lots of different really small submodules.
>
> Suggestions so far:
> `classprivate`
> `constructprivate`
> `private(instance)`, `private(instance, set)` - problem -> how would
this work? `public private(instance, set)`
> `internal(class)`
>
> Personally I think a name like `classprivate` or `constructprivate`,
although not particularly well named would reduce complexities with private
setters syntax and keep migrations much simpler.
>
>
> On Sat, 10 Sep 2016 at 07:09 Adrian Zubarev via swift-evolution < >> swift-evolution@swift.org> wrote:
> I don't think submodules would solve it nicely. Each module/submodule
will require it's own namespace + it feels like an overkill to create
submodules for a few types. `internal(xyz)` seems to me like a better
solution. And yes this is purely additional and nothing for phase 1.
>
> --
> Adrian Zubarev
> Sent with Airmail
> Am 9. September 2016 um 19:09:12, Xiaodi Wu (xiaodi.wu@gmail.com)
schrieb:
>
>> Isn't the general solution to this problem submodules? In any case,
seems like it'd be out of scope for Swift 4 phase 1.
>>
>>
>> On Fri, Sep 9, 2016 at 11:34 AM, Adrian Zubarev via swift-evolution < >> swift-evolution@swift.org> wrote:
>> There must be a better solution to this problem, because you might
also extend value types from different files. That would mean, we'd need
`structprivate` `protocolprivate` etc.
>>
>> How about: `internal(class)` etc. ? Or something like
`internal(private)` to rule them all (I don't like the last name, but
something that would rule them all would be nice to have)!
>>
>>
>> --
>> Adrian Zubarev
>> Sent with Airmail
>> Am 9. September 2016 um 17:49:29, Tom Bates via swift-evolution (
swift-evolution@swift.org) schrieb:
>>
>>> There is currently no way of accessing "shared code" from extensions
declared outside the base .swift file
>>>
>>> I would love to see along side the new fileprivate access level a
classprivate access level that would allow any extension declared outside
of the original .swift file to access these properties and functions in an
attempt to reuse code.
>>>
>>> an example is below...
>>>
>>> =================
>>> //MyClass.swift
>>> public class MyClass {
>>>
>>> classprivate func sharedFunction() {
>>> self.function1()
>>> self.function2()
>>> }
>>>
>>> fileprivate func function1() {}
>>> fileprivate func function2() {}
>>> }
>>> =================
>>>
>>> =================
>>> //MyClass+Save.swift
>>> extension MyClass {
>>>
>>> public func save() {
>>> self.someFunction()
>>> self.sharedFunction()
>>> }
>>>
>>> fileprivate func someFunction() {}
>>> }
>>> =================
>>>
>>> Currently to achieve anything like this you would have to make the
"core" functions public or internal or write the whole thing in a single
file which as I understand it is not optimal for the compile speed and can
get unmanageable for large classes. This would allow a more managed file
structure and the separation of related functions from the core declaration.
>>>
>>> There would be no migration needed I don't think as the impact on
current code would be zero until the developer adopts the new access level
>>>
>>> Regards,
>>> Tom
>>> _______________________________________________
>>> swift-evolution mailing list
>>> swift-evolution@swift.org
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
>>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

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

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


(Paul Cantrell) #13

I do certainly agree that 5 access levels are _plenty_, C++ “friend” is no great friend to me, and I too not want to see another one access level added. However, I do think there’s a related problem here worth solving.

Sometimes, trying to break apart a large type using extensions, I encounter this pattern:

class Thingamer {
    private var doodads: [Doodad]

    // All of these use the doodads var:

    public func mangleDoodads() { … }
    public func fungeDoodads() { … }
    public func renoberateDoodads() { … }
    private func doodadHelper() { … }

    // …and no other methods touch it
}

My first instinct in this situation is to pull all the doodad-related stuff into a separate type, but sometimes that’s the wrong solution. Perhaps the public API gets messy or nonsensical if those public doodad-related methods aren’t on Thingamer. Perhaps other Thingamer methods use those doodad methods, even if they don’t use the private var. Perhaps there’s still coupling to Thingamer through other class properties. And so forth.

It would be great to group all the doodad-stuff into an extension. The inability of extensions to use class-private vars is the barrier. My usual solution is to make the doodads var internal, and then try to remember not to use it outside of the extension — which looks a lot like “fake friend”.

It would be nice if Swift extensions let us encapsulate state+behavior relationships without having to create new type boundaries.

IIRC, there was talk of extensions being able to add properties to an existing type. It seems like this would be feasible, at least for types within the same module? Perhaps there’s another better way?

Cheers,

Paul

···

On Sep 10, 2016, at 11:28 AM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

Agreed.

Swift's access levels are deliberately defined in terms of contiguous blocks of written code [this is inelegantly phrased, but I think you see what I mean]. As such, neither a "class scoped" level nor a level shared between a type and its extensions would fit in such a scheme.

Such an addition would fundamentally counter the existing design of Swift, open the door for compensating features such as "friend classes" that (IIUC) were deliberately avoided, and fails to compose with existing access levels as inevitably there will be proposals to do. By that I mean, why should a "class scoped" member always be limited in visibility to the same module? This satisfies your particular motivating use case, but someone else will want the same kind of class scoping but also allow a member to be accessed by extensions outside the module (classpublic, if you will); still others will want a member to be overridable outside the module (classopen); for good measure, some will want access limited to only extensions and not other types in the same file (classfileprivate; it is not out of the question for someone to raise this point, since it is a close cousin of the argument for distinguishing private and fileprivate).

If I had my druthers, it'd be nice to have exactly something like Nevin's idea, a terse way to group related files into submodules, and a keyword like `subinternal` that restricts visibility to that group of files. It would satisfy the motivating use case here while preserving the deliberate design decision that Swift access levels do not pick and choose non-contiguous chunks of multiple files.

In any case, let's postpone this discussion until it comes into scope at a later phase of Swift evolution. The core team and other experts would no doubt have much to contribute at that time.

On Sat, Sep 10, 2016 at 09:31 Nevin Brackett-Rozinsky via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Indeed, I find it rather less convenient to write “fileprivate” in many places I previously would use “private”, and unfortunate that I must choose between aggregating many pieces into a single lengthy file or else polluting the module scope with implementation details.

I agree with Xiaodi that submodules are a far cleaner design, and I would very much like to replace “fileprivate” with a short word that implies “private to the submodule”. Then by default each file could be its own submodule, and a developer could opt into having more files in a submodule if they so desire.

Count me as opposed to any sort of “class scoped” access level.

Nevin

On Sat, Sep 10, 2016 at 10:01 AM, Rien via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
> On 10 Sep 2016, at 14:16, T.J. Usiyan via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>
> I am firmly against this. The 5 levels that we have cover us well and have enough complexity already.

Agree.

> On Sat, Sep 10, 2016 at 5:23 AM, Tom Bates via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
> I agree that classprivate would probably not work, maybe constructprivate? but then you are leaving our enum etc.
> With the `internal(class)` suggestion, if declaring a var such as `internal(set) var name: String?` would this become `internal(class, set) var name: String?`
> Also there would need to be some kind of compile check either way because if you declared an enum for example outside of a constructor you would not be able to mark it as our new constructor only access level or it would become inaccessible throughout the project.
>
> Re: submodules, they are indeed overkill for this. As you would need a separate submodule for each class you wanted to do this with and then run the risk of inter coupling lots of different really small submodules.
>
> Suggestions so far:
> `classprivate`
> `constructprivate`
> `private(instance)`, `private(instance, set)` - problem -> how would this work? `public private(instance, set)`
> `internal(class)`
>
> Personally I think a name like `classprivate` or `constructprivate`, although not particularly well named would reduce complexities with private setters syntax and keep migrations much simpler.
>
>
> On Sat, 10 Sep 2016 at 07:09 Adrian Zubarev via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
> I don't think submodules would solve it nicely. Each module/submodule will require it's own namespace + it feels like an overkill to create submodules for a few types. `internal(xyz)` seems to me like a better solution. And yes this is purely additional and nothing for phase 1.
>
> --
> Adrian Zubarev
> Sent with Airmail
> Am 9. September 2016 um 19:09:12, Xiaodi Wu (xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>) schrieb:
>
>> Isn't the general solution to this problem submodules? In any case, seems like it'd be out of scope for Swift 4 phase 1.
>>
>>
>> On Fri, Sep 9, 2016 at 11:34 AM, Adrian Zubarev via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>> There must be a better solution to this problem, because you might also extend value types from different files. That would mean, we'd need `structprivate` `protocolprivate` etc.
>>
>> How about: `internal(class)` etc. ? Or something like `internal(private)` to rule them all (I don't like the last name, but something that would rule them all would be nice to have)!
>>
>>
>> --
>> Adrian Zubarev
>> Sent with Airmail
>> Am 9. September 2016 um 17:49:29, Tom Bates via swift-evolution (swift-evolution@swift.org <mailto:swift-evolution@swift.org>) schrieb:
>>
>>> There is currently no way of accessing "shared code" from extensions declared outside the base .swift file
>>>
>>> I would love to see along side the new fileprivate access level a classprivate access level that would allow any extension declared outside of the original .swift file to access these properties and functions in an attempt to reuse code.
>>>
>>> an example is below...
>>>
>>> =================
>>> //MyClass.swift
>>> public class MyClass {
>>>
>>> classprivate func sharedFunction() {
>>> self.function1()
>>> self.function2()
>>> }
>>>
>>> fileprivate func function1() {}
>>> fileprivate func function2() {}
>>> }
>>> =================
>>>
>>> =================
>>> //MyClass+Save.swift
>>> extension MyClass {
>>>
>>> public func save() {
>>> self.someFunction()
>>> self.sharedFunction()
>>> }
>>>
>>> fileprivate func someFunction() {}
>>> }
>>> =================
>>>
>>> Currently to achieve anything like this you would have to make the "core" functions public or internal or write the whole thing in a single file which as I understand it is not optimal for the compile speed and can get unmanageable for large classes. This would allow a more managed file structure and the separation of related functions from the core declaration.
>>>
>>> There would be no migration needed I don't think as the impact on current code would be zero until the developer adopts the new access level
>>>
>>> Regards,
>>> Tom
>>> _______________________________________________
>>> 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
>>
>>
> _______________________________________________
> 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
>
>
> _______________________________________________
> 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

_______________________________________________
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


(Xiaodi Wu) #14

Is that (i.e. having properties in extensions) listed in the completing
generics manifesto? It certainly seems like it'd be a worthwhile feature to
consider under that umbrella.

The one place where it will complicate matters is in the use of protocol
extensions as traits, since what I know of traits is that they should not
encapsulate state.

···

On Sat, Sep 10, 2016 at 14:13 Paul Cantrell <cantrell@pobox.com> wrote:

I do certainly agree that 5 access levels are _plenty_, C++ “friend” is no
great friend to me, and I too not want to see another one access level
added. However, I do think there’s a related problem here worth solving.

Sometimes, trying to break apart a large type using extensions, I
encounter this pattern:

class Thingamer {
    private var doodads: [Doodad]

    // All of these use the doodads var:

    public func mangleDoodads() { … }
    public func fungeDoodads() { … }
    public func renoberateDoodads() { … }
    private func doodadHelper() { … }

    // …and no other methods touch it
}

My first instinct in this situation is to pull all the doodad-related
stuff into a separate type, but sometimes that’s the wrong solution.
Perhaps the public API gets messy or nonsensical if those public
doodad-related methods aren’t on Thingamer. Perhaps other Thingamer methods
use those doodad methods, even if they don’t use the private var. Perhaps
there’s still coupling to Thingamer through other class properties. And so
forth.

It would be great to group all the doodad-stuff into an extension. The
inability of extensions to use class-private vars is the barrier. My usual
solution is to make the doodads var internal, and then try to remember not
to use it outside of the extension — which looks a lot like “fake friend”.

It would be nice if Swift extensions let us encapsulate state+behavior
relationships without having to create new type boundaries.

IIRC, there was talk of extensions being able to add properties to an
existing type. It seems like this would be feasible, at least for types
within the same module? Perhaps there’s another better way?

Cheers,

Paul

On Sep 10, 2016, at 11:28 AM, Xiaodi Wu via swift-evolution < > swift-evolution@swift.org> wrote:

Agreed.

Swift's access levels are deliberately defined in terms of contiguous
blocks of written code [this is inelegantly phrased, but I think you see
what I mean]. As such, neither a "class scoped" level nor a level shared
between a type and its extensions would fit in such a scheme.

Such an addition would fundamentally counter the existing design of Swift,
open the door for compensating features such as "friend classes" that
(IIUC) were deliberately avoided, and fails to compose with existing access
levels as inevitably there will be proposals to do. By that I mean, why
should a "class scoped" member always be limited in visibility to the same
module? This satisfies your particular motivating use case, but someone
else will want the same kind of class scoping but also allow a member to be
accessed by extensions outside the module (classpublic, if you will); still
others will want a member to be overridable outside the module (classopen);
for good measure, some will want access limited to only extensions and not
other types in the same file (classfileprivate; it is not out of the
question for someone to raise this point, since it is a close cousin of the
argument for distinguishing private and fileprivate).

If I had my druthers, it'd be nice to have exactly something like Nevin's
idea, a terse way to group related files into submodules, and a keyword
like `subinternal` that restricts visibility to that group of files. It
would satisfy the motivating use case here while preserving the deliberate
design decision that Swift access levels do not pick and choose
non-contiguous chunks of multiple files.

In any case, let's postpone this discussion until it comes into scope at a
later phase of Swift evolution. The core team and other experts would no
doubt have much to contribute at that time.

On Sat, Sep 10, 2016 at 09:31 Nevin Brackett-Rozinsky via swift-evolution < > swift-evolution@swift.org> wrote:

Indeed, I find it rather less convenient to write “fileprivate” in many
places I previously would use “private”, and unfortunate that I must choose
between aggregating many pieces into a single lengthy file or else
polluting the module scope with implementation details.

I agree with Xiaodi that submodules are a far cleaner design, and I would
very much like to replace “fileprivate” with a short word that implies
“private to the submodule”. Then by default each file could be its own
submodule, and a developer could opt into having more files in a submodule
if they so desire.

Count me as opposed to any sort of “class scoped” access level.

Nevin

On Sat, Sep 10, 2016 at 10:01 AM, Rien via swift-evolution < >> swift-evolution@swift.org> wrote:

> On 10 Sep 2016, at 14:16, T.J. Usiyan via swift-evolution < >>> swift-evolution@swift.org> wrote:
>
> I am firmly against this. The 5 levels that we have cover us well and
have enough complexity already.

Agree.

> On Sat, Sep 10, 2016 at 5:23 AM, Tom Bates via swift-evolution < >>> swift-evolution@swift.org> wrote:
> I agree that classprivate would probably not work, maybe
constructprivate? but then you are leaving our enum etc.
> With the `internal(class)` suggestion, if declaring a var such as
`internal(set) var name: String?` would this become `internal(class, set)
var name: String?`
> Also there would need to be some kind of compile check either way
because if you declared an enum for example outside of a constructor you
would not be able to mark it as our new constructor only access level or it
would become inaccessible throughout the project.
>
> Re: submodules, they are indeed overkill for this. As you would need a
separate submodule for each class you wanted to do this with and then run
the risk of inter coupling lots of different really small submodules.
>
> Suggestions so far:
> `classprivate`
> `constructprivate`
> `private(instance)`, `private(instance, set)` - problem -> how would
this work? `public private(instance, set)`
> `internal(class)`
>
> Personally I think a name like `classprivate` or `constructprivate`,
although not particularly well named would reduce complexities with private
setters syntax and keep migrations much simpler.
>
>
> On Sat, 10 Sep 2016 at 07:09 Adrian Zubarev via swift-evolution < >>> swift-evolution@swift.org> wrote:
> I don't think submodules would solve it nicely. Each module/submodule
will require it's own namespace + it feels like an overkill to create
submodules for a few types. `internal(xyz)` seems to me like a better
solution. And yes this is purely additional and nothing for phase 1.
>
> --
> Adrian Zubarev
> Sent with Airmail
> Am 9. September 2016 um 19:09:12, Xiaodi Wu (xiaodi.wu@gmail.com)
schrieb:
>
>> Isn't the general solution to this problem submodules? In any case,
seems like it'd be out of scope for Swift 4 phase 1.
>>
>>
>> On Fri, Sep 9, 2016 at 11:34 AM, Adrian Zubarev via swift-evolution < >>> swift-evolution@swift.org> wrote:
>> There must be a better solution to this problem, because you might
also extend value types from different files. That would mean, we'd need
`structprivate` `protocolprivate` etc.
>>
>> How about: `internal(class)` etc. ? Or something like
`internal(private)` to rule them all (I don't like the last name, but
something that would rule them all would be nice to have)!
>>
>>
>> --
>> Adrian Zubarev
>> Sent with Airmail
>> Am 9. September 2016 um 17:49:29, Tom Bates via swift-evolution (
swift-evolution@swift.org) schrieb:
>>
>>> There is currently no way of accessing "shared code" from extensions
declared outside the base .swift file
>>>
>>> I would love to see along side the new fileprivate access level a
classprivate access level that would allow any extension declared outside
of the original .swift file to access these properties and functions in an
attempt to reuse code.
>>>
>>> an example is below...
>>>
>>> =================
>>> //MyClass.swift
>>> public class MyClass {
>>>
>>> classprivate func sharedFunction() {
>>> self.function1()
>>> self.function2()
>>> }
>>>
>>> fileprivate func function1() {}
>>> fileprivate func function2() {}
>>> }
>>> =================
>>>
>>> =================
>>> //MyClass+Save.swift
>>> extension MyClass {
>>>
>>> public func save() {
>>> self.someFunction()
>>> self.sharedFunction()
>>> }
>>>
>>> fileprivate func someFunction() {}
>>> }
>>> =================
>>>
>>> Currently to achieve anything like this you would have to make the
"core" functions public or internal or write the whole thing in a single
file which as I understand it is not optimal for the compile speed and can
get unmanageable for large classes. This would allow a more managed file
structure and the separation of related functions from the core declaration.
>>>
>>> There would be no migration needed I don't think as the impact on
current code would be zero until the developer adopts the new access level
>>>
>>> Regards,
>>> Tom
>>> _______________________________________________
>>> swift-evolution mailing list
>>> swift-evolution@swift.org
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
>>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

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

_______________________________________________
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


(Charles Srstka) #15

I think that came up at some point, but was deemed not to be implementable in a sufficiently performant way.

Charles

···

On Sep 10, 2016, at 2:52 PM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

Is that (i.e. having properties in extensions) listed in the completing generics manifesto? It certainly seems like it'd be a worthwhile feature to consider under that umbrella.


(Paul Cantrell) #16

It seems like it ought to be implementable for _in-module_ extensions, since presumably the memory layout of each type is fungible until the module is compiled.

In-module extensions address the use case I had in mind, namely breaking apart a large type by isolating some private properties within extensions. It seems like the possible and the desirable may actually intersect here.

P

···

On Sep 10, 2016, at 5:25 PM, Charles Srstka <cocoadev@charlessoft.com> wrote:

On Sep 10, 2016, at 2:52 PM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Is that (i.e. having properties in extensions) listed in the completing generics manifesto? It certainly seems like it'd be a worthwhile feature to consider under that umbrella.

I think that came up at some point, but was deemed not to be implementable in a sufficiently performant way.