continuations - "extensions on steroids" idea

a general feeling that there are two very different use cases of extensions
-- one to extend own classes and another to extend other people classes; a
lengthy discussion in a nearby thread; a disparity of features of class and
it's extensions and different access right treatment depending upon whether
the extension is in the same with the main class or a different file lead
me to the following idea. hopefully you will find this idea useful and we
may even see it one day in swift.

introducing class / struct / enum continuations.

in a few words the are:

1) "extensions on steroids". in fact very similar to Objective-C "class
extensions" but can be more than one and in more than one file.

2) as good as the classes they continue (or other continuations they
continue)

3) can declare variables

4) have full access to "private" members of the class or other continuations
regardless whether they are in the same or in a different files. no need
for "public/internal/module" fallbacks to pass though files boundaries.
similarly the class itself can use private members of its continuations.

5) "by invitation only" system. can only be written if declared by the
class or some continuation of it.

6) A particular continuation only defined once (of course). There can be an
arbitrary number of different continuations to a class similar to
extensions.

7) alternative name considered: "extending" (as a noun). shall definitely
be a different name than say, "extension" with some bracket-syntax
variation - the two use cases are very different and shall be named
differently.

8) the particular syntax is preliminary of course.

example:

============= Some.swift ==================

class Some {

    private func private_method_of_class() {

        // *** can use private methods of continuations even if they are in
a different file
        private_method_defined_in_a_continuation()
    }

    // *** "by invitation" system

    continuation Feature // *** declaring a continuation
    continuation SomethingElse // *** Capitalized names, like classes
}

============= Some-Feature.swift ==================

// *** similar naming convetion to "Some+Feature.swift"
// used for extensions, just with "-" instead

// *** this is merely a naming convention, no need to
necessarily follow it, can put more than one thing into
a file, the continuation can reside in the same file as
the main class fie, etc.

continuation Feature of Some {

// *** as good as class itself. first-class citizen
// *** same syntax can be used for structs and enums

    var x: Int // *** can declare variables

    private func private_method_defined_in_a_continuation() {
        private_method_of_class()

        // *** can use private methods of the class or of other
continuations even if they are in a different file
    }

    // *** continuations are as good as classes and can
    // *** declare other continuations if needed

    continuation CanDoThis
}

============= Any file ==================

continuation Feature of Some { // *** error, continuation is already defined
}

continuation Other of Some { // *** error: Other is not a continuation of
Some
}

thoughts?

Mike

1 Like

This I actually support. In C# the same concept exists in the form of partial classes. A class must be declared as partial everywhere in order to support it. It only works within a single assembly (similar to a module).

There are a few important use cases for this in C#:

1. Code generation. For instance, Interface Builder could modify a separate file for things like outlets and actions, and it could freely wipe and regenerate that file from scratch without touching any of your own code. Some people also generate parts of classes from templates while filling in the rest in another file.

2. Cross platform code. A common strategy in C# is to have a class split into parts, where one part is compiled on all platforms, and the other files are each specific to one platform or another. For instance, you may have Foo.swift, Foo.macOS.swift, and Foo.iOS.swift. Foo.swift would be compiled on both platforms, but then the iOS build would only include Foo.iOS.swift. This is a preferred alternative to using #ifs.

3. The use case Mike described. Sometimes we fail at making classes small, or maybe someone else failed and we’re stuck with it. Splitting a single class into pieces can be useful to organize cohesive chunks. That’s not something I tend to encourage as a design pattern, but it still happens anyway.

A related feature in C# is partial methods, which are just void-returning methods that have been declared as partial without an implementation. If an implementation is provided by another file (in another part of the partial class) then it is used. If no file provides an implementation then calls to that method are just stripped out by the compiler. This is also commonly used for cross-platform code. Maybe one platform needs to do something at a particular time but another doesn’t. Rather than using #ifs or having empty stubs in other platforms you can declare it partial and provide an implementation on just the one platform that needs it.

···

On Oct 30, 2017, at 6:12 PM, Mike Kluev via swift-evolution <swift-evolution@swift.org> wrote:

a general feeling that there are two very different use cases of extensions -- one to extend own classes and another to extend other people classes; a lengthy discussion in a nearby thread; a disparity of features of class and it's extensions and different access right treatment depending upon whether the extension is in the same with the main class or a different file lead me to the following idea. hopefully you will find this idea useful and we may even see it one day in swift.

introducing class / struct / enum continuations.

