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


(Rob Napier) #1

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


(ilya) #2

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


(Charles Srstka) #3

Since opinions seem to be divided on this, how about adding an optional warning flag to the compiler, which would warn if one accessed an instance variable or method without self. in front? That way, each person could choose whether they wanted implicit ‘self.’ or not. I know that this warning would be helpful to me, as I’ve already run into some rather weird bugs due to the implicit self, and it would be one less thing to debug.

Charles

···

On Dec 13, 2015, at 1:15 AM, Rob Napier via swift-evolution <swift-evolution@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@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(David Hart) #4

Hi Ilya,

Why use a style guide when the language can enforce rules to eliminate the ambiguity?

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

This helps implementing patterns like "take a long function and make it into a struct with a bunch of small functions instead".

Both of your previous points make sense but they make code editing easier at the expense of readability. For me, readability has always been more important, as we spend most of our time reading than writing code.

That's why I suggest using .x and .f() to mark implicit self.

I agree that that would potentially add confusion to the grammar. I've always liked the @ and @@ prefixes of Ruby for accessing instance and class properties, but I agree that symbols like that would feel a bit foreign in Swift.

David

···

On 13 Dec 2015, at 10:16, ilya via swift-evolution <swift-evolution@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@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@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 Waite) #5

<snip>
I agree that that would potentially add confusion to the grammar. I've always liked the @ and @@ prefixes of Ruby for accessing instance and class properties, but I agree that symbols like that would feel a bit foreign in Swift.

I believe the interesting bit about Ruby in this case is that it only exposes variables through bound scope. self.foo means ‘call foo on object self’.

So @foo is *not* shorthand in Ruby, it provides different functionality. This is similar to using this->foo vs self.foo in Objective C.

-DW

···

On Dec 13, 2015, at 2:40 AM, David Hart via swift-evolution <swift-evolution@swift.org> wrote:

David

On 13 Dec 2015, at 10:16, ilya via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@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 <http://x.name/> or self.name <http://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@swift.org <mailto:swift-evolution@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@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


(ilya) #6

For me, readability has always been more important, as we spend most of

our time reading than writing code.
Agree.

but they make code editing easier at the expense of readability.

Disagree. This really depends on the example. E.g. which is more readable:

struct Vector {
    var dx: Double
    var dy: Double
    var length: Double { return sqrt(dx*dx + dy*dy) }
}

vs

struct Vector {
    var dx: Double
    var dy: Double
    var length: Double { return sqrt(@dx*@dx + @dy*@dy) }
}

struct Vector {
    var dx: Double
    var dy: Double
    var length: Double { return sqrt(self.dx*self.dx + self.dy*self.dy) }
}

···

On Sun, Dec 13, 2015 at 12:40 PM, David Hart <david@hartbit.com> wrote:

Hi Ilya,

Why use a style guide when the language can enforce rules to eliminate the
ambiguity?

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

This helps implementing patterns like "take a long function and make it
into a struct with a bunch of small functions instead".

Both of your previous points make sense but they make code editing easier
at the expense of readability. For me, readability has always been more
important, as we spend most of our time reading than writing code.

That's why I suggest using .x and .f() to mark implicit self.

I agree that that would potentially add confusion to the grammar. I've
always liked the @ and @@ prefixes of Ruby for accessing instance and class
properties, but I agree that symbols like that would feel a bit foreign in
Swift.

David

On 13 Dec 2015, at 10:16, ilya via swift-evolution < > swift-evolution@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@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@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


(Dennis Lysenko) #7

- 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@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@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@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) #8

That is a good alternative.

···

On 13 Dec 2015, at 22:45, Charles Srstka via swift-evolution <swift-evolution@swift.org> wrote:

Since opinions seem to be divided on this, how about adding an optional warning flag to the compiler, which would warn if one accessed an instance variable or method without self. in front?


(David Hart) #9

struct Vector {
    var dx: Double
    var dy: Double
    var length: Double { return sqrt(dx*dx + dy*dy) }
}

vs

struct Vector {
    var dx: Double
    var dy: Double
    var length: Double { return sqrt(@dx*@dx + @dy*@dy) }
}

struct Vector {
    var dx: Double
    var dy: Double
    var length: Double { return sqrt(self.dx*self.dx + self.dy*self.dy) }
}

I don't agree with you because when reading your first example, I have to make a mental gymnastic to find out if the variables are local/global variables or if they are instance properties. It might seem obvious in a small piece of code like yours, but it becomes less so in a class several hundred of lines long.

···

On 13 Dec 2015, at 10:48, ilya <ilya.nikokoshev@gmail.com> wrote:

> For me, readability has always been more important, as we spend most of our time reading than writing code.
Agree.

> but they make code editing easier at the expense of readability.
Disagree. This really depends on the example. E.g. which is more readable:

struct Vector {
    var dx: Double
    var dy: Double
    var length: Double { return sqrt(dx*dx + dy*dy) }
}

vs

struct Vector {
    var dx: Double
    var dy: Double
    var length: Double { return sqrt(@dx*@dx + @dy*@dy) }
}

struct Vector {
    var dx: Double
    var dy: Double
    var length: Double { return sqrt(self.dx*self.dx + self.dy*self.dy) }
}

On Sun, Dec 13, 2015 at 12:40 PM, David Hart <david@hartbit.com> wrote:
Hi Ilya,

Why use a style guide when the language can enforce rules to eliminate the ambiguity?

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

This helps implementing patterns like "take a long function and make it into a struct with a bunch of small functions instead".

Both of your previous points make sense but they make code editing easier at the expense of readability. For me, readability has always been more important, as we spend most of our time reading than writing code.

That's why I suggest using .x and .f() to mark implicit self.

I agree that that would potentially add confusion to the grammar. I've always liked the @ and @@ prefixes of Ruby for accessing instance and class properties, but I agree that symbols like that would feel a bit foreign in Swift.

David

On 13 Dec 2015, at 10:16, ilya via swift-evolution <swift-evolution@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@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@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


(ilya) #10

It might seem obvious in a small piece of code like yours, but it becomes

less so in a class several hundred of lines long.

I'll be happy to take a look at the specific examples and see if perhaps
self-dot access will be useful there.
But even if we disagree you're still able to use self-dot access in any
place where you feel this to be beneficial without any changes in the
language.

Why use a style guide when the language can enforce rules to eliminate

the ambiguity?

Because each project's situation can be unique. For the same reason there's
no need to rush to add concurrency at the language level without
considering other possibilities first.

For the record I would also like it if the "globals must start with an
uppercase letter" rule were enforced by the compiler (well, not in the
playground, those aren't true globals).

It still looks to me that if we make compiler enforce that and the
"instance names must not start with an uppercase letter" rule this
eliminates the ambiguity discussed in this thread.

···

On Sun, Dec 13, 2015 at 13:12 David Hart <david@hartbit.com <javascript:_e(%7B%7D,'cvml','david@hartbit.com');>> wrote:

struct Vector {
    var dx: Double
    var dy: Double
    var length: Double { return sqrt(dx*dx + dy*dy) }
}

vs

struct Vector {
    var dx: Double
    var dy: Double
    var length: Double { return sqrt(@dx*@dx + @dy*@dy) }
}

struct Vector {
    var dx: Double
    var dy: Double
    var length: Double { return sqrt(self.dx*self.dx + self.dy*self.dy) }
}

I don't agree with you because when reading your first example, I have to
make a mental gymnastic to find out if the variables are local/global
variables or if they are instance properties. It might seem obvious in a
small piece of code like yours, but it becomes less so in a class several
hundred of lines long.

On 13 Dec 2015, at 10:48, ilya <ilya.nikokoshev@gmail.com > <javascript:_e(%7B%7D,'cvml','ilya.nikokoshev@gmail.com');>> wrote:

> For me, readability has always been more important, as we spend most of
our time reading than writing code.
Agree.

> but they make code editing easier at the expense of readability.
Disagree. This really depends on the example. E.g. which is more readable:

struct Vector {
    var dx: Double
    var dy: Double
    var length: Double { return sqrt(dx*dx + dy*dy) }
}

vs

struct Vector {
    var dx: Double
    var dy: Double
    var length: Double { return sqrt(@dx*@dx + @dy*@dy) }
}

struct Vector {
    var dx: Double
    var dy: Double
    var length: Double { return sqrt(self.dx*self.dx + self.dy*self.dy) }
}

On Sun, Dec 13, 2015 at 12:40 PM, David Hart <david@hartbit.com > <javascript:_e(%7B%7D,'cvml','david@hartbit.com');>> wrote:

Hi Ilya,

Why use a style guide when the language can enforce rules to eliminate
the ambiguity?

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

This helps implementing patterns like "take a long function and make it
into a struct with a bunch of small functions instead".

Both of your previous points make sense but they make code editing easier
at the expense of readability. For me, readability has always been more
important, as we spend most of our time reading than writing code.

That's why I suggest using .x and .f() to mark implicit self.

I agree that that would potentially add confusion to the grammar. I've
always liked the @ and @@ prefixes of Ruby for accessing instance and class
properties, but I agree that symbols like that would feel a bit foreign in
Swift.

David

On 13 Dec 2015, at 10:16, ilya via swift-evolution < >> swift-evolution@swift.org >> <javascript:_e(%7B%7D,'cvml','swift-evolution@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@swift.org >> <javascript:_e(%7B%7D,'cvml','swift-evolution@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@swift.org
<javascript:_e(%7B%7D,'cvml','swift-evolution@swift.org');>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
<javascript:_e(%7B%7D,'cvml','swift-evolution@swift.org');>
https://lists.swift.org/mailman/listinfo/swift-evolution


(ilya) #11

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@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@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@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@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


(Andrew Brown) #12

This discussion isn't going to be solved quickly so +1 for a compiler flag.
I'd propose the flag generates an error if member variables are accessed without self.
Then after some time we can survey the community (or scan GitHub) to see how many people use the flag.
(making it a preference in Xcode would also help)

ABR.

···

On 14 Dec 2015, at 07:12, David Hart via swift-evolution <swift-evolution@swift.org> wrote:

On 13 Dec 2015, at 22:45, Charles Srstka via swift-evolution <swift-evolution@swift.org> wrote:

Since opinions seem to be divided on this, how about adding an optional warning flag to the compiler, which would warn if one accessed an instance variable or method without self. in front?

That is a good alternative.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Pierre Monod-Broca) #13

+1 on a way to tell the compiler to warn the developper (a cli flag or a compiler directive in the file)

Pierre

···

Le 14 déc. 2015 à 09:01, Andrew Brown via swift-evolution <swift-evolution@swift.org> a écrit :

This discussion isn't going to be solved quickly so +1 for a compiler flag.
I'd propose the flag generates an error if member variables are accessed without self.
Then after some time we can survey the community (or scan GitHub) to see how many people use the flag.
(making it a preference in Xcode would also help)

ABR.

On 14 Dec 2015, at 07:12, David Hart via swift-evolution <swift-evolution@swift.org> wrote:

On 13 Dec 2015, at 22:45, Charles Srstka via swift-evolution <swift-evolution@swift.org> wrote:

Since opinions seem to be divided on this, how about adding an optional warning flag to the compiler, which would warn if one accessed an instance variable or method without self. in front?

That is a good alternative.
_______________________________________________
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


(Jeremy Pereira) #14

This discussion isn't going to be solved quickly so +1 for a compiler flag.
I'd propose the flag generates an error if member variables are accessed without self.

I’d propose it only be a warning. The reason for this is that Chris Lattner, in an unrelated thread, expressed an aversion to compiler flags that create different dialects of the language and I agree with him.

···

On 14 Dec 2015, at 09:01, Andrew Brown via swift-evolution <swift-evolution@swift.org> wrote:

Then after some time we can survey the community (or scan GitHub) to see how many people use the flag.
(making it a preference in Xcode would also help)

ABR.

On 14 Dec 2015, at 07:12, David Hart via swift-evolution <swift-evolution@swift.org> wrote:

On 13 Dec 2015, at 22:45, Charles Srstka via swift-evolution <swift-evolution@swift.org> wrote:

Since opinions seem to be divided on this, how about adding an optional warning flag to the compiler, which would warn if one accessed an instance variable or method without self. in front?

That is a good alternative.
_______________________________________________
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


(Andrey Tarantsov) #15

I agree with Ilya here:

> but they make code editing easier at the expense of readability.
Disagree. This really depends on the example. E.g. which is more readable:

    var length: Double { return sqrt(dx*dx + dy*dy) }

    var length: Double { return sqrt(@dx*@dx + @dy*@dy) }

    var length: Double { return sqrt(self.dx*self.dx + self.dy*self.dy) }

I find that this holds true in larger classes as well (or even more). I have tons of view controllers and views that do stuff like:

obj1.prop1 = X
obj1.prop2 = Y
...
obj1.prop10 = Z
superview1.addSubview(obj1)

Adding “self.” everywhere adds a significant amount of visual noise; I've tried _property and self.property access styles in Objective-C, and find the former one to be noticeably more readable.

To be fair, there are cases when it's not immediately clear if something is a property or a variable. That's why you can still add an explicit self. if you want. Some of those are also probably code smells.

A.


(Marc Knaup) #16

I also prefer to keep self. optional.

In the past I wrote a lot code in Java and decided that I want to
consistently use "this." in my code whenever possible. Eclipse even
automatically inserted it for me every time I saved the file so I usually
didn't have to write it on my own. Over time I noticed that while it did
slightly improve clarity in *some* cases my code started looking like it
consists of plenty of this keywords with some actual logic spread in
between.

Then Swift was released and I began migrating our Objective-C app to Swift.
I noticed that the common approach was to refer to self implicitly whenever
possible instead of writing it explicitly and I followed that approach. Now
our team has built two large Swift apps which are even broken down into
plenty of modules. It happened very very rarely that I had to look up
whether a variable access or function call was referring to a local symbol
or to one in self. Most of the time it was clear by context.

I liked the result so much that I started writing and converting Java-code
the same way and now omit this whenever possible.

*Bottom line:*
I agree that referring to symbols in self explicitly does improve clarity
in a few cases. But that comes at a high cost where the whole code gets
polluted by and hidden between a lot placements of the self keyword. For me
the benefits of omitting self for decluttering outweighs the occasional
benefit of improved clarity by far.

Also the clarity can be improved easily by the IDE in this case. The IDE
can present instance symbols and global symbols visually distinct which
removes any remaining ambiguity. So in good IDEs the benefit of requiring
an explicit self would even be practically zero.

PS: Also note that this discussion of implicitly vs. explicitly would have
to also extend to various other occasions like global vs. local vs. nested
type names and even type inference, where a variable's type might also be
unclear occasionally unless the IDE supports you.

···

On Sun, Dec 13, 2015 at 11:35 AM, ilya via swift-evolution < swift-evolution@swift.org> wrote:

> It might seem obvious in a small piece of code like yours, but it
becomes less so in a class several hundred of lines long.

I'll be happy to take a look at the specific examples and see if perhaps
self-dot access will be useful there.
But even if we disagree you're still able to use self-dot access in any
place where you feel this to be beneficial without any changes in the
language.

> Why use a style guide when the language can enforce rules to eliminate
the ambiguity?

Because each project's situation can be unique. For the same reason
there's no need to rush to add concurrency at the language level without
considering other possibilities first.

For the record I would also like it if the "globals must start with an
uppercase letter" rule were enforced by the compiler (well, not in the
playground, those aren't true globals).

It still looks to me that if we make compiler enforce that and the
"instance names must not start with an uppercase letter" rule this
eliminates the ambiguity discussed in this thread.

On Sun, Dec 13, 2015 at 13:12 David Hart <david@hartbit.com> wrote:

struct Vector {
    var dx: Double
    var dy: Double
    var length: Double { return sqrt(dx*dx + dy*dy) }
}

vs

struct Vector {
    var dx: Double
    var dy: Double
    var length: Double { return sqrt(@dx*@dx + @dy*@dy) }
}

struct Vector {
    var dx: Double
    var dy: Double
    var length: Double { return sqrt(self.dx*self.dx + self.dy*self.dy) }
}

I don't agree with you because when reading your first example, I have to
make a mental gymnastic to find out if the variables are local/global
variables or if they are instance properties. It might seem obvious in a
small piece of code like yours, but it becomes less so in a class several
hundred of lines long.

On 13 Dec 2015, at 10:48, ilya <ilya.nikokoshev@gmail.com> wrote:

> For me, readability has always been more important, as we spend most of
our time reading than writing code.
Agree.

> but they make code editing easier at the expense of readability.
Disagree. This really depends on the example. E.g. which is more readable:

struct Vector {
    var dx: Double
    var dy: Double
    var length: Double { return sqrt(dx*dx + dy*dy) }
}

vs

struct Vector {
    var dx: Double
    var dy: Double
    var length: Double { return sqrt(@dx*@dx + @dy*@dy) }
}

struct Vector {
    var dx: Double
    var dy: Double
    var length: Double { return sqrt(self.dx*self.dx + self.dy*self.dy) }
}

On Sun, Dec 13, 2015 at 12:40 PM, David Hart <david@hartbit.com> wrote:

Hi Ilya,

Why use a style guide when the language can enforce rules to eliminate
the ambiguity?

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

This helps implementing patterns like "take a long function and make it
into a struct with a bunch of small functions instead".

Both of your previous points make sense but they make code editing
easier at the expense of readability. For me, readability has always been
more important, as we spend most of our time reading than writing code.

That's why I suggest using .x and .f() to mark implicit self.

I agree that that would potentially add confusion to the grammar. I've
always liked the @ and @@ prefixes of Ruby for accessing instance and class
properties, but I agree that symbols like that would feel a bit foreign in
Swift.

David

On 13 Dec 2015, at 10:16, ilya via swift-evolution < >>> swift-evolution@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@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@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) #17

For the record I would also like it if the "globals must start with an uppercase letter" rule were enforced by the compiler (well, not in the playground, those aren't true globals).

+1, in the same vein, global a should stand out :slight_smile:

···

On 13 Dec 2015, at 11:35, ilya <ilya.nikokoshev@gmail.com> wrote:

> It might seem obvious in a small piece of code like yours, but it becomes less so in a class several hundred of lines long.

I'll be happy to take a look at the specific examples and see if perhaps self-dot access will be useful there.
But even if we disagree you're still able to use self-dot access in any place where you feel this to be beneficial without any changes in the language.

> Why use a style guide when the language can enforce rules to eliminate the ambiguity?

Because each project's situation can be unique. For the same reason there's no need to rush to add concurrency at the language level without considering other possibilities first.

For the record I would also like it if the "globals must start with an uppercase letter" rule were enforced by the compiler (well, not in the playground, those aren't true globals).

It still looks to me that if we make compiler enforce that and the "instance names must not start with an uppercase letter" rule this eliminates the ambiguity discussed in this thread.

On Sun, Dec 13, 2015 at 13:12 David Hart <david@hartbit.com> wrote:

struct Vector {
    var dx: Double
    var dy: Double
    var length: Double { return sqrt(dx*dx + dy*dy) }
}

vs

struct Vector {
    var dx: Double
    var dy: Double
    var length: Double { return sqrt(@dx*@dx + @dy*@dy) }
}

struct Vector {
    var dx: Double
    var dy: Double
    var length: Double { return sqrt(self.dx*self.dx + self.dy*self.dy) }
}

I don't agree with you because when reading your first example, I have to make a mental gymnastic to find out if the variables are local/global variables or if they are instance properties. It might seem obvious in a small piece of code like yours, but it becomes less so in a class several hundred of lines long.

On 13 Dec 2015, at 10:48, ilya <ilya.nikokoshev@gmail.com> wrote:

> For me, readability has always been more important, as we spend most of our time reading than writing code.
Agree.

> but they make code editing easier at the expense of readability.
Disagree. This really depends on the example. E.g. which is more readable:

struct Vector {
    var dx: Double
    var dy: Double
    var length: Double { return sqrt(dx*dx + dy*dy) }
}

vs

struct Vector {
    var dx: Double
    var dy: Double
    var length: Double { return sqrt(@dx*@dx + @dy*@dy) }
}

struct Vector {
    var dx: Double
    var dy: Double
    var length: Double { return sqrt(self.dx*self.dx + self.dy*self.dy) }
}

On Sun, Dec 13, 2015 at 12:40 PM, David Hart <david@hartbit.com> wrote:
Hi Ilya,

Why use a style guide when the language can enforce rules to eliminate the ambiguity?

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

This helps implementing patterns like "take a long function and make it into a struct with a bunch of small functions instead".

Both of your previous points make sense but they make code editing easier at the expense of readability. For me, readability has always been more important, as we spend most of our time reading than writing code.

That's why I suggest using .x and .f() to mark implicit self.

I agree that that would potentially add confusion to the grammar. I've always liked the @ and @@ prefixes of Ruby for accessing instance and class properties, but I agree that symbols like that would feel a bit foreign in Swift.

David

On 13 Dec 2015, at 10:16, ilya via swift-evolution <swift-evolution@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@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@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


(Dave Abrahams) #18

Please consider that individually-selectable warnings have a tendency to do the same thing.

Cheers,

-Dave

···

On Dec 14, 2015, at 7:29 AM, Jeremy Pereira via swift-evolution <swift-evolution@swift.org> wrote:

On 14 Dec 2015, at 09:01, Andrew Brown via swift-evolution <swift-evolution@swift.org> wrote:

This discussion isn't going to be solved quickly so +1 for a compiler flag.
I'd propose the flag generates an error if member variables are accessed without self.

I’d propose it only be a warning. The reason for this is that Chris Lattner, in an unrelated thread, expressed an aversion to compiler flags that create different dialects of the language and I agree with him.


#19

I believe Chris stated he was fine with options that enforced existing syntax, just not ones that changed the grammar.

In this case, code would compile without the flag regardless of whether or not it was originally written with the flag.

I believe it was also stated that some sort of attribute in the file was preferred over a compiler flag, which definitely seems like a good idea to me.

···

On Dec 14, 2015, 09:29 -0600, Jeremy Pereira via swift-evolution<swift-evolution@swift.org>, wrote:

> On 14 Dec 2015, at 09:01, Andrew Brown via swift-evolution<swift-evolution@swift.org>wrote:
>
> This discussion isn't going to be solved quickly so +1 for a compiler flag.
> I'd propose the flag generates an error if member variables are accessed without self.

I’d propose it only be a warning. The reason for this is that Chris Lattner, in an unrelated thread, expressed an aversion to compiler flags that create different dialects of the language and I agree with him.

> Then after some time we can survey the community (or scan GitHub) to see how many people use the flag.
> (making it a preference in Xcode would also help)
>
> ABR.
>
> > On 14 Dec 2015, at 07:12, David Hart via swift-evolution<swift-evolution@swift.org>wrote:
> >
> >
> > > On 13 Dec 2015, at 22:45, Charles Srstka via swift-evolution<swift-evolution@swift.org>wrote:
> > >
> > > Since opinions seem to be divided on this, how about adding an optional warning flag to the compiler, which would warn if one accessed an instance variable or method without self. in front?
> >
> > That is a good alternative.
> > _______________________________________________
> > 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


(Rob Napier) #20

Agreed. This should not be a warning. There should be a correct way to
reference global functions, constants, variables, methods, and properties.
If leading "self." or punctuation is recommended, it should be required. If
scopes should have no distinction, then adding unnecessary "self" should be
discouraged at a minimum, not encouraged with an optional warning.

I prefer a distinction for methods and properties (specifically I prefer
punctuation), but I currently drop all unnecessary "self." because
consistency is more critical than preference, and Apple's sample code
doesn't use "self." except where required. Adding warnings makes it very
hard to share code that was written by different teams with different
opinions. It is better to bend than splinter.

But I do find that the current system (where a property looks like a local
variable and a method looks just like a global function) makes code review
harder in the tools that code review is usually done with (which are web
browsers, email and chat sessions, not editors or IDEs). Since I believe
that code review is second only to strong types in reducing bugs, I want
code review to be as easy as possible. So I advocate a distinction, and
think punctuation (particularly :x) is the lightest-weight solution.

But please, no warnings. There should be a single approach for stdlib, and
that approach should be what we all use.

-Rob

···

On Mon, Dec 14, 2015 at 10:32 AM, Dave Abrahams via swift-evolution < swift-evolution@swift.org> wrote:

> On Dec 14, 2015, at 7:29 AM, Jeremy Pereira via swift-evolution < > swift-evolution@swift.org> wrote:
>
>>
>> On 14 Dec 2015, at 09:01, Andrew Brown via swift-evolution < > swift-evolution@swift.org> wrote:
>>
>> This discussion isn't going to be solved quickly so +1 for a compiler
flag.
>> I'd propose the flag generates an error if member variables are
accessed without self.
>
> I’d propose it only be a warning. The reason for this is that Chris
Lattner, in an unrelated thread, expressed an aversion to compiler flags
that create different dialects of the language and I agree with him.

Please consider that individually-selectable warnings have a tendency to
do the same thing.