Proposal: Re-instate mandatory self for accessing instance properties and functions


(David Hart) #1

I don't understand the reasoning behind removing the need to access instance properties and functions using self. Swift has always seemed to prefer readability to brevity and the feature makes the distinction between local and instance variables/functions crystal clear. Any good reason I shouldn't go on with the proposition?

Just as example, my proposition makes the following piece of code illegal:

struct FooBar {
    var foo: String = "foobar"

    func bar() {
        print(foo) // compiler error
        print(self.foo) // compiler happy
    }

    func bar2() {
        bar() // compiler error
        self.bar() // compiler happy
    }
}

(David Smith) #2

Currently, ‘self.’ is required when used in closure capture contexts, which has the nice property of making it really clear when things are being captured (and therefore retained).

  David

···

On Dec 4, 2015, at 1:19 PM, David Hart <david@hartbit.com> wrote:

I don't understand the reasoning behind removing the need to access instance properties and functions using self. Swift has always seemed to prefer readability to brevity and the feature makes the distinction between local and instance variables/functions crystal clear. Any good reason I shouldn't go on with the proposition?

Just as example, my proposition makes the following piece of code illegal:

struct FooBar {
   var foo: String = "foobar"

   func bar() {
       print(foo) // compiler error
       print(self.foo) // compiler happy
   }

   func bar2() {
       bar() // compiler error
       self.bar() // compiler happy
   }
}

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


(Rudolf Adamkovič) #3

+1

1) I actually encountered at least two bugs in my app introduced by this implicit "self" behavior. It can be dangerous and hard to track down.

2) Also when, say fine-tuning UIKit animations, I find myself wasting enormous amount of time adding and removing "self".

R+

···

Sent from my iPhone

On 04 Dec 2015, at 22:19, David Hart <david@hartbit.com> wrote:

I don't understand the reasoning behind removing the need to access instance properties and functions using self. Swift has always seemed to prefer readability to brevity and the feature makes the distinction between local and instance variables/functions crystal clear. Any good reason I shouldn't go on with the proposition?

Just as example, my proposition makes the following piece of code illegal:

struct FooBar {
   var foo: String = "foobar"

   func bar() {
       print(foo) // compiler error
       print(self.foo) // compiler happy
   }

   func bar2() {
       bar() // compiler error
       self.bar() // compiler happy
   }
}

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


(Rudolf Adamkovič) #4

To be a little more specific, here’s a real-world example:

1. Say there’s a method in my class that contains a local variable called “title”.
2. After a while, I decide to remove a part of this method, including the “title” variable.
3. Everything compiles and seems to work just fine.
4. However, I forgot to remove one more line that used the “title” variable.
5. Because we’re in a UIViewController subclass, I'm unknowingly modifying view controller’s title.

R+

···

On 4 Dec 2015, at 22:51, Rudolf Adamkovic <salutis@me.com> wrote:

+1

1) I actually encountered at least two bugs in my app introduced by this implicit "self" behavior. It can be dangerous and hard to track down.

2) Also when, say fine-tuning UIKit animations, I find myself wasting enormous amount of time adding and removing "self".

R+

Sent from my iPhone

On 04 Dec 2015, at 22:19, David Hart <david@hartbit.com> wrote:

I don't understand the reasoning behind removing the need to access instance properties and functions using self. Swift has always seemed to prefer readability to brevity and the feature makes the distinction between local and instance variables/functions crystal clear. Any good reason I shouldn't go on with the proposition?

Just as example, my proposition makes the following piece of code illegal:

struct FooBar {
  var foo: String = "foobar"

  func bar() {
      print(foo) // compiler error
      print(self.foo) // compiler happy
  }

  func bar2() {
      bar() // compiler error
      self.bar() // compiler happy
  }
}

_______________________________________________
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


(Lily Ballard) #5

Very strong -1.

The ability to elide `self` in most contexts is really nice. Especially
when combined with the fact that SourceKitService lets Xcode syntax-
colorize properties/methods nicely so the color of the identifier tells
me whether it's a method/property on self or something else. I realize
that not everybody will be using Xcode (particularly people on other
platforms), but in time we should hopefully see other editors gain
support for SourceKit to provide more intelligent handling of Swift
code as well.

Similarly, I rely on the ability to shadow things (including properties
of self) a _lot_. And it's not just me; it's very common for e.g.
initializers to use property names as the parameter names, such as:

init(x: Int, y: Int) { self.x = x self.y = y }

-Kevin Ballard

Are there warnings/diagnostics that could call out when local
variables shadow properties? I generally like that `self` is optional
and prefer limiting its use to explicitly call out potential retain
cycles. Xcode also makes it easy to introspect variable scope, though
Xcode is less of a requirement these days...

To be a little more specific, here’s a real-world example:

1. Say there’s a method in my class that contains a local variable
   called “title”.

2. After a while, I decide to remove a part of this method, including
   the “title” variable.

3. Everything compiles and seems to work just fine.

4. However, I forgot to remove one more line that used the
   “title” variable.

5. Because we’re in a UIViewController subclass, I'm unknowingly
   modifying view controller’s title.

R+

···

On Fri, Dec 4, 2015, at 02:41 PM, Stephen Celis wrote:

On Fri, Dec 4, 2015 at 5:34 PM, Rudolf Adamkovič > <salutis@me.com> wrote:

On 4 Dec 2015, at 22:51, Rudolf Adamkovic <salutis@me.com> wrote:

+1

1) I actually encountered at least two bugs in my app introduced by
   this implicit "self" behavior. It can be dangerous and hard to
   track down.

2) Also when, say fine-tuning UIKit animations, I find myself wasting
   enormous amount of time adding and removing "self".

R+

Sent from my iPhone

On 04 Dec 2015, at 22:19, David Hart <david@hartbit.com> wrote:

I don't understand the reasoning behind removing the need to access
instance properties and functions using self. Swift has always seemed
to prefer readability to brevity and the feature makes the
distinction between local and instance variables/functions crystal
clear. Any good reason I shouldn't go on with the proposition?

Just as example, my proposition makes the following piece of code
illegal:


struct FooBar {

var foo: String = "foobar"

func bar() {

print(foo) // compiler error

print(self.foo) // compiler happy

}

func bar2() {

bar() // compiler error

self.bar() // compiler happy

}

}

_______________________________________________

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


#6

Are there warnings/diagnostics that could call out when local variables
shadow properties? I generally like that `self` is optional and prefer
limiting its use to explicitly call out potential retain cycles. Xcode also
makes it easy to introspect variable scope, though Xcode is less of a
requirement these days...

···

On Fri, Dec 4, 2015 at 5:34 PM, Rudolf Adamkovič <salutis@me.com> wrote:

To be a little more specific, here’s a real-world example:

1. Say there’s a method in my class that contains a local variable called
“title”.
2. After a while, I decide to remove a part of this method, including the
“title” variable.
3. Everything compiles and seems to work just fine.
4. However, I forgot to remove one more line that used the “title”
variable.
5. Because we’re in a UIViewController subclass, I'm unknowingly modifying
view controller’s title.

R+

> On 4 Dec 2015, at 22:51, Rudolf Adamkovic <salutis@me.com> wrote:
>
> +1
>
> 1) I actually encountered at least two bugs in my app introduced by this
implicit "self" behavior. It can be dangerous and hard to track down.
>
> 2) Also when, say fine-tuning UIKit animations, I find myself wasting
enormous amount of time adding and removing "self".
>
> R+
>
> Sent from my iPhone
>
>> On 04 Dec 2015, at 22:19, David Hart <david@hartbit.com> wrote:
>>
>> I don't understand the reasoning behind removing the need to access
instance properties and functions using self. Swift has always seemed to
prefer readability to brevity and the feature makes the distinction between
local and instance variables/functions crystal clear. Any good reason I
shouldn't go on with the proposition?
>>
>> Just as example, my proposition makes the following piece of code
illegal:
>>
>> ```
>> struct FooBar {
>> var foo: String = "foobar"
>>
>> func bar() {
>> print(foo) // compiler error
>> print(self.foo) // compiler happy
>> }
>>
>> func bar2() {
>> bar() // compiler error
>> self.bar() // compiler happy
>> }
>> }
>> ```
>> _______________________________________________
>> 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


(David Hart) #7

Stephen, as previously stated by Rudolf, his real-world example would not trigger such a warning because the title local variable no longer exists and therefore no longer shadows the instance property.

To continue the discussion, here is a more detailed but rough proposal closer to the required template to advance discussions. I hope you don’t mind Rudolf, but I used your example to illustrate the proposal:

Introduction

Swift used to force using ‘.self’ when accessing instance properties and functions, but since dropped this requirement, only to keep it for closure captures. It now feels inconsistent, and we have lost the automatic documentation of instance properties vs local variables and instance functions vs local functions or closures. This proposal offers to re-instate the original behaviour.

Motivation

The previous behaviour which this proposal hopes to re-instate provided several advantages:

* When reading code, it makes it obvious which are instance properties and which are local variables, as well as which are instance functions and which are local functions/closures. Moreover, a sloppy programmer can make it hard to read his code if he does not constantly use self. or not.
* Avoids bugs where the author meant to use one a local variable but instead is unknowingly using an instance property (and the other way round).

One example of a bug avoided by the original proposal (provided by Rudolf Adamkovic):

class MyViewController : UIViewController {
  @IBOutlet var button: UIButton!
        var name: String = “David"

  func updateButton() {
    // var title = “Hello \(name)”
    button.setTitle(title, forState: .Normal) // forgot to comment this line but the compiler does not complain and title is now referencing UIViewController’s title by mistake
    button.setTitleColor(UIColor.blackColor(), forState: .Normal)
  }
}

The API Design Guidelines <https://swift.org/documentation/api-design-guidelines.html> are meant for writing APIs but I still think they represent fundamentals of Swift. The two first points are:

  • Clarity at the point of use is your most important goal. Code is read far more than it is written.
  • Clarity is more important than brevity. Although Swift code can be compact, it is a non-goal to enable the smallest possible code with the fewest characters. Brevity in Swift code, where it occurs, is a side-effect of the strong type system and features that naturally reduce boilerplate.

And I believe that the proposition is directly in line with those objectives.

Proposed solution

Re-instante the previous behaviour where ‘self.’ was required to access instance properties and functions.

Detailed design

It would not require changes to the grammar, and I think (not a compiler engineer) that it would require minimal amount of work.

Impact on existing code

A lot of code written since the original change would be impacted by this proposal, but it seems like it can be easily fixed by both the migrator tool and Auto Fixes.

Alternatives considered

The alternative is to keep the current behaviour, but it has the aforementioned disadvantages

···

On 04 Dec 2015, at 22:51, Rudolf Adamkovic <salutis@me.com> wrote:

+1

1) I actually encountered at least two bugs in my app introduced by this implicit "self" behavior. It can be dangerous and hard to track down.

2) Also when, say fine-tuning UIKit animations, I find myself wasting enormous amount of time adding and removing "self".

R+

Sent from my iPhone

On 04 Dec 2015, at 22:19, David Hart <david@hartbit.com> wrote:

I don't understand the reasoning behind removing the need to access instance properties and functions using self. Swift has always seemed to prefer readability to brevity and the feature makes the distinction between local and instance variables/functions crystal clear. Any good reason I shouldn't go on with the proposition?

Just as example, my proposition makes the following piece of code illegal:

struct FooBar {
  var foo: String = "foobar"

  func bar() {
      print(foo) // compiler error
      print(self.foo) // compiler happy
  }

  func bar2() {
      bar() // compiler error
      self.bar() // compiler happy
  }
}

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

On 04 Dec 2015, at 23:41, Stephen Celis <stephen.celis@gmail.com> wrote:

Are there warnings/diagnostics that could call out when local variables shadow properties? I generally like that `self` is optional and prefer limiting its use to explicitly call out potential retain cycles. Xcode also makes it easy to introspect variable scope, though Xcode is less of a requirement these days...

On Fri, Dec 4, 2015 at 5:34 PM, Rudolf Adamkovič <salutis@me.com <mailto:salutis@me.com>> wrote:
To be a little more specific, here’s a real-world example:

1. Say there’s a method in my class that contains a local variable called “title”.
2. After a while, I decide to remove a part of this method, including the “title” variable.
3. Everything compiles and seems to work just fine.
4. However, I forgot to remove one more line that used the “title” variable.
5. Because we’re in a UIViewController subclass, I'm unknowingly modifying view controller’s title.

R+

> On 4 Dec 2015, at 22:51, Rudolf Adamkovic <salutis@me.com <mailto:salutis@me.com>> wrote:
>
> +1
>
> 1) I actually encountered at least two bugs in my app introduced by this implicit "self" behavior. It can be dangerous and hard to track down.
>
> 2) Also when, say fine-tuning UIKit animations, I find myself wasting enormous amount of time adding and removing "self".
>
> R+
>
> Sent from my iPhone
>
>> On 04 Dec 2015, at 22:19, David Hart <david@hartbit.com <mailto:david@hartbit.com>> wrote:
>>
>> I don't understand the reasoning behind removing the need to access instance properties and functions using self. Swift has always seemed to prefer readability to brevity and the feature makes the distinction between local and instance variables/functions crystal clear. Any good reason I shouldn't go on with the proposition?
>>
>> Just as example, my proposition makes the following piece of code illegal:
>>
>> ```
>> struct FooBar {
>> var foo: String = "foobar"
>>
>> func bar() {
>> print(foo) // compiler error
>> print(self.foo) // compiler happy
>> }
>>
>> func bar2() {
>> bar() // compiler error
>> self.bar() // compiler happy
>> }
>> }
>> ```
>> _______________________________________________
>> 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


(David Hart) #8

Very strong -1.

I have the impression that this topic can be quite divisive.

The ability to elide `self` in most contexts is really nice. Especially when combined with the fact that SourceKitService lets Xcode syntax-colorize properties/methods nicely so the color of the identifier tells me whether it's a method/property on self or something else. I realize that not everybody will be using Xcode (particularly people on other platforms), but in time we should hopefully see other editors gain support for SourceKit to provide more intelligent handling of Swift code as well.

For me, Swift should be clear even without the help of syntax highlighting. Syntax highlighting should come only as a bonus. On a personal note, I’m colourblind and have great difficulties telling colours apart.

Similarly, I rely on the ability to shadow things (including properties of self) a _lot_. And it's not just me; it's very common for e.g. initializers to use property names as the parameter names, such as:

init(x: Int, y: Int) {
    self.x = x
    self.y = y
}

I agree with you on this, as I often use such idioms. That’s why the shadowing warning is not a good solution IMHO.

David.

···

On Fri, Dec 4, 2015, at 02:41 PM, Stephen Celis wrote:

Are there warnings/diagnostics that could call out when local variables shadow properties? I generally like that `self` is optional and prefer limiting its use to explicitly call out potential retain cycles. Xcode also makes it easy to introspect variable scope, though Xcode is less of a requirement these days...

On Fri, Dec 4, 2015 at 5:34 PM, Rudolf Adamkovič <salutis@me.com <mailto:salutis@me.com>> wrote:
To be a little more specific, here’s a real-world example:

1. Say there’s a method in my class that contains a local variable called “title”.
2. After a while, I decide to remove a part of this method, including the “title” variable.
3. Everything compiles and seems to work just fine.
4. However, I forgot to remove one more line that used the “title” variable.
5. Because we’re in a UIViewController subclass, I'm unknowingly modifying view controller’s title.

R+

> On 4 Dec 2015, at 22:51, Rudolf Adamkovic <salutis@me.com <mailto:salutis@me.com>> wrote:
>
> +1
>
> 1) I actually encountered at least two bugs in my app introduced by this implicit "self" behavior. It can be dangerous and hard to track down.
>
> 2) Also when, say fine-tuning UIKit animations, I find myself wasting enormous amount of time adding and removing "self".
>
> R+
>
> Sent from my iPhone
>
>> On 04 Dec 2015, at 22:19, David Hart <david@hartbit.com <mailto:david@hartbit.com>> wrote:
>>
>> I don't understand the reasoning behind removing the need to access instance properties and functions using self. Swift has always seemed to prefer readability to brevity and the feature makes the distinction between local and instance variables/functions crystal clear. Any good reason I shouldn't go on with the proposition?
>>
>> Just as example, my proposition makes the following piece of code illegal:
>>
>> ```
>> struct FooBar {
>> var foo: String = "foobar"
>>
>> func bar() {
>> print(foo) // compiler error
>> print(self.foo) // compiler happy
>> }
>>
>> func bar2() {
>> bar() // compiler error
>> self.bar() // compiler happy
>> }
>> }
>> ```
>> _______________________________________________
>> 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


#9

Wouldn't the warning trigger prior to refactoring and therefore be more
apparent during such a removal?

···

On Fri, Dec 4, 2015 at 5:59 PM, David Hart <david@hartbit.com> wrote:

Stephen, as previously stated by Rudolf, his real-world example would not
trigger such a warning because the title local variable no longer exists
and therefore no longer shadows the instance property.


#10

This is a fair point, though initialization seems to be the most common
exception and could be omitted from the rule.

···

On Fri, Dec 4, 2015 at 6:08 PM, David Hart <david@hartbit.com> wrote:

Similarly, I rely on the ability to shadow things (including properties of
self) a _lot_. And it's not just me; it's very common for e.g. initializers
to use property names as the parameter names, such as:

init(x: Int, y: Int) {
    self.x = x
    self.y = y
}

I agree with you on this, as I often use such idioms. That’s why the
shadowing warning is not a good solution IMHO.


(David Hart) #11

It would, so it’s better than nothing, but it would disappear as soon as the un-intentional bug appears. But, as Kevin stated, there are too many good used of shadowing to suffer a warning.

···

On 05 Dec 2015, at 00:20, Stephen Celis <stephen.celis@gmail.com> wrote:

On Fri, Dec 4, 2015 at 5:59 PM, David Hart <david@hartbit.com <mailto:david@hartbit.com>> wrote:
Stephen, as previously stated by Rudolf, his real-world example would not trigger such a warning because the title local variable no longer exists and therefore no longer shadows the instance property.

Wouldn't the warning trigger prior to refactoring and therefore be more apparent during such a removal?