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

ilya ilya.nikokoshev at gmail.com
Sun Dec 13 12:48:42 CST 2015


> Ilya, I think this may be a presumptuous way of how well programmers
code. When deadlines hit, those first two suggestions go out the window.
And the fourth/last suggestion is not valid for me - changing naming
conventions would be both more confusing and more work (context switching)
than explicit self.

Well, I listed the things that help me deal with the shadowing problem;
your team is still able to use a different solution that you have chosen
for your project.

>  Global state and class state should never be conflated

Well yes, moreover I tend to prohibit any global state at all. But moving
things from a *local* to instance scope is quite a useful pattern.

Whatever syntactic changes are required can be inserted by hand, but the
main point of this example is that I don't see why using an instance scope
should be more painful than using a local scope.

> You can move code to and from closures at will

This is not something that I would call a benefit: normally, when moving
things to closures, you have to make a decision on the capture rules, that
is

func f() {
   bar.doStuff()
}

can become either

async { [bar = bar] in
  bar.doStuff()
}

or

async {
  self.bar.doStuff()
}

I wouldn't say that the second capture semantics – capturing the whole self
and using the value of bar at the time of executing it – is always what we
want when we extract code to closures.

> This is actually the reason why my team chose unanimously to adopt
explicit self as a strict code style guideline.

That's a very interesting data point, thanks.

Ilya.

On Sun, Dec 13, 2015 at 9:33 PM, Dennis Lysenko <dennis.s.lysenko at gmail.com>
wrote:

> > - only expose the minimum necessary amount of names in any scope
>
> > - break functions into small part so that it's easy to see all the local
> name declarations
>
> > - not use any globals, or at least name them in a visually different way
> (UppercaseCamelStyle)
>
> > - name properties and locals in a different way (classProperty,
> local_var)
>
> Ilya, I think this may be a presumptuous way of how well programmers code.
> When deadlines hit, those first two suggestions go out the window. And the
> fourth/last suggestion is not valid for me - changing naming conventions
> would be both more confusing and more work (context switching) than
> explicit self.
>
>
> The other tangible benefit of explicit self is that code becomes more
> refactorable. You can move code to and from closures at will, and moving it
> to unsuitable contexts gives immediate negative feedback. This is actually
> the reason why my team chose unanimously to adopt explicit self as a strict
> code style guideline.
>
>
> -1 to the notion that it makes the transition from global state to class
> state less fluid. Global state and class state should never be conflated
> and implicit self can lead to such conflation. Global functions should be
> carefully rewritten to class dynamics when the transition is desired, and
> implicit self makes it easier to make that transition without careful
> consideration.
>
>
> Overall, I give +1 to the explicit self proposal, -1 to using a special
> operator. Explicit self is neither hard nor particularly verbose in my
> experience; with syntax highlighting, it happens to be very readable. I
> love Ruby, but an @ operator for ivars would be very foreign and would kill
> the aesthetic of the language for me. Not sure where others stand on it.
>
> On Sun, Dec 13, 2015, 4:16 AM ilya via swift-evolution <
> swift-evolution at swift.org> wrote:
>
>> > But implicit self is confusing in a lot of code
>>
>> On the other hand, it allows a logical explanation of how you can take
>> code from global scope and put it into an instance scope:
>>
>> let greeting = "Hello"
>> let name = "Michael"
>>
>> func greet() {
>>     print("\(greeting), \(name)")
>> }
>>
>> seemlessly becomes
>>
>> class Greeter {
>>
>>     let greeting = "Hello"
>>     let name = "Michael"
>>
>>     func greet() {
>>         print("\(greeting), \(name)")
>>     }
>>
>> }
>>
>> > can (and does) lead to shadowing bugs,
>>
>> There are simple strategies that help to minimize the amount of
>> shadowing, e.g.
>>
>> - only expose the minimum necessary amount of names in any scope
>> - break functions into small part so that it's easy to see all the local
>> name declarations
>> - not use any globals, or at least name them in a visually different way
>> (UppercaseCamelStyle)
>> - name properties and locals in a different way (classProperty, local_var)
>>
>> Even without a formal code style, if you tend to make property names
>> longer and local names shorter, your risk of shadowing goes down.
>>
>> > .x and .f() to mark implicit self. I realize that this may conflict
>> with enum usage.
>>
>> This will lead to a lot of ambiguity:
>>
>> func f() {
>>     let x = NSOperation()
>>     .name = "Name" // is it x.name or self.name??
>>    ...
>> }
>>
>> >  If so, then use another marker. For instance :x or ^x or anything.
>>
>> This is workable, but still I think this is one of the best points of
>> Swift – the existence of instance scope where names are simply written
>> as-is. This helps implementing patterns like "take a long function and make
>> it into a struct with a bunch of small functions instead".
>>
>> > is very difficult to reason about in diffs or any other interface that
>> isn't an IDE (especially code review)
>>
>> This is the point where I entirely agree, good code should be easily read
>> in any context.
>> Again, may I suggest you take a look into using a style guide to
>> differentiate visually between local and instance scope?
>>
>> Ilya
>>
>> On Sun, Dec 13, 2015 at 10:15 AM, Rob Napier via swift-evolution <
>> swift-evolution at swift.org> wrote:
>>
>>> I wanted to reopen this discussion that seems to have trailed off.
>>> Requesting the return of self was my very first ask of Swift if I remember
>>> correctly (https://devforums.apple.com/message/1013085). Continued work
>>> in Swift has both strengthened and modified that ask. Here are several of
>>> the examples discussed before:
>>>
>>> https://gist.github.com/schwa/94b11dc0a7a331f46b25
>>> https://gist.github.com/rnapier/478465d1b15e95b98b42
>>> https://gist.github.com/rnapier/4213dc64206b17df6935
>>> https://gist.github.com/dwineman/d6c56ec0c0e2fdb761db
>>>
>>> I get that it seems tedious to type (and read) "self." and I get that
>>> "self." is currently a hint that self might be captured (but doesn't
>>> actually mean that, since you can use self. without capturing, and
>>> sometimes have to, very often in init, so really it's basically meaningless
>>> for that use).
>>>
>>> That's why I suggest using .x and .f() to mark implicit self. I realize
>>> that this may conflict with enum usage. If so, then use another marker. For
>>> instance :x or ^x or anything. But implicit self is confusing in a lot of
>>> code, can (and does) lead to shadowing bugs, and is very difficult to
>>> reason about in diffs or any other interface that isn't an IDE (especially
>>> code review).
>>>
>>> Thoughts, David? I agree with your basic proposal; I just want to amend
>>> it.
>>>
>>> -Rob
>>>
>>>
>>> _______________________________________________
>>> swift-evolution mailing list
>>> swift-evolution at swift.org
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>
>>>
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20151213/f84c58dc/attachment.html>


More information about the swift-evolution mailing list