[swift-evolution] Proposal: Re-instate mandatory self for accessing instance properties and functions

David Hart david at hartbit.com
Fri Dec 4 16:59:07 CST 2015


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


> On 04 Dec 2015, at 23:41, Stephen Celis <stephen.celis at 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 at me.com <mailto:salutis at 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 at me.com <mailto:salutis at 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 at hartbit.com <mailto:david at 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 at swift.org <mailto:swift-evolution at swift.org>
> >> https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>
> > _______________________________________________
> > swift-evolution mailing list
> > swift-evolution at swift.org <mailto:swift-evolution at swift.org>
> > https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
> https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>
> 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20151204/8d4f1eb5/attachment-0001.html>


More information about the swift-evolution mailing list