[Pitch] Adding a Self type name shortcut for static member access


(Erica Sadun) #1

Are there reasons that prevent using `Self` as a synonym for an instance's type name?

Consider:

struct MyStruct {
    static func foo() { print("foo") }
    func bar() {
        MyStruct.foo() // works
        self.dynamicType.foo() // works
        Self.foo() // error
    }
}

Obviously, you can always name a type directly or use `self.dynamicType` but
neither solution does any favors for readability. Both approaches obscure intent,
especially as type names grow large: `MyExtremelyLargeTypeName.staticMember`,
for example. Plus, as Kevin B pointed out to me, `self.dynamicType.classMember`
and `TypeName.classMember` may not be synonyms in class types with non-final members.

I'd like to see `Self.staticMember` introduced as a synonym for `TypeName.staticMember`.

Thoughts?

-- E


(Joe Groff) #2

There's the wrinkle of inheritance, as there so often is. `Self` inside a class scope already means "the dynamic class of 'self'", not "the type this declaration statically appears within". Now, we really ought to allow you to utter Self in the bodies of class methods too. It would be consistent to extend that courtesy to value types, where dynamic `Self` always matches the static type, from that principle.

-Joe

···

On Apr 4, 2016, at 11:00 AM, Erica Sadun via swift-evolution <swift-evolution@swift.org> wrote:

Are there reasons that prevent using `Self` as a synonym for an instance's type name?

Consider:

struct MyStruct {
    static func foo() { print("foo") }
    func bar() {
        MyStruct.foo() // works
        self.dynamicType.foo() // works
        Self.foo() // error
    }
}

Obviously, you can always name a type directly or use `self.dynamicType` but
neither solution does any favors for readability. Both approaches obscure intent,
especially as type names grow large: `MyExtremelyLargeTypeName.staticMember`,
for example. Plus, as Kevin B pointed out to me, `self.dynamicType.classMember`
and `TypeName.classMember` may not be synonyms in class types with non-final members.

I'd like to see `Self.staticMember` introduced as a synonym for `TypeName.staticMember`.


(Timothy Wood) #3

Are there reasons that prevent using `Self` as a synonym for an instance's type name?

[...]

I'd like to see `Self.staticMember` introduced as a synonym for `TypeName.staticMember`.

I would love to see a way to get the type of the "enclosing thing at compile time”. In my particular case, I’m using the type as a generic parameter to tag a created resource with something like:

class Client: PropertyOwner {
  let intProperty = Client.property(“name”, Int(0))
}

where PropertyOwner has a static property<Owner, DataType>(...)

With `Self` meaning the static version of the thing being compiled, I could at least write:

class Client: PropertyOwner {
  let intProperty = Self.property(“name”, Int(0))
}

which would have the benefit of being harder to mess up due to copy-pasting between different PropertyOwner implementors.

I would love to be able to omit the `Self.` entirely, but instances can’t call functions on themselves at init time, and instances don’t see static funcs, so that probably won’t fly =)

The particular spelling of ‘static self` doesn’t matter too much to me, so if `Self` needs to be the runtime type of the executing class then maybe `StaticSelf` could be added.

-tim

···

On Apr 4, 2016, at 11:00 AM, Erica Sadun via swift-evolution <swift-evolution@swift.org> wrote:


(Erica Sadun) #4

Would using another word or symbol fix that problem?

-- E

···

On Apr 4, 2016, at 12:13 PM, Joe Groff <jgroff@apple.com> wrote:

On Apr 4, 2016, at 11:00 AM, Erica Sadun via swift-evolution <swift-evolution@swift.org> wrote:

Are there reasons that prevent using `Self` as a synonym for an instance's type name?

Consider:

struct MyStruct {
   static func foo() { print("foo") }
   func bar() {
       MyStruct.foo() // works
       self.dynamicType.foo() // works
       Self.foo() // error
   }
}

Obviously, you can always name a type directly or use `self.dynamicType` but
neither solution does any favors for readability. Both approaches obscure intent,
especially as type names grow large: `MyExtremelyLargeTypeName.staticMember`,
for example. Plus, as Kevin B pointed out to me, `self.dynamicType.classMember`
and `TypeName.classMember` may not be synonyms in class types with non-final members.

I'd like to see `Self.staticMember` introduced as a synonym for `TypeName.staticMember`.

There's the wrinkle of inheritance, as there so often is. `Self` inside a class scope already means "the dynamic class of 'self'", not "the type this declaration statically appears within". Now, we really ought to allow you to utter Self in the bodies of class methods too. It would be consistent to extend that courtesy to value types, where dynamic `Self` always matches the static type, from that principle.

-Joe


(Sean Heber) #5

I’ve wondered this as well. Using “self.dynamicType” is noisy and somewhat esoteric, and using “MyStruct.foo” is bad the moment you want to rename “MyStruct”.

l8r
Sean

···

On Apr 4, 2016, at 1:00 PM, Erica Sadun via swift-evolution <swift-evolution@swift.org> wrote:

Are there reasons that prevent using `Self` as a synonym for an instance's type name?

Consider:

struct MyStruct {
    static func foo() { print("foo") }
    func bar() {
        MyStruct.foo() // works
        self.dynamicType.foo() // works
        Self.foo() // error
    }
}

Obviously, you can always name a type directly or use `self.dynamicType` but
neither solution does any favors for readability. Both approaches obscure intent,
especially as type names grow large: `MyExtremelyLargeTypeName.staticMember`,
for example. Plus, as Kevin B pointed out to me, `self.dynamicType.classMember`
and `TypeName.classMember` may not be synonyms in class types with non-final members.

I'd like to see `Self.staticMember` introduced as a synonym for `TypeName.staticMember`.

Thoughts?

-- E

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


(Brent Royal-Gordon) #6

Are there reasons that prevent using `Self` as a synonym for an instance's type name?

Consider:

struct MyStruct {
    static func foo() { print("foo") }
    func bar() {
        MyStruct.foo() // works
        self.dynamicType.foo() // works
        Self.foo() // error
    }
}

Obviously, you can always name a type directly or use `self.dynamicType` but
neither solution does any favors for readability. Both approaches obscure intent,
especially as type names grow large: `MyExtremelyLargeTypeName.staticMember`,
for example. Plus, as Kevin B pointed out to me, `self.dynamicType.classMember`
and `TypeName.classMember` may not be synonyms in class types with non-final members.

I'd like to see `Self.staticMember` introduced as a synonym for `TypeName.staticMember`.

Thoughts?

I'm kind of struggling with how best to design this. Here's the most coherent design I've been able to come up with so far.

* Adopt the proposal to no longer require `.self` on types to get the type instance. Using a type name in expression context gives you the type instance.
* Every variable `foo` has a typealias attached to it, `foo.Self`. This is the static (compile-time declared or inferred) type of that instance. You can use it anywhere you can use a type name, including in declarations. If it's used in an expression, it becomes the type instance of the variable's static type.
* Every variable `foo` has a special typealias attached to it, `foo.DynamicSelf`. This is the dynamic (runtime assigned) type of that instance. In theory you can use it anywhere you can use a type name, though in practice there are probably significant limitations. If it's used an expression, it become the type instance of the variable's dynamic type.
* A bare `Self` or `DynamicSelf` is a shorthand for `self.Self` or `self.DynamicSelf`.

`DynamicSelf` subsumes the roles of both the old `Self` and `dynamicType`. `Self` is both an alias for the declared type and a way to get its type instance.

This gives us a number of new abilities:

  Self.classMember() // Instead of ReallyLongClassName.classMember()
  foo.Self.classMember() // Likewise, but for a different variable
  
  let self2: Self // Match the static type of self
  let foo2: foo.Self // Match the static type of a different variable
  
  DynamicSelf.classMember() // Instead of self.dynamicType.classMember()
  foo.DynamicSelf.classMember() // Likewise

  let self3: DynamicSelf // Match the dynamic type of self
  let foo3: foo.DynamicSelf // Match the dynamic type of a different variable
  // (Those would probably require certain restrictions, like the base variable has to be
  // immutable and the assignment has to come from a function returning a DynamicSelf
  // derived from `self`/`foo`.)
  
  // Make promises about matching dynamic types of parameters besides `self`:
  func tenMinutesAfter(date: NSDate) -> date.DynamicSelf {
    return date.adding(10 * 60) // Note that `adding(_: NSTimeInterval)` returns DynamicSelf
  }
  
  // Possible alternative to generic syntax:
  func removingCommonPrefix(_ one: Collection, _ two: Collection) -> (one.Self.SubSequence, two.Self.SubSequence) where one.Self.Element == two.Self.Element, one.Self.Element: Equatable {
    for (oneIndex, twoIndex) in zip(one.indices + [one.endIndex], two.indices + [two.endIndex]) {
      if oneIndex == one.endIndex || twoIndex == two.endIndex || one[oneIndex] != two[twoIndex] {
        return (one.suffixFrom(oneIndex), two.suffixFrom(twoIndex))
      }
    }
    fatalError("Can't get here")
  }

The only disadvantage I see to this approach is that code which currently uses `Self` will be longer. But there may be other problems as well. I'm not entirely sure I have a good handle on the existing `Self` vs. `dynamicType`; it's possible the connection I see between them is spurious or ill-defined.

By the way, an alternative would be to leave the dynamic type as `Self` and call the static type `Type`, which I *think* would generalize the existing notion of the metatype being accessible as `Type`. In other words:

  Type.classMember() // Instead of ReallyLongClassName.classMember()
  foo.Type.classMember() // Likewise, but for a different variable
  
  let self2: Type // Match the static type of self
  let foo2: foo.Type // Match the static type of a different variable
  
  Self.classMember() // Instead of self.dynamicType.classMember()
  foo.Self.classMember() // Likewise

  let self3: Self // Match the dynamic type of self
  let foo3: foo.Self // Match the dynamic type of a different variable
  // (Those would probably require certain restrictions, like the base variable has to be
  // immutable and the assignment has to come from a function returning a Self
  // derived from `self`/`foo`.)
  
  // Make promises about matching dynamic types of parameters besides `self`:
  func tenMinutesAfter(date: NSDate) -> date.Self {
    return date.adding(10 * 60) // Note that `adding(_: NSTimeInterval)` returns Self
  }
  
  // Possible alternative to generic syntax:
  func removingCommonPrefix(_ one: Collection, _ two: Collection) -> (one.Type.SubSequence, two.Type.SubSequence) where one.Type.Element == two.Type.Element, one.Type.Element: Equatable {
    for (oneIndex, twoIndex) in zip(one.indices + [one.endIndex], two.indices + [two.endIndex]) {
      if oneIndex == one.endIndex || twoIndex == two.endIndex || one[oneIndex] != two[twoIndex] {
        return (one.suffixFrom(oneIndex), two.suffixFrom(twoIndex))
      }
    }
    fatalError("Can't get here")
  }

But I'm even *less* certain that `someVariable.Type` and `SomeClass.Type` are similar in any real sense, so I have my doubts about the wisdom of that one.

···

--
Brent Royal-Gordon
Architechies


(Howard Lovatt) #7

If the `.StaticMember` (no type name) notation discussed already at least
twice, in the context of expanding the `.EnumCase` syntax, was accepted,
this would eleviate the problem.

···

On Tuesday, 5 April 2016, Timothy Wood via swift-evolution < swift-evolution@swift.org> wrote:

On Apr 4, 2016, at 11:00 AM, Erica Sadun via swift-evolution < > swift-evolution@swift.org > <javascript:_e(%7B%7D,'cvml','swift-evolution@swift.org');>> wrote:

Are there reasons that prevent using `Self` as a synonym for an instance's
type name?

[...]

I'd like to see `Self.staticMember` introduced as a synonym for
`TypeName.staticMember`.

I would love to see a way to get the type of the "enclosing thing at
compile time”. In my particular case, I’m using the type as a generic
parameter to tag a created resource with something like:

class Client: PropertyOwner {
let intProperty = Client.property(“name”, Int(0))
}

where PropertyOwner has a static property<Owner, DataType>(...)

With `Self` meaning the static version of the thing being compiled, I
could at least write:

class Client: PropertyOwner {
let intProperty = Self.property(“name”, Int(0))
}

which would have the benefit of being harder to mess up due to
copy-pasting between different PropertyOwner implementors.

I would love to be able to omit the `Self.` entirely, but instances can’t
call functions on themselves at init time, and instances don’t see static
funcs, so that probably won’t fly =)

The particular spelling of ‘static self` doesn’t matter too much to me, so
if `Self` needs to be the runtime type of the executing class then maybe
`StaticSelf` could be added.

-tim

--
-- Howard.


(Timothy Wood) #8

I was thinking about the syntax a bit further and it seems like the capability that would be added is like #file, in that it does some compile-time textual replacement. So, perhaps #Self would work?

Also, along these lines, I would find use for call-site interpolation like #file has. I could then do a free function version of my property() call that was something like:

  func property(ownerType: PropertyOwner.Type = #Self, ...) { }

which would only be callable from w/in things conforming to or subclassing PropertyOwner.

-tim

···

On Apr 4, 2016, at 1:39 PM, Howard Lovatt <howard.lovatt@gmail.com> wrote:

If the `.StaticMember` (no type name) notation discussed already at least twice, in the context of expanding the `.EnumCase` syntax, was accepted, this would eleviate the problem.


(Joe Groff) #9

My preference would be for there to be only one Self, and have it always be the dynamic type of 'self'. Some people disagree, but I don't think it's all that onerous to have to write ClassName.foo if that's really what you specifically mean.

-Joe

···

On Apr 4, 2016, at 11:17 AM, Erica Sadun <erica@ericasadun.com> wrote:

On Apr 4, 2016, at 12:13 PM, Joe Groff <jgroff@apple.com> wrote:

On Apr 4, 2016, at 11:00 AM, Erica Sadun via swift-evolution <swift-evolution@swift.org> wrote:

Are there reasons that prevent using `Self` as a synonym for an instance's type name?

Consider:

struct MyStruct {
   static func foo() { print("foo") }
   func bar() {
       MyStruct.foo() // works
       self.dynamicType.foo() // works
       Self.foo() // error
   }
}

Obviously, you can always name a type directly or use `self.dynamicType` but
neither solution does any favors for readability. Both approaches obscure intent,
especially as type names grow large: `MyExtremelyLargeTypeName.staticMember`,
for example. Plus, as Kevin B pointed out to me, `self.dynamicType.classMember`
and `TypeName.classMember` may not be synonyms in class types with non-final members.

I'd like to see `Self.staticMember` introduced as a synonym for `TypeName.staticMember`.

There's the wrinkle of inheritance, as there so often is. `Self` inside a class scope already means "the dynamic class of 'self'", not "the type this declaration statically appears within". Now, we really ought to allow you to utter Self in the bodies of class methods too. It would be consistent to extend that courtesy to value types, where dynamic `Self` always matches the static type, from that principle.

-Joe

Would using another word or symbol fix that problem?


(Erica Sadun) #10

There's a pleasing simplicity to that approach.

-- E

···

On Apr 4, 2016, at 8:13 PM, Joe Groff <jgroff@apple.com> wrote:

On Apr 4, 2016, at 11:17 AM, Erica Sadun <erica@ericasadun.com> wrote:

On Apr 4, 2016, at 12:13 PM, Joe Groff <jgroff@apple.com> wrote:

On Apr 4, 2016, at 11:00 AM, Erica Sadun via swift-evolution <swift-evolution@swift.org> wrote:

Are there reasons that prevent using `Self` as a synonym for an instance's type name?

Consider:

struct MyStruct {
  static func foo() { print("foo") }
  func bar() {
      MyStruct.foo() // works
      self.dynamicType.foo() // works
      Self.foo() // error
  }
}

Obviously, you can always name a type directly or use `self.dynamicType` but
neither solution does any favors for readability. Both approaches obscure intent,
especially as type names grow large: `MyExtremelyLargeTypeName.staticMember`,
for example. Plus, as Kevin B pointed out to me, `self.dynamicType.classMember`
and `TypeName.classMember` may not be synonyms in class types with non-final members.

I'd like to see `Self.staticMember` introduced as a synonym for `TypeName.staticMember`.

There's the wrinkle of inheritance, as there so often is. `Self` inside a class scope already means "the dynamic class of 'self'", not "the type this declaration statically appears within". Now, we really ought to allow you to utter Self in the bodies of class methods too. It would be consistent to extend that courtesy to value types, where dynamic `Self` always matches the static type, from that principle.

-Joe

Would using another word or symbol fix that problem?

My preference would be for there to be only one Self, and have it always be the dynamic type of 'self'. Some people disagree, but I don't think it's all that onerous to have to write ClassName.foo if that's really what you specifically mean.

-Joe


(Timothy Wood) #11

I would agree that Self should remain the dynamic version, but adding StaticSelf (however it is spelled) adds the safety of being able to refactor code w/o forgetting to rename an explicit class name. It adds the ability to more clearly express what you mean (“the containing class/struct, whatever it happens to be”), and it would reduce effort while reading code (in that you could see quickly that it was StaticSelf instead of having to look to see whether it was the same name as the enclosing type every time you read the code).

My support for StaticSelf isn’t at all about it being too hard to type ClassName.foo the first time, but about being able to read and maintain code after the fact.

And, of course, the argument that writing ClassName.foo isn’t onerous is dangerously close to an argument for dropping “.foo” with a type inferred by the call site... =)

-tim

···

On Apr 4, 2016, at 7:13 PM, Joe Groff via swift-evolution <swift-evolution@swift.org> wrote:

Would using another word or symbol fix that problem?

My preference would be for there to be only one Self, and have it always be the dynamic type of 'self'. Some people disagree, but I don't think it's all that onerous to have to write ClassName.foo if that's really what you specifically mean.


(Andrey Tarantsov) #12

My preference would be for there to be only one Self, and have it always be the dynamic type of 'self'. Some people disagree, but I don't think it's all that onerous to have to write ClassName.foo if that's really what you specifically mean.

+1. There's just no way we want to explain two kinds of Selves to people.

However, we need to make sure it works in these contexts:

1) #selector
2) getting an unbound method
3) referring to static methods (including private ones)

A.


(Chris Lattner) #13

I agree with this, with the clarification that “Self” should be valid inside of structs and enums, where it is unambiguous what it refers to.

-Chris

···

On Apr 4, 2016, at 7:13 PM, Joe Groff via swift-evolution <swift-evolution@swift.org> wrote:

On Apr 4, 2016, at 11:17 AM, Erica Sadun <erica@ericasadun.com> wrote:

On Apr 4, 2016, at 12:13 PM, Joe Groff <jgroff@apple.com> wrote:

On Apr 4, 2016, at 11:00 AM, Erica Sadun via swift-evolution <swift-evolution@swift.org> wrote:

Are there reasons that prevent using `Self` as a synonym for an instance's type name?

Consider:

struct MyStruct {
  static func foo() { print("foo") }
  func bar() {
      MyStruct.foo() // works
      self.dynamicType.foo() // works
      Self.foo() // error
  }
}

Obviously, you can always name a type directly or use `self.dynamicType` but
neither solution does any favors for readability. Both approaches obscure intent,
especially as type names grow large: `MyExtremelyLargeTypeName.staticMember`,
for example. Plus, as Kevin B pointed out to me, `self.dynamicType.classMember`
and `TypeName.classMember` may not be synonyms in class types with non-final members.

I'd like to see `Self.staticMember` introduced as a synonym for `TypeName.staticMember`.

There's the wrinkle of inheritance, as there so often is. `Self` inside a class scope already means "the dynamic class of 'self'", not "the type this declaration statically appears within". Now, we really ought to allow you to utter Self in the bodies of class methods too. It would be consistent to extend that courtesy to value types, where dynamic `Self` always matches the static type, from that principle.

-Joe

Would using another word or symbol fix that problem?

My preference would be for there to be only one Self, and have it always be the dynamic type of 'self'. Some people disagree, but I don't think it's all that onerous to have to write ClassName.foo if that's really what you specifically mean.


(Joe Groff) #14

Would using another word or symbol fix that problem?

My preference would be for there to be only one Self, and have it always be the dynamic type of 'self'. Some people disagree, but I don't think it's all that onerous to have to write ClassName.foo if that's really what you specifically mean.

I would agree that Self should remain the dynamic version, but adding StaticSelf (however it is spelled) adds the safety of being able to refactor code w/o forgetting to rename an explicit class name. It adds the ability to more clearly express what you mean (“the containing class/struct, whatever it happens to be”), and it would reduce effort while reading code (in that you could see quickly that it was StaticSelf instead of having to look to see whether it was the same name as the enclosing type every time you read the code).

My support for StaticSelf isn’t at all about it being too hard to type ClassName.foo the first time, but about being able to read and maintain code after the fact.

I think you have a good point with your `#Self` idea—there's definitely an analogy there to other magic constants like #function.

And, of course, the argument that writing ClassName.foo isn’t onerous is dangerously close to an argument for dropping “.foo” with a type inferred by the call site... =)

-Joe

···

On Apr 5, 2016, at 7:34 AM, Timothy Wood via swift-evolution <swift-evolution@swift.org> wrote:

On Apr 4, 2016, at 7:13 PM, Joe Groff via swift-evolution <swift-evolution@swift.org> wrote:

From my own experience with C++11, if it weren't for code completion, having to utter 'EnumName::Case' over and over again when working with `enum class`es would drive me up the wall.


(Russ Bishop) #15

But if you don’t want subclasses to override it then why are you making it internal/public in the first place?

I’m not sure the only-classes case of exposing a class/static publicly but also not wanting subclasses to override it justifies a new language construct. Accessing these things via Self (aka self.dynamicType) seems good enough to me.

Russ

···

On Apr 5, 2016, at 7:34 AM, Timothy Wood via swift-evolution <swift-evolution@swift.org> wrote:

On Apr 4, 2016, at 7:13 PM, Joe Groff via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Would using another word or symbol fix that problem?

My preference would be for there to be only one Self, and have it always be the dynamic type of 'self'. Some people disagree, but I don't think it's all that onerous to have to write ClassName.foo if that's really what you specifically mean.

I would agree that Self should remain the dynamic version, but adding StaticSelf (however it is spelled) adds the safety of being able to refactor code w/o forgetting to rename an explicit class name. It adds the ability to more clearly express what you mean (“the containing class/struct, whatever it happens to be”), and it would reduce effort while reading code (in that you could see quickly that it was StaticSelf instead of having to look to see whether it was the same name as the enclosing type every time you read the code).


(Dave Abrahams) #16

It is not that it's “all that onerous,” but that I (at least) was driven
to the assumption based on the uses “Self” in the language that it would
naturally work in other contexts. As a user experience, it feels like a
violation when “Self” doesn't work where one would expect it to, and
that is compounded by the fact that the expected workaround

     private typealias _Self = NameOfTheTypeIAmDefining

doesn't work either because I can't use a private name in public APIs,
and

     public typealias Self_ = NameOfTheTypeIAmDefining

doesn't work because now I have to expose this extra name, “Self_,”
publicly. It's a frustration I've learned to live with, and others can
too, but it's really annoying. The annoyance doesn't go away easily,
either: I'm reminded of the frustration every time I have to work around
it. IMO we should try to reduce the number of these repeated points of
friction when we can.

···

on Sat Apr 09 2016, Chris Lattner <swift-evolution@swift.org> wrote:

On Apr 4, 2016, at 7:13 PM, Joe Groff via swift-evolution <swift-evolution@swift.org> wrote:

On Apr 4, 2016, at 11:17 AM, Erica Sadun <erica@ericasadun.com> wrote:

On Apr 4, 2016, at 12:13 PM, Joe Groff <jgroff@apple.com> wrote:

On Apr 4, 2016, at 11:00 AM, Erica Sadun via swift-evolution <swift-evolution@swift.org> wrote:

Are there reasons that prevent using `Self` as a synonym for an instance's type name?

Consider:

struct MyStruct {
  static func foo() { print("foo") }
  func bar() {
      MyStruct.foo() // works
      self.dynamicType.foo() // works
      Self.foo() // error
  }
}

Obviously, you can always name a type directly or use `self.dynamicType` but
neither solution does any favors for readability. Both approaches obscure intent,
especially as type names grow large: `MyExtremelyLargeTypeName.staticMember`,
for example. Plus, as Kevin B pointed out to me, `self.dynamicType.classMember`
and `TypeName.classMember` may not be synonyms in class types with non-final members.

I'd like to see `Self.staticMember` introduced as a synonym for `TypeName.staticMember`.

There's the wrinkle of inheritance, as there so often is. `Self`
inside a class scope already means "the dynamic class of 'self'",
not "the type this declaration statically appears within". Now, we
really ought to allow you to utter Self in the bodies of class
methods too. It would be consistent to extend that courtesy to
value types, where dynamic `Self` always matches the static type,
from that principle.

-Joe

Would using another word or symbol fix that problem?

My preference would be for there to be only one Self, and have it
always be the dynamic type of 'self'. Some people disagree, but I
don't think it's all that onerous to have to write ClassName.foo if
that's really what you specifically mean.

I agree with this, with the clarification that “Self” should be valid
inside of structs and enums, where it is unambiguous what it refers
to.

--
Dave


(Erica Sadun) #17

Would using another word or symbol fix that problem?

My preference would be for there to be only one Self, and have it always be the dynamic type of 'self'. Some people disagree, but I don't think it's all that onerous to have to write ClassName.foo if that's really what you specifically mean.

I would agree that Self should remain the dynamic version, but adding StaticSelf (however it is spelled) adds the safety of being able to refactor code w/o forgetting to rename an explicit class name. It adds the ability to more clearly express what you mean (“the containing class/struct, whatever it happens to be”), and it would reduce effort while reading code (in that you could see quickly that it was StaticSelf instead of having to look to see whether it was the same name as the enclosing type every time you read the code).

My support for StaticSelf isn’t at all about it being too hard to type ClassName.foo the first time, but about being able to read and maintain code after the fact.

I think you have a good point with your `#Self` idea—there's definitely an analogy there to other magic constants like #function.

This also falls nicely into my list of "debug literals we discussed on-list as wanting to see but did nothing about". (I would also like to see #function upgraded to use full gregorized naming with arguments. )

-- E

···

On Apr 5, 2016, at 10:06 AM, Joe Groff via swift-evolution <swift-evolution@swift.org> wrote:

On Apr 5, 2016, at 7:34 AM, Timothy Wood via swift-evolution <swift-evolution@swift.org> wrote:

On Apr 4, 2016, at 7:13 PM, Joe Groff via swift-evolution <swift-evolution@swift.org> wrote:

And, of course, the argument that writing ClassName.foo isn’t onerous is dangerously close to an argument for dropping “.foo” with a type inferred by the call site... =)

From my own experience with C++11, if it weren't for code completion, having to utter 'EnumName::Case' over and over again when working with `enum class`es would drive me up the wall.

-Joe
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution


(Austin Zheng) #18

I too would like a #Self. In my (subjective, biased) experience, sufficiently descriptive type names are usually long enough to make working with static members painfully onerous.

If there's still the risk of confusion (compile-time type versus runtime type), maybe #Self can be limited to instances where the type it references cannot change at runtime (e.g. a struct, enum, or final class). I don't know if this will actually be necessary, though - just throwing ideas out there.

Austin

···

On Apr 5, 2016, at 9:06 AM, Joe Groff via swift-evolution <swift-evolution@swift.org> wrote:

On Apr 5, 2016, at 7:34 AM, Timothy Wood via swift-evolution <swift-evolution@swift.org> wrote:

On Apr 4, 2016, at 7:13 PM, Joe Groff via swift-evolution <swift-evolution@swift.org> wrote:

Would using another word or symbol fix that problem?

My preference would be for there to be only one Self, and have it always be the dynamic type of 'self'. Some people disagree, but I don't think it's all that onerous to have to write ClassName.foo if that's really what you specifically mean.

I would agree that Self should remain the dynamic version, but adding StaticSelf (however it is spelled) adds the safety of being able to refactor code w/o forgetting to rename an explicit class name. It adds the ability to more clearly express what you mean (“the containing class/struct, whatever it happens to be”), and it would reduce effort while reading code (in that you could see quickly that it was StaticSelf instead of having to look to see whether it was the same name as the enclosing type every time you read the code).

My support for StaticSelf isn’t at all about it being too hard to type ClassName.foo the first time, but about being able to read and maintain code after the fact.

I think you have a good point with your `#Self` idea—there's definitely an analogy there to other magic constants like #function.

And, of course, the argument that writing ClassName.foo isn’t onerous is dangerously close to an argument for dropping “.foo” with a type inferred by the call site... =)

From my own experience with C++11, if it weren't for code completion, having to utter 'EnumName::Case' over and over again when working with `enum class`es would drive me up the wall.

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


(Timothy Wood) #19

I'm wan’t talking about overriding it… In my earlier posts I was talking about subclasses being able to call a utility function on their superclass and have a generic be expanded to the subclass type (whatever it is) by using `#Self`.

So, if the superclass `PropertyOwner ` has something like this (excusing typos since this code can’t be compiled right now, obviously =) ...

  static func property<Owner: PropertyOwner, ValueType>(ownerType: Owner.Type = #Self.self, name: String, value: ValueType)

then a subclass `Sub` could do:

  static let foozle = property(name: “foozle”, value: Int(3))

and end up with `foozle` being configured with ownerType = Sub.self. If later this property is moved to a different class, its ownerType would automatically change based on its new scope.

-tim

···

On Apr 5, 2016, at 11:41 AM, Russ Bishop <xenadu@gmail.com> wrote:

But if you don’t want subclasses to override it then why are you making it internal/public in the first place?


(Erica Sadun) #20

As the discussion seems to be quieting down, I've tried to summarize the on-list discussion and distill it into a preliminary proposal draft. Please let me know if this covers what you think it should or if I've entirely missed the mark. (It wouldn't be the first time.)

Regards, -- Erica

Adding a #Self literal to Swift

Proposal: SE-XXXX <https://gist.github.com/erica/5a26d523f3d6ffb74e34d179740596f7>
Author(s): Erica Sadun <http://github.com/erica>
Status: TBD
Review manager: TBD
<https://gist.github.com/erica/c60c7d51809889f3dfd47cdb482d6227#introduction>Introduction

This proposal introduces #Self, a new literal that expands to self.dynamicType.

This proposal was discussed on the Swift Evolution list in the [Pitch] Adding a Self type name shortcut for static member access <http://thread.gmane.org/gmane.comp.lang.swift.evolution/13708/focus=13712> thread.

<https://gist.github.com/erica/c60c7d51809889f3dfd47cdb482d6227#motivation>Motivation

It is common in Swift to reference an instance's type, whether for accessing a static member or passing a type for an unsafe bitcast, among other uses. At this time, you can either fully specify a type by name or use self.dynamicType to access an instance's dynamic runtime type as a value.

struct MyStruct {
    static func staticMethod() { ... }
    func instanceMethod() {
        MyStruct.staticMethod()
        self.dynamicType.staticMethod()
    }
}
As type names grow large, readability suffers, for example MyExtremelyLargeTypeName.staticMember
Code using hardwired type names is less portable than code that automatically knows its type.
Renaming a type means updating any TypeName references in code.
Using self.dynamicType fights against Swift's goals of concision and clarity; it is both noisy and esoteric.
self.dynamicType.classMember and TypeName.classMember may not be synonyms in class types with non-final members.
Joe Groff points out, Self inside a class scope already means "the dynamic class of 'self'", not "the type this declaration statically appears within...Swift ought to allow developers to utter Self in the bodies of class methods. It would be consistent to extend that courtesy to value types, where dynamic Self always matches the static type, from that principle"
<https://gist.github.com/erica/c60c7d51809889f3dfd47cdb482d6227#detail-design>Detail Design

In this proposal, #Self expands to the dynamic type of self and only the dynamic type of self. Joe Groff writes, "I don't think it's all that onerous to have to write ClassName.foo if that's really what you specifically mean."

<https://gist.github.com/erica/c60c7d51809889f3dfd47cdb482d6227#alternatives-considered>Alternatives Considered

Not at this time

<https://gist.github.com/erica/c60c7d51809889f3dfd47cdb482d6227#acknowlegements>Acknowlegements

Thanks Sean Heber, Kevin Ballard, Joe Groff, Timothy Wood, Brent Royal-Gordon, Andrey Tarantsov, Austin Zheng