in a few words the are:

1) "extensions on steroids". in fact very similar to Objective-C "class extensions" but can be more than one and in more than one file.

2) as good as the classes they continue (or other continuations they continue)

3) can declare variables

4) have full access to "private" members of the class or other continuations
regardless whether they are in the same or in a different files. no need for "public/internal/module" fallbacks to pass though files boundaries. similarly the class itself can use private members of its continuations.

5) "by invitation only" system. can only be written if declared by the class or some continuation of it.

6) A particular continuation only defined once (of course). There can be an arbitrary number of different continuations to a class similar to extensions.

7) alternative name considered: "extending" (as a noun). shall definitely be a different name than say, "extension" with some bracket-syntax variation - the two use cases are very different and shall be named differently.

8) the particular syntax is preliminary of course.

example:

============= Some.swift ==================

class Some {

    private func private_method_of_class() {

        // *** can use private methods of continuations even if they are in a different file
        private_method_defined_in_a_continuation()
    }
    
    // *** "by invitation" system

    continuation Feature // *** declaring a continuation
    continuation SomethingElse // *** Capitalized names, like classes
}

============= Some-Feature.swift ==================

// *** similar naming convetion to "Some+Feature.swift"
// used for extensions, just with "-" instead

// *** this is merely a naming convention, no need to
necessarily follow it, can put more than one thing into
a file, the continuation can reside in the same file as
the main class fie, etc.

continuation Feature of Some {

// *** as good as class itself. first-class citizen
// *** same syntax can be used for structs and enums

    var x: Int // *** can declare variables
    
    private func private_method_defined_in_a_continuation() {
        private_method_of_class()

        // *** can use private methods of the class or of other
continuations even if they are in a different file
    }
    
    // *** continuations are as good as classes and can
    // *** declare other continuations if needed

    continuation CanDoThis
}

============= Any file ==================

continuation Feature of Some { // *** error, continuation is already defined
}

continuation Other of Some { // *** error: Other is not a continuation of Some
}

thoughts?

Mike

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

1 Like

I like the IB use case :).

···

Sent from my iPhone

On 31 Oct 2017, at 03:22, Adam Kemp via swift-evolution <swift-evolution@swift.org> wrote:

This I actually support. In C# the same concept exists in the form of partial classes. A class must be declared as partial everywhere in order to support it. It only works within a single assembly (similar to a module).

There are a few important use cases for this in C#:

1. Code generation. For instance, Interface Builder could modify a separate file for things like outlets and actions, and it could freely wipe and regenerate that file from scratch without touching any of your own code. Some people also generate parts of classes from templates while filling in the rest in another file.

2. Cross platform code. A common strategy in C# is to have a class split into parts, where one part is compiled on all platforms, and the other files are each specific to one platform or another. For instance, you may have Foo.swift, Foo.macOS.swift, and Foo.iOS.swift. Foo.swift would be compiled on both platforms, but then the iOS build would only include Foo.iOS.swift. This is a preferred alternative to using #ifs.

3. The use case Mike described. Sometimes we fail at making classes small, or maybe someone else failed and we’re stuck with it. Splitting a single class into pieces can be useful to organize cohesive chunks. That’s not something I tend to encourage as a design pattern, but it still happens anyway.

A related feature in C# is partial methods, which are just void-returning methods that have been declared as partial without an implementation. If an implementation is provided by another file (in another part of the partial class) then it is used. If no file provides an implementation then calls to that method are just stripped out by the compiler. This is also commonly used for cross-platform code. Maybe one platform needs to do something at a particular time but another doesn’t. Rather than using #ifs or having empty stubs in other platforms you can declare it partial and provide an implementation on just the one platform that needs it.

On Oct 30, 2017, at 6:12 PM, Mike Kluev via swift-evolution <swift-evolution@swift.org> wrote:

a general feeling that there are two very different use cases of extensions -- one to extend own classes and another to extend other people classes; a lengthy discussion in a nearby thread; a disparity of features of class and it's extensions and different access right treatment depending upon whether the extension is in the same with the main class or a different file lead me to the following idea. hopefully you will find this idea useful and we may even see it one day in swift.

introducing class / struct / enum continuations.

in a few words the are:

1) "extensions on steroids". in fact very similar to Objective-C "class extensions" but can be more than one and in more than one file.

2) as good as the classes they continue (or other continuations they continue)

3) can declare variables

4) have full access to "private" members of the class or other continuations
regardless whether they are in the same or in a different files. no need for "public/internal/module" fallbacks to pass though files boundaries. similarly the class itself can use private members of its continuations.

5) "by invitation only" system. can only be written if declared by the class or some continuation of it.

6) A particular continuation only defined once (of course). There can be an arbitrary number of different continuations to a class similar to extensions.

7) alternative name considered: "extending" (as a noun). shall definitely be a different name than say, "extension" with some bracket-syntax variation - the two use cases are very different and shall be named differently.

8) the particular syntax is preliminary of course.

example:

============= Some.swift ==================

class Some {

   private func private_method_of_class() {

       // *** can use private methods of continuations even if they are in a different file
       private_method_defined_in_a_continuation()
   }

   // *** "by invitation" system

   continuation Feature // *** declaring a continuation
   continuation SomethingElse // *** Capitalized names, like classes
}

============= Some-Feature.swift ==================

// *** similar naming convetion to "Some+Feature.swift"
// used for extensions, just with "-" instead

// *** this is merely a naming convention, no need to
necessarily follow it, can put more than one thing into
a file, the continuation can reside in the same file as
the main class fie, etc.

continuation Feature of Some {

// *** as good as class itself. first-class citizen
// *** same syntax can be used for structs and enums

   var x: Int // *** can declare variables

   private func private_method_defined_in_a_continuation() {
       private_method_of_class()

       // *** can use private methods of the class or of other
continuations even if they are in a different file
   }

   // *** continuations are as good as classes and can
   // *** declare other continuations if needed

   continuation CanDoThis
}

============= Any file ==================

continuation Feature of Some { // *** error, continuation is already defined
}

continuation Other of Some { // *** error: Other is not a continuation of Some
}

thoughts?

Mike

_______________________________________________
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

"Continuation" already means something else in computer programming. I would suggest you find another term.

···

On Oct 30, 2017, at 6:12 PM, Mike Kluev via swift-evolution <swift-evolution@swift.org> wrote:

a general feeling that there are two very different use cases of extensions -- one to extend own classes and another to extend other people classes; a lengthy discussion in a nearby thread; a disparity of features of class and it's extensions and different access right treatment depending upon whether the extension is in the same with the main class or a different file lead me to the following idea. hopefully you will find this idea useful and we may even see it one day in swift.

introducing class / struct / enum continuations.

in a few words the are:

1) "extensions on steroids". in fact very similar to Objective-C "class extensions" but can be more than one and in more than one file.

2) as good as the classes they continue (or other continuations they continue)

3) can declare variables

4) have full access to "private" members of the class or other continuations
regardless whether they are in the same or in a different files. no need for "public/internal/module" fallbacks to pass though files boundaries. similarly the class itself can use private members of its continuations.

5) "by invitation only" system. can only be written if declared by the class or some continuation of it.

6) A particular continuation only defined once (of course). There can be an arbitrary number of different continuations to a class similar to extensions.

7) alternative name considered: "extending" (as a noun). shall definitely be a different name than say, "extension" with some bracket-syntax variation - the two use cases are very different and shall be named differently.

8) the particular syntax is preliminary of course.

example:

============= Some.swift ==================

class Some {

    private func private_method_of_class() {

        // *** can use private methods of continuations even if they are in a different file
        private_method_defined_in_a_continuation()
    }
    
    // *** "by invitation" system

    continuation Feature // *** declaring a continuation
    continuation SomethingElse // *** Capitalized names, like classes
}

============= Some-Feature.swift ==================

// *** similar naming convetion to "Some+Feature.swift"
// used for extensions, just with "-" instead

// *** this is merely a naming convention, no need to
necessarily follow it, can put more than one thing into
a file, the continuation can reside in the same file as
the main class fie, etc.

continuation Feature of Some {

// *** as good as class itself. first-class citizen
// *** same syntax can be used for structs and enums

    var x: Int // *** can declare variables
    
    private func private_method_defined_in_a_continuation() {
        private_method_of_class()

        // *** can use private methods of the class or of other
continuations even if they are in a different file
    }
    
    // *** continuations are as good as classes and can
    // *** declare other continuations if needed

    continuation CanDoThis
}

============= Any file ==================

continuation Feature of Some { // *** error, continuation is already defined
}

continuation Other of Some { // *** error: Other is not a continuation of Some
}

thoughts?

Mike

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

All your use cases make perfect sense, however i see one potential issue
with this "pattern" :

I've seen a LOT of iOS developers (some juniors, some not) ending up with
monstruous UIViewControllers, and it has happened almost since the very
beginning of iOS development. Because of their lack of understanding of the
MVC pattern, they completely under estimate either the model or the view
layer and put too many things in their VC.

Now this pattern would give them the illusion that they're working in a
sane architecture and that they've decomposed the problem correctly, but in
fact were not. The fact that extension wouldn't let you add variable makes
it harder to conceal the problem, but with "continuations" i can see no
limit.

What do you think ?

···

On Tue, Oct 31, 2017 at 4:22 AM, Adam Kemp via swift-evolution < swift-evolution@swift.org> wrote:

This I actually support. In C# the same concept exists in the form of
partial classes. A class must be declared as partial everywhere in order to
support it. It only works within a single assembly (similar to a module).

There are a few important use cases for this in C#:

1. Code generation. For instance, Interface Builder could modify a
separate file for things like outlets and actions, and it could freely wipe
and regenerate that file from scratch without touching any of your own
code. Some people also generate parts of classes from templates while
filling in the rest in another file.

2. Cross platform code. A common strategy in C# is to have a class split
into parts, where one part is compiled on all platforms, and the other
files are each specific to one platform or another. For instance, you may
have Foo.swift, Foo.macOS.swift, and Foo.iOS.swift. Foo.swift would be
compiled on both platforms, but then the iOS build would only include
Foo.iOS.swift. This is a preferred alternative to using #ifs.

3. The use case Mike described. Sometimes we fail at making classes small,
or maybe someone else failed and we’re stuck with it. Splitting a single
class into pieces can be useful to organize cohesive chunks. That’s not
something I tend to encourage as a design pattern, but it still happens
anyway.

A related feature in C# is partial methods, which are just void-returning
methods that have been declared as partial without an implementation. If an
implementation is provided by another file (in another part of the partial
class) then it is used. If no file provides an implementation then calls to
that method are just stripped out by the compiler. This is also commonly
used for cross-platform code. Maybe one platform needs to do something at a
particular time but another doesn’t. Rather than using #ifs or having empty
stubs in other platforms you can declare it partial and provide an
implementation on just the one platform that needs it.

> On Oct 30, 2017, at 6:12 PM, Mike Kluev via swift-evolution < > swift-evolution@swift.org> wrote:
>
> a general feeling that there are two very different use cases of
extensions -- one to extend own classes and another to extend other people
classes; a lengthy discussion in a nearby thread; a disparity of features
of class and it's extensions and different access right treatment depending
upon whether the extension is in the same with the main class or a
different file lead me to the following idea. hopefully you will find this
idea useful and we may even see it one day in swift.
>
> introducing class / struct / enum continuations.
>
> in a few words the are:
>
> 1) "extensions on steroids". in fact very similar to Objective-C "class
extensions" but can be more than one and in more than one file.
>
> 2) as good as the classes they continue (or other continuations they
continue)
>
> 3) can declare variables
>
> 4) have full access to "private" members of the class or other
continuations
> regardless whether they are in the same or in a different files. no need
for "public/internal/module" fallbacks to pass though files boundaries.
similarly the class itself can use private members of its continuations.
>
> 5) "by invitation only" system. can only be written if declared by the
class or some continuation of it.
>
> 6) A particular continuation only defined once (of course). There can be
an arbitrary number of different continuations to a class similar to
extensions.
>
> 7) alternative name considered: "extending" (as a noun). shall
definitely be a different name than say, "extension" with some
bracket-syntax variation - the two use cases are very different and shall
be named differently.
>
> 8) the particular syntax is preliminary of course.
>
> example:
>
> ============= Some.swift ==================
>
> class Some {
>
> private func private_method_of_class() {
>
> // *** can use private methods of continuations even if they are
in a different file
> private_method_defined_in_a_continuation()
> }
>
> // *** "by invitation" system
>
> continuation Feature // *** declaring a continuation
> continuation SomethingElse // *** Capitalized names, like
classes
> }
>
> ============= Some-Feature.swift ==================
>
> // *** similar naming convetion to "Some+Feature.swift"
> // used for extensions, just with "-" instead
>
> // *** this is merely a naming convention, no need to
> necessarily follow it, can put more than one thing into
> a file, the continuation can reside in the same file as
> the main class fie, etc.
>
> continuation Feature of Some {
>
> // *** as good as class itself. first-class citizen
> // *** same syntax can be used for structs and enums
>
> var x: Int // *** can declare variables
>
> private func private_method_defined_in_a_continuation() {
> private_method_of_class()
>
> // *** can use private methods of the class or of other
> continuations even if they are in a different file
> }
>
> // *** continuations are as good as classes and can
> // *** declare other continuations if needed
>
> continuation CanDoThis
> }
>
> ============= Any file ==================
>
> continuation Feature of Some { // *** error, continuation is already
defined
> }
>
> continuation Other of Some { // *** error: Other is not a continuation
of Some
> }
>
> thoughts?
>
> Mike
>
> _______________________________________________
> 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

my favourite one would probably be continuations used for protocol adoption
- no longer the trip to the main class needed to add a variable:

continuation DataSource of MyViewController: UITableViewDataSource {

    private var variable: Bool // ***

    override func tableView(_ tableView: UITableView, cellForRowAt
indexPath: IndexPath) -> UITableViewCell {
        ...
    }
}

···

On 31 October 2017 at 06:57, Goffredo Marocchi <panajev@gmail.com> wrote:

I like the IB use case :).

class ViewController {
    part DataSource
    ...
}

part DataSource of ViewController: UITableViewDataSource {
    ....
}

Mike

That is a legitimate concern, but massive view controllers is a problem that already exists. The kind of person who would use partial classes to split up a giant view controller would probably also use extensions and just throw all of the fields in the main file. People do that today with both Objective-C and Swift. Partial classes would only make it marginally easier to implement the bad designs that people are already doing. So I do think it’s a legitimate concern, but I also think the benefits outweigh those costs.

···

On Nov 8, 2017, at 2:54 AM, Benjamin G <benjamin.garrigues@gmail.com> wrote:

All your use cases make perfect sense, however i see one potential issue with this "pattern" :

I've seen a LOT of iOS developers (some juniors, some not) ending up with monstruous UIViewControllers, and it has happened almost since the very beginning of iOS development. Because of their lack of understanding of the MVC pattern, they completely under estimate either the model or the view layer and put too many things in their VC.

Now this pattern would give them the illusion that they're working in a sane architecture and that they've decomposed the problem correctly, but in fact were not. The fact that extension wouldn't let you add variable makes it harder to conceal the problem, but with "continuations" i can see no limit.

What do you think ?

My preference would be around features to aggregate functionality, or to provide proper mixing.

1. One simpler feature would be a way to indicate your implementation of a protocol is via a property, and that calls should be forwarded.

2. More complex mixin behavior would include the included feature basically requesting a protocol as well, as a sort of language-level delegate. Compiler support means this can be done with value types, and that the implementations can be optimized/inlined.

Partial classes can solve some of these problems, but without a contract it can be difficult to manage the spaghetti nest of data and responsibilities. It also doesn’t allow for either part to be reusable across multiple implementations (except through class inheritance).

Partial classes in C# always seemed to exist specifically to combine authored and generated code without requiring a subclassing relationship.

-DW

···

On Nov 8, 2017, at 11:44 AM, Adam Kemp via swift-evolution <swift-evolution@swift.org> wrote:

That is a legitimate concern, but massive view controllers is a problem that already exists. The kind of person who would use partial classes to split up a giant view controller would probably also use extensions and just throw all of the fields in the main file. People do that today with both Objective-C and Swift. Partial classes would only make it marginally easier to implement the bad designs that people are already doing. So I do think it’s a legitimate concern, but I also think the benefits outweigh those costs.

On Nov 8, 2017, at 2:54 AM, Benjamin G <benjamin.garrigues@gmail.com> wrote:

All your use cases make perfect sense, however i see one potential issue with this "pattern" :

I've seen a LOT of iOS developers (some juniors, some not) ending up with monstruous UIViewControllers, and it has happened almost since the very beginning of iOS development. Because of their lack of understanding of the MVC pattern, they completely under estimate either the model or the view layer and put too many things in their VC.

Now this pattern would give them the illusion that they're working in a sane architecture and that they've decomposed the problem correctly, but in fact were not. The fact that extension wouldn't let you add variable makes it harder to conceal the problem, but with "continuations" i can see no limit.

What do you think ?

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

good tools won't fix bad developers (c)

you know that you can already sort of "store variables" in extensions,
right? obj-c associated object is one way (1). and if we are talking about
the use case of extending "your own types only" -- i am -- your own classes
are under your full control, so nobody stops you from having, say, an
"extensionVars" dictionary in your root class(es) and a handy set of
generic api's to get/set those in a convenient manner without too much
effort (2). is it ideal? no. performance suffers. usability suffers. non
trivial to have weak/unowned variables with (2). not a "first class
citizen" solution. the sheer number of hits of "how to i store variables in
extensions in swift" (more than a million now) hints you that the language
can step in to help, at least in the critical use case of "own types".

Mike

···

On 8 November 2017 at 10:54, Benjamin G <benjamin.garrigues@gmail.com> wrote:

All your use cases make perfect sense, however i see one potential issue
with this "pattern" :

I've seen a LOT of iOS developers (some juniors, some not) ending up with
monstruous UIViewControllers, and it has happened almost since the very
beginning of iOS development. Because of their lack of understanding of the
MVC pattern, they completely under estimate either the model or the view
layer and put too many things in their VC.

Now this pattern would give them the illusion that they're working in a
sane architecture and that they've decomposed the problem correctly, but in
fact were not. The fact that extension wouldn't let you add variable makes
it harder to conceal the problem, but with "continuations" i can see no
limit.

What do you think ?

Like Adam said, this make much more sense than
"classprivate./typeprivate"...

+1 for me.

You just create another 'bucket'! ;)

···

Em ter, 31 de out de 2017 às 08:19, Mike Kluev via swift-evolution < swift-evolution@swift.org> escreveu:

On 31 October 2017 at 06:57, Goffredo Marocchi <panajev@gmail.com> wrote:

I like the IB use case :).

my favourite one would probably be continuations used for protocol
adoption - no longer the trip to the main class needed to add a variable:

continuation DataSource of MyViewController: UITableViewDataSource {

    private var variable: Bool // ***

    override func tableView(_ tableView: UITableView, cellForRowAt
indexPath: IndexPath) -> UITableViewCell {
        ...
    }
}

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

Partial (like in C#) is good enough.

···

Em qua, 1 de nov de 2017 às 09:52, Mike Kluev via swift-evolution < swift-evolution@swift.org> escreveu:

class ViewController {
    part DataSource
    ...
}

part DataSource of ViewController: UITableViewDataSource {
    ....
}

Mike

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

ftm, this is what i have now (based on method 2):

extension SomeClass /* FeatureX */ {

    var someVar: Float {

        get { return extensionVar() }

        set { setExtensionVar(newValue) }

    }

    var otherVar: Bool {

        get { return extensionVar() }

        set { setExtensionVar(newValue) }

    }

    var someOptionalVar: Int? {

        get { return extensionVarOpt() }

        set { setExtensionVarOpt(newValue) }

    }

    func initFeatureX() {

        // init is optional if you can trust your code doing "set" before
the first "get"

        someVar = 0

        otherVar = false

    }

}

this is on the use side. "not too bad". not too insane syntax. not too much
code on the use side. note that i don't even have to spell the keys
explicitly, so it is the same copy-paste code for all the variables. but
then... optional vars need a different syntax. no weak/unowned support.
non-optional ones need to be "set before get". performance suffers. etc,
etc... (see the above).

this is the ideal i am dreaming of:

part FeatureX SomeClass {

    var someOptionalVar: Int? {

        var someVar: Float = 0

        var otherVar: Bool = false

        var someOptionalVar: Int?

        weak var someWeakVar: X?

    }

}

parts (continuations) can be an answer.

Mike

···

On 8 November 2017 at 14:20, Mike Kluev <mike.kluev@gmail.com> wrote:

On 8 November 2017 at 10:54, Benjamin G <benjamin.garrigues@gmail.com> > wrote:

All your use cases make perfect sense, however i see one potential issue
with this "pattern" :

I've seen a LOT of iOS developers (some juniors, some not) ending up with
monstruous UIViewControllers, and it has happened almost since the very
beginning of iOS development. Because of their lack of understanding of the
MVC pattern, they completely under estimate either the model or the view
layer and put too many things in their VC.

Now this pattern would give them the illusion that they're working in a
sane architecture and that they've decomposed the problem correctly, but in
fact were not. The fact that extension wouldn't let you add variable makes
it harder to conceal the problem, but with "continuations" i can see no
limit.

What do you think ?

good tools won't fix bad developers (c)

you know that you can already sort of "store variables" in extensions,
right? obj-c associated object is one way (1). and if we are talking about
the use case of extending "your own types only" -- i am -- your own classes
are under your full control, so nobody stops you from having, say, an
"extensionVars" dictionary in your root class(es) and a handy set of
generic api's to get/set those in a convenient manner without too much
effort (2). is it ideal? no. performance suffers. usability suffers. non
trivial to have weak/unowned variables with (2). not a "first class
citizen" solution. the sheer number of hits of "how to i store variables in
extensions in swift" (more than a million now) hints you that the language
can step in to help, at least in the critical use case of "own types".

"partial" will not read correctly in this context:

class ViewController: UIViewController {
    partial DataSource // ?!
    ...
}

partial DataSource of ViewController: UITableViewDataSource { // ?!
}

if you mean:

partial class ViewController: UITableViewDataSource {
    ...
}

this is not what i'm suggesting. parts/continuations must have a name and
this name must be listed in a ledger (of the main class or another part of
it) for the part to be able to exist at all.

having the "main" part (just the normal class definition) is good for:

- it is the only place to put base class in (like the above
UIViewController)

- it has the starting ledger that list parts (direct sub-parts). all parts
can be found "recursively" from that starting point.

with "parts" many pieces that are extensions today will become parts. and
"private" to "fileprivate" promotion feature will likely not be needed
anymore (we can of course leave it as is for compatibility).

Mike

···

On 1 November 2017 at 13:34, Wallacy <wallacyf@gmail.com> wrote:

Partial (like in C#) is good enough.

I'm extremely curious to know the use case that made you code this way. Is
it one of the case Adam listed before ?

I don't want to sidetrack this issue, but i wonder if something like this
Effective Go - The Go Programming Language wouldn't be a "cleaner"
solution.

···

On Wed, Nov 8, 2017 at 3:45 PM, Mike Kluev <mike.kluev@gmail.com> wrote:

On 8 November 2017 at 14:20, Mike Kluev <mike.kluev@gmail.com> wrote:

On 8 November 2017 at 10:54, Benjamin G <benjamin.garrigues@gmail.com> >> wrote:

All your use cases make perfect sense, however i see one potential issue
with this "pattern" :

I've seen a LOT of iOS developers (some juniors, some not) ending up
with monstruous UIViewControllers, and it has happened almost since the
very beginning of iOS development. Because of their lack of understanding
of the MVC pattern, they completely under estimate either the model or the
view layer and put too many things in their VC.

Now this pattern would give them the illusion that they're working in a
sane architecture and that they've decomposed the problem correctly, but in
fact were not. The fact that extension wouldn't let you add variable makes
it harder to conceal the problem, but with "continuations" i can see no
limit.

What do you think ?

good tools won't fix bad developers (c)

you know that you can already sort of "store variables" in extensions,
right? obj-c associated object is one way (1). and if we are talking about
the use case of extending "your own types only" -- i am -- your own classes
are under your full control, so nobody stops you from having, say, an
"extensionVars" dictionary in your root class(es) and a handy set of
generic api's to get/set those in a convenient manner without too much
effort (2). is it ideal? no. performance suffers. usability suffers. non
trivial to have weak/unowned variables with (2). not a "first class
citizen" solution. the sheer number of hits of "how to i store variables in
extensions in swift" (more than a million now) hints you that the language
can step in to help, at least in the critical use case of "own types".

ftm, this is what i have now (based on method 2):

extension SomeClass /* FeatureX */ {

    var someVar: Float {

        get { return extensionVar() }

        set { setExtensionVar(newValue) }

    }

    var otherVar: Bool {

        get { return extensionVar() }

        set { setExtensionVar(newValue) }

    }

    var someOptionalVar: Int? {

        get { return extensionVarOpt() }

        set { setExtensionVarOpt(newValue) }

    }

    func initFeatureX() {

        // init is optional if you can trust your code doing "set" before
the first "get"

        someVar = 0

        otherVar = false

    }

}

this is on the use side. "not too bad". not too insane syntax. not too
much code on the use side. note that i don't even have to spell the keys
explicitly, so it is the same copy-paste code for all the variables. but
then... optional vars need a different syntax. no weak/unowned support.
non-optional ones need to be "set before get". performance suffers. etc,
etc... (see the above).

this is the ideal i am dreaming of:

part FeatureX SomeClass {

    var someOptionalVar: Int? {

        var someVar: Float = 0

        var otherVar: Bool = false

        var someOptionalVar: Int?

        weak var someWeakVar: X?

    }

}

parts (continuations) can be an answer.

Mike

I don‚Äôt see why ‚Äúparts‚ÄĚ would need to be named. That seems overly complex for little benefit.

···

On Nov 1, 2017, at 7:43 AM, Mike Kluev via swift-evolution <swift-evolution@swift.org> wrote:

On 1 November 2017 at 13:34, Wallacy <wallacyf@gmail.com> wrote:
Partial (like in C#) is good enough.

"partial" will not read correctly in this context:

class ViewController: UIViewController {
    partial DataSource // ?!
    ...
}

partial DataSource of ViewController: UITableViewDataSource { // ?!
}

if you mean:

partial class ViewController: UITableViewDataSource {
    ...
}

this is not what i'm suggesting. parts/continuations must have a name and this name must be listed in a ledger (of the main class or another part of it) for the part to be able to exist at all.

having the "main" part (just the normal class definition) is good for:

- it is the only place to put base class in (like the above UIViewController)

- it has the starting ledger that list parts (direct sub-parts). all parts can be found "recursively" from that starting point.

with "parts" many pieces that are extensions today will become parts. and "private" to "fileprivate" promotion feature will likely not be needed anymore (we can of course leave it as is for compatibility).

Mike

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

The advantage of the extra keyword is that it makes it opt-in, which means you can know by looking at the class whether there are other places that have access to your private methods/fields/etc.

···

On Nov 1, 2017, at 8:54 AM, Zach Wolfe via swift-evolution <swift-evolution@swift.org> wrote:

I like what this idea attempts to do, but have you thought of simply allowing extensions of types within the same module to access private members and declare stored properties?

I like what this idea attempts to do, but have you thought of simply allowing extensions of types within the same module to access private members and declare stored properties? Adding a whole new construct to the language‚ÄĒwhile technically not source-breaking‚ÄĒwould in practice change what is considered to be the idiomatic ‚ÄúSwifty‚ÄĚ way of extending your own types, forcing people who care about such things to revisit their code for (imo) no good reason.

As a separate point, I’m strongly against the requirement that continuations be named and declared within the original type declaration or other continuations. As an optional categorization feature I’d be ok with it, but naming is hard, and forcing me to come up with a name every time I wish to isolate functionality of my types will push me away from doing it in the first place. Not to mention when I inevitably change one of my horrible continuation names, I will have to change it in two places (or more in the cross-platform example)!

Also on the naming point, you mention being able to refer to continuations by name. Can you give an example where that would be useful?

name and ledger are essential in this proposal.

no name ->
no ledger (how to reference it?) ->
anyone can write parts of your class ->
anyone can add variables to your class ?! ->
anyone can access private members of your class ?!

makes no sense without a name and a ledger.

Mike

···

On 1 November 2017 at 15:22, Adam Kemp <adam.kemp@apple.com> wrote:

I don‚Äôt see why ‚Äúparts‚ÄĚ would need to be named. That seems overly complex
for little benefit.

I'm extremely curious to know the use case that made you code this way. Is
it one of the case Adam listed before ?

to "manage complexities". once the type is relatively big (it's not a view
controller :) -> there's a need to split it into different extensions (or
even files) to keep things manageable -> hence the need to expose the
private things as internals due to the current language limitations ->
hence the fear that someone on the same module (even myself few weeks
later) one day will take advantage of "what is supposed to be private" and
get an unwanted dependency on it. plus of course a desire to save time on
trips to the main type and back when i have to change the variables, which
is quite annoying. if your type is reasonably big you may find yourself in
a situation when all you have in the main type definitions is just
variables (*), and you have several extensions each implementing a certain
feature.

(*) and those methods that relate to other language limitations, e.g.
"can't override methods of extensions yet"

among those 1.5 million hits for "how do i store variables in extensions in
swift" a significant portion would be for the "own type" use cases - so
that's not "just me".

the use case of IB outlets/variables brought by Adam can be a significant
plus for parts/continuations/partial ideas. just imagine you no longer have
to manually keep in sync the two (storyboard and outlets/variables) as
Xcode will do it itself. once we have this feature all IB classes (e.g. all
view controllers) will become parts/continuations/partials.

I don't want to sidetrack this issue, but i wonder if something like this

Effective Go - The Go Programming Language wouldn't be a
"cleaner" solution.

at the first glance it resembles... the ledger :) just from a slightly
different angle.

Mike

···

On 8 November 2017 at 15:56, Benjamin G <benjamin.garrigues@gmail.com> wrote: