Proposal: Allow "flat" declaration of nested types


(Alexander Doloz) #1

Hello, Swift community!

Right now, when we declare nested types in Swift, we have to literally nest them:

// Swift 3
struct A {
  var a = 0
  struct B {
    var b = 0
    struct C {
      var c = 0
      func someFunc() {
        if something {

        }
      }
    }
  }
}

By nesting types this way we waste amount of indents we can do without losing readability. In the example above, code inside if statement will already be far away from left border.
I propose to allow do nested types like this:

// Proposal
struct A {
  var a = 0
}

struct A.B {
  var b = 0
}

struct A.B.C {
  var c = 0
  func someFunc() {
    if something {

    }
  }
}

No more unnecessary indentation.
Of course, the old way should also continue to work.


(Robert Widmann) #2

I think this is an interesting proposal, but I don't write enough extremely-nested code to know that it will do much more than save you some whitespace - as you say. What situation have you run into specifically where this kind of code is both called-for and headache-inducing?

~Robert Widmann

2016/11/19 18:48、Alexander Doloz via swift-evolution <swift-evolution@swift.org> のメッセージ:

···

Hello, Swift community!

Right now, when we declare nested types in Swift, we have to literally nest them:

// Swift 3
struct A {
   var a = 0
   struct B {
       var b = 0
       struct C {
           var c = 0
           func someFunc() {
               if something {

               }
           }
       }
   }
}

By nesting types this way we waste amount of indents we can do without losing readability. In the example above, code inside if statement will already be far away from left border.
I propose to allow do nested types like this:

// Proposal
struct A {
   var a = 0
}

struct A.B {
   var b = 0
}

struct A.B.C {
   var c = 0
   func someFunc() {
       if something {

       }
   }
}

No more unnecessary indentation.
Of course, the old way should also continue to work.

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


(Rien) #3

Imo, it does not need extreme nested code to be useful. I find that more than 1 level of nesting tends to create obfuscation. Probably because we loose the ability to associate type C with type A. By allowing "struct A.B.C" it is very clear that C does indeed depend on A.
However, I can already see questions coming: how to refer to struct A elements and can we introduce new scope visibility rules?
Still, I like this way of programming, so for me its a +1

Regards,
Rien

Site: http://balancingrock.nl
Blog: http://swiftrien.blogspot.com
Github: http://github.com/Swiftrien
Project: http://swiftfire.nl

···

On 20 Nov 2016, at 04:18, Robert Widmann via swift-evolution <swift-evolution@swift.org> wrote:

I think this is an interesting proposal, but I don't write enough extremely-nested code to know that it will do much more than save you some whitespace - as you say. What situation have you run into specifically where this kind of code is both called-for and headache-inducing?

~Robert Widmann

2016/11/19 18:48、Alexander Doloz via swift-evolution <swift-evolution@swift.org> のメッセージ:

Hello, Swift community!

Right now, when we declare nested types in Swift, we have to literally nest them:

// Swift 3
struct A {
  var a = 0
  struct B {
      var b = 0
      struct C {
          var c = 0
          func someFunc() {
              if something {

              }
          }
      }
  }
}

By nesting types this way we waste amount of indents we can do without losing readability. In the example above, code inside if statement will already be far away from left border.
I propose to allow do nested types like this:

// Proposal
struct A {
  var a = 0
}

struct A.B {
  var b = 0
}

struct A.B.C {
  var c = 0
  func someFunc() {
      if something {

      }
  }
}

No more unnecessary indentation.
Of course, the old way should also continue to work.

_______________________________________________
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 always wanted something like this. Can't we extend the idea a little further and make it `flat extension` instead?

struct A {}

func A.foo() {}

struct A.B {}

It would be some sugar for `extension A { ... }`

···

--
Adrian Zubarev
Sent with Airmail

Am 20. November 2016 um 04:18:32, Robert Widmann via swift-evolution (swift-evolution@swift.org(mailto:swift-evolution@swift.org)) schrieb:

I think this is an interesting proposal, but I don't write enough extremely-nested code to know that it will do much more than save you some whitespace - as you say. What situation have you run into specifically where this kind of code is both called-for and headache-inducing?

~Robert Widmann

2016/11/19 18:48、Alexander Doloz via swift-evolution <swift-evolution@swift.org> のメッセージ:

> Hello, Swift community!
>
> Right now, when we declare nested types in Swift, we have to literally nest them:
>
> // Swift 3
> struct A {
> var a = 0
> struct B {
> var b = 0
> struct C {
> var c = 0
> func someFunc() {
> if something {
>
> }
> }
> }
> }
> }
>
> By nesting types this way we waste amount of indents we can do without losing readability. In the example above, code inside if statement will already be far away from left border.
> I propose to allow do nested types like this:
>
> // Proposal
> struct A {
> var a = 0
> }
>
> struct A.B {
> var b = 0
> }
>
> struct A.B.C {
> var c = 0
> func someFunc() {
> if something {
>
> }
> }
> }
>
> No more unnecessary indentation.
> Of course, the old way should also continue to work.
>
>
> _______________________________________________
> 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


(Alexander Doloz) #5

About scope visibility rules – I think, for now this new syntax should behave exactly like the old. What’s possible with old syntax should be possible with the new and vice versa.
To Robert Widmann’s question about real situation where such syntax will be useful – right now I have a project where nested types are used. They are good for my situation, but:
1. When they appear directly in the outer type I have to take extra effort to distinguish between properties and methods of outer type vs. properties and methods of inner type.
2. And yes, indents. I don’t do something crazy - I have only I place where 3 types are nested. But even if there are 2 types, it becomes inconvenient to read code in the methods of the last nested type.
New syntax solves this issues.

···

20 нояб. 2016 г., в 16:00, Rien <Rien@Balancingrock.nl> написал(а):

Imo, it does not need extreme nested code to be useful. I find that more than 1 level of nesting tends to create obfuscation. Probably because we loose the ability to associate type C with type A. By allowing "struct A.B.C" it is very clear that C does indeed depend on A.
However, I can already see questions coming: how to refer to struct A elements and can we introduce new scope visibility rules?
Still, I like this way of programming, so for me its a +1

Regards,
Rien

Site: http://balancingrock.nl
Blog: http://swiftrien.blogspot.com
Github: http://github.com/Swiftrien
Project: http://swiftfire.nl

On 20 Nov 2016, at 04:18, Robert Widmann via swift-evolution <swift-evolution@swift.org> wrote:

I think this is an interesting proposal, but I don't write enough extremely-nested code to know that it will do much more than save you some whitespace - as you say. What situation have you run into specifically where this kind of code is both called-for and headache-inducing?

~Robert Widmann

2016/11/19 18:48、Alexander Doloz via swift-evolution <swift-evolution@swift.org> のメッセージ:

Hello, Swift community!

Right now, when we declare nested types in Swift, we have to literally nest them:

// Swift 3
struct A {
var a = 0
struct B {
     var b = 0
     struct C {
         var c = 0
         func someFunc() {
             if something {

             }
         }
     }
}
}

By nesting types this way we waste amount of indents we can do without losing readability. In the example above, code inside if statement will already be far away from left border.
I propose to allow do nested types like this:

// Proposal
struct A {
var a = 0
}

struct A.B {
var b = 0
}

struct A.B.C {
var c = 0
func someFunc() {
     if something {

     }
}
}

No more unnecessary indentation.
Of course, the old way should also continue to work.

_______________________________________________
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


(Derrick Ho) #6

Alexander, I took your code and "flattened" it with what currently exists
in Swift 3. Is this not flat enough for you?

struct A {

  var a = 0

}

extension A {

  struct B {

  var b = "Bee"

  }

}

extension A.B {

  struct C {

  var c = 0

  func someFunc() {

  print("something")

  }

  }

}

A().a // print 0

A.B().b // Print "Bee"

A.B.C().someFunc() // Print "something"

···

On Sun, Nov 20, 2016 at 10:23 AM Alexander Doloz via swift-evolution < swift-evolution@swift.org> wrote:

About scope visibility rules – I think, for now this new syntax should
behave exactly like the old. What’s possible with old syntax should be
possible with the new and vice versa.
To Robert Widmann’s question about real situation where such syntax will
be useful – right now I have a project where nested types are used. They
are good for my situation, but:
1. When they appear directly in the outer type I have to take extra effort
to distinguish between properties and methods of outer type vs. properties
and methods of inner type.
2. And yes, indents. I don’t do something crazy - I have only I place
where 3 types are nested. But even if there are 2 types, it becomes
inconvenient to read code in the methods of the last nested type.
New syntax solves this issues.
> 20 нояб. 2016 г., в 16:00, Rien <Rien@Balancingrock.nl> написал(а):
>
> Imo, it does not need extreme nested code to be useful. I find that more
than 1 level of nesting tends to create obfuscation. Probably because we
loose the ability to associate type C with type A. By allowing "struct
A.B.C" it is very clear that C does indeed depend on A.
> However, I can already see questions coming: how to refer to struct A
elements and can we introduce new scope visibility rules?
> Still, I like this way of programming, so for me its a +1
>
> Regards,
> Rien
>
> Site: http://balancingrock.nl
> Blog: http://swiftrien.blogspot.com
> Github: http://github.com/Swiftrien
> Project: http://swiftfire.nl
>
>
>
>
>> On 20 Nov 2016, at 04:18, Robert Widmann via swift-evolution < > swift-evolution@swift.org> wrote:
>>
>> I think this is an interesting proposal, but I don't write enough
extremely-nested code to know that it will do much more than save you some
whitespace - as you say. What situation have you run into specifically
where this kind of code is both called-for and headache-inducing?
>>
>> ~Robert Widmann
>>
>> 2016/11/19 18:48、Alexander Doloz via swift-evolution <
swift-evolution@swift.org> のメッセージ:
>>
>>> Hello, Swift community!
>>>
>>> Right now, when we declare nested types in Swift, we have to literally
nest them:
>>>
>>> // Swift 3
>>> struct A {
>>> var a = 0
>>> struct B {
>>> var b = 0
>>> struct C {
>>> var c = 0
>>> func someFunc() {
>>> if something {
>>>
>>> }
>>> }
>>> }
>>> }
>>> }
>>>
>>> By nesting types this way we waste amount of indents we can do without
losing readability. In the example above, code inside if statement will
already be far away from left border.
>>> I propose to allow do nested types like this:
>>>
>>> // Proposal
>>> struct A {
>>> var a = 0
>>> }
>>>
>>> struct A.B {
>>> var b = 0
>>> }
>>>
>>> struct A.B.C {
>>> var c = 0
>>> func someFunc() {
>>> if something {
>>>
>>> }
>>> }
>>> }
>>>
>>> No more unnecessary indentation.
>>> Of course, the old way should also continue to work.
>>>
>>>
>>> _______________________________________________
>>> 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


(Adrian Zubarev) #7

Real type nesting vs. extension nesting creates a new visibility boundary. If your type somehow depends on the visibility of your parent type scope, it could became problematic. Just speaking generally here.

Bikeshedding:

struct A {
    struct B {}
}

extension A {
    struct C {}
}

// Could be written as

@scoped
struct A.B {}

@extension // where this could be by default and fully inferred
struct A.C {}

···

--
Adrian Zubarev
Sent with Airmail

Am 20. November 2016 um 19:06:13, Derrick Ho via swift-evolution (swift-evolution@swift.org) schrieb:

Alexander, I took your code and "flattened" it with what currently exists in Swift 3. Is this not flat enough for you?

struct A {
var a = 0
}

extension A {
struct B {
var b = "Bee"
}
}

extension A.B {
struct C {
var c = 0
func someFunc() {
print("something")
}
}
}

A().a // print 0
A.B().b // Print "Bee"
A.B.C().someFunc() // Print "something"

On Sun, Nov 20, 2016 at 10:23 AM Alexander Doloz via swift-evolution <swift-evolution@swift.org> wrote:
About scope visibility rules – I think, for now this new syntax should behave exactly like the old. What’s possible with old syntax should be possible with the new and vice versa.
To Robert Widmann’s question about real situation where such syntax will be useful – right now I have a project where nested types are used. They are good for my situation, but:
1. When they appear directly in the outer type I have to take extra effort to distinguish between properties and methods of outer type vs. properties and methods of inner type.
2. And yes, indents. I don’t do something crazy - I have only I place where 3 types are nested. But even if there are 2 types, it becomes inconvenient to read code in the methods of the last nested type.
New syntax solves this issues.

20 нояб. 2016 г., в 16:00, Rien <Rien@Balancingrock.nl> написал(а):

Imo, it does not need extreme nested code to be useful. I find that more than 1 level of nesting tends to create obfuscation. Probably because we loose the ability to associate type C with type A. By allowing "struct A.B.C" it is very clear that C does indeed depend on A.
However, I can already see questions coming: how to refer to struct A elements and can we introduce new scope visibility rules?
Still, I like this way of programming, so for me its a +1

Regards,
Rien

Site: http://balancingrock.nl
Blog: http://swiftrien.blogspot.com
Github: http://github.com/Swiftrien
Project: http://swiftfire.nl

On 20 Nov 2016, at 04:18, Robert Widmann via swift-evolution <swift-evolution@swift.org> wrote:

I think this is an interesting proposal, but I don't write enough extremely-nested code to know that it will do much more than save you some whitespace - as you say. What situation have you run into specifically where this kind of code is both called-for and headache-inducing?

~Robert Widmann

2016/11/19 18:48、Alexander Doloz via swift-evolution <swift-evolution@swift.org> のメッセージ:

Hello, Swift community!

Right now, when we declare nested types in Swift, we have to literally nest them:

// Swift 3
struct A {
var a = 0
struct B {
var b = 0
struct C {
var c = 0
func someFunc() {
if something {

          \}
      \}
  \}

}
}

By nesting types this way we waste amount of indents we can do without losing readability. In the example above, code inside if statement will already be far away from left border.
I propose to allow do nested types like this:

// Proposal
struct A {
var a = 0
}

struct A.B {
var b = 0
}

struct A.B.C {
var c = 0
func someFunc() {
if something {

  \}

}
}

No more unnecessary indentation.
Of course, the old way should also continue to work.

_______________________________________________
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


(Alexander Doloz) #8

Frankly speaking I didn’t know it’s possible with extensions :slight_smile: Thank you for answer, it will be helpful for my project.
Since this method works my proposal no longer makes much sense.

···

20 нояб. 2016 г., в 21:05, Derrick Ho <wh1pch81n@gmail.com> написал(а):

struct A {
   var a = 0
}

extension A {
   struct B {
      var b = "Bee"
   }
}

extension A.B {
   struct C {
      var c = 0
      func someFunc() {
         print("something")
      }
   }
}


(Rien) #9

Sure you can do that, but I rather write:

struct A.B {…}

than

extension A { struct B {…} }

The first seems much “swiftier” to me.
In fact, now that this “obvious” dot-notation has been pointed out, I wonder why this was not the initial implementation instead of the “extension” keyword.
Was the dot-notation considered? and if so, what was the rationale for choosing the “extension” keyword? Is it worth reconsidering?

Regards,
Rien

Site: http://balancingrock.nl
Blog: http://swiftrien.blogspot.com
Github: http://github.com/Swiftrien
Project: http://swiftfire.nl

···

On 20 Nov 2016, at 19:05, Derrick Ho <wh1pch81n@gmail.com> wrote:

Alexander, I took your code and "flattened" it with what currently exists in Swift 3. Is this not flat enough for you?

struct A {
   var a = 0
}

extension A {
   struct B {
      var b = "Bee"
   }
}

extension A.B {
   struct C {
      var c = 0
      func someFunc() {
         print("something")
      }
   }
}

A().a // print 0
A.B().b // Print "Bee"
A.B.C().someFunc() // Print "something"

On Sun, Nov 20, 2016 at 10:23 AM Alexander Doloz via swift-evolution <swift-evolution@swift.org> wrote:
About scope visibility rules – I think, for now this new syntax should behave exactly like the old. What’s possible with old syntax should be possible with the new and vice versa.
To Robert Widmann’s question about real situation where such syntax will be useful – right now I have a project where nested types are used. They are good for my situation, but:
1. When they appear directly in the outer type I have to take extra effort to distinguish between properties and methods of outer type vs. properties and methods of inner type.
2. And yes, indents. I don’t do something crazy - I have only I place where 3 types are nested. But even if there are 2 types, it becomes inconvenient to read code in the methods of the last nested type.
New syntax solves this issues.
> 20 нояб. 2016 г., в 16:00, Rien <Rien@Balancingrock.nl> написал(а):
>
> Imo, it does not need extreme nested code to be useful. I find that more than 1 level of nesting tends to create obfuscation. Probably because we loose the ability to associate type C with type A. By allowing "struct A.B.C" it is very clear that C does indeed depend on A.
> However, I can already see questions coming: how to refer to struct A elements and can we introduce new scope visibility rules?
> Still, I like this way of programming, so for me its a +1
>
> Regards,
> Rien
>
> Site: http://balancingrock.nl
> Blog: http://swiftrien.blogspot.com
> Github: http://github.com/Swiftrien
> Project: http://swiftfire.nl
>
>
>
>
>> On 20 Nov 2016, at 04:18, Robert Widmann via swift-evolution <swift-evolution@swift.org> wrote:
>>
>> I think this is an interesting proposal, but I don't write enough extremely-nested code to know that it will do much more than save you some whitespace - as you say. What situation have you run into specifically where this kind of code is both called-for and headache-inducing?
>>
>> ~Robert Widmann
>>
>> 2016/11/19 18:48、Alexander Doloz via swift-evolution <swift-evolution@swift.org> のメッセージ:
>>
>>> Hello, Swift community!
>>>
>>> Right now, when we declare nested types in Swift, we have to literally nest them:
>>>
>>> // Swift 3
>>> struct A {
>>> var a = 0
>>> struct B {
>>> var b = 0
>>> struct C {
>>> var c = 0
>>> func someFunc() {
>>> if something {
>>>
>>> }
>>> }
>>> }
>>> }
>>> }
>>>
>>> By nesting types this way we waste amount of indents we can do without losing readability. In the example above, code inside if statement will already be far away from left border.
>>> I propose to allow do nested types like this:
>>>
>>> // Proposal
>>> struct A {
>>> var a = 0
>>> }
>>>
>>> struct A.B {
>>> var b = 0
>>> }
>>>
>>> struct A.B.C {
>>> var c = 0
>>> func someFunc() {
>>> if something {
>>>
>>> }
>>> }
>>> }
>>>
>>> No more unnecessary indentation.
>>> Of course, the old way should also continue to work.
>>>
>>>
>>> _______________________________________________
>>> 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


(Derrick Ho) #10

No problem Alexander!

···

On Sun, Nov 20, 2016 at 1:15 PM Alexander Doloz <adoloz@cayugasoft.com> wrote:

Frankly speaking I didn’t know it’s possible with extensions :slight_smile: Thank you
for answer, it will be helpful for my project.
Since this method works my proposal no longer makes much sense.

20 нояб. 2016 г., в 21:05, Derrick Ho <wh1pch81n@gmail.com> написал(а):

struct A {
  var a = 0
}

extension A {
  struct B {
  var b = "Bee"
  }
}

extension A.B {
  struct C {
  var c = 0
  func someFunc() {
  print("something")
  }
  }
}


(Jeremy Pereira) #11

Sure you can do that, but I rather write:

struct A.B {…}

than

extension A { struct B {…} }

The first seems much “swiftier” to me.

Hmm, objectively, it’s not “swiftier” is it, because Swift has had the extension syntax since day 1 and not the dot syntax. What you actually mean is “it looks nicer to me” which is an entirely subjective position, one with which I agree, but I don’t think such arguments should carry much weight.

Actually, I’d like to see “it seems more swifty” and equivalent expressions banned from the list. The concept isn’t well enough defined for a serious discussion on the merits of proposed language features. /rant

In fact, now that this “obvious” dot-notation has been pointed out, I wonder why this was not the initial implementation instead of the “extension” keyword.

The extension keyword is needed in the case where you are extending an existing type to conform to a protocol. Given that we already have (and need) the extension form and we can already do

extension A.B { struct C { … } }

is there an objective justification for adding a redundant way of doing the same thing?

···

On 21 Nov 2016, at 08:42, Rien via swift-evolution <swift-evolution@swift.org> wrote:


(Rien) #12

Sure you can do that, but I rather write:

struct A.B {…}

than

extension A { struct B {…} }

The first seems much “swiftier” to me.

Hmm, objectively, it’s not “swiftier” is it, because Swift has had the extension syntax since day 1 and not the dot syntax. What you actually mean is “it looks nicer to me” which is an entirely subjective position, one with which I agree, but I don’t think such arguments should carry much weight.

Actually, I’d like to see “it seems more swifty” and equivalent expressions banned from the list. The concept isn’t well enough defined for a serious discussion on the merits of proposed language features. /rant

Agreed, won’t use it anymore.

In swift the dot-notation seems to be the preferred way of expressing hierarchical relationships. Why not allow the use of the dot-notation for inner-type definitions?

In fact, now that this “obvious” dot-notation has been pointed out, I wonder why this was not the initial implementation instead of the “extension” keyword.

The extension keyword is needed in the case where you are extending an existing type to conform to a protocol. Given that we already have (and need) the extension form and we can already do

extension A.B { struct C { … } }

is there an objective justification for adding a redundant way of doing the same thing?

I do not see it as the same thing.
Creating an extension for a protocol is conceptually different from defining an inner type.
It is common to use a different syntax for same-functionaly if the underlying concept is different enough. For example the “if” and “guard” statements.

Regards,
Rien

Site: http://balancingrock.nl
Blog: http://swiftrien.blogspot.com
Github: http://github.com/Swiftrien
Project: http://swiftfire.nl

···

On 21 Nov 2016, at 11:52, Jeremy Pereira <jeremy.j.pereira@googlemail.com> wrote:

On 21 Nov 2016, at 08:42, Rien via swift-evolution <swift-evolution@swift.org> wrote: