little self, Big Self

⇐ Notes archive

(This is an entry in my technical notebook. There will likely be typos, mistakes, or wider logical leaps — the intent here is to “let others look over my shoulder while I figure things out.”)

Yesterday I learned — let’s pretend “YIL” is a thing — Swift’s postfix self (i.e. .self) can be used after any expression (not just types). It’s a lesser-known arcanum in the language.

1.self // ⇒ evaluates to 1.
"ayy lmao".self // ⇒ evaluates to "ayy lmao".
"ayy lmao".self.count // ⇒ evaluates to 8.
"ayy lmao".self.count.self % 2 // ⇒ evaluates to 0.

Unlike TypeName.self metatype expressions, SomeExpression.self postfix self expressions evaluate to the value of the expression. Which adds color to the decision behind \.self as the identity key path — it’s a sort of postfix self as a key path. QuinceyMorris noted in a Swift Forum’s thread that this precedent comes from the Objective-C days,

For historical, Objective-C* reasons, you can add .self to pretty much any expression and the resulting value is that same expression’s value.


*In Objective-C, [key-value coding (KVC)] always requires an object and a non-empty key-path to access a value. To reference the object itself, you don’t have a key-path, so NSObject defined a self method, which works as key-path “self” in KVC. It works like this in Swift, too:

let myself = self[keyPath: \.self]

To make things doubly esoteric, I might’ve had too much cold brew one morning when I realized Self.self is a valid expression and can be used to back Identifiable conformances for one-off alerts or sheets in SwiftUI.

(Gist permalink.)

Self.self allows id to follow suit with the type’s name, if it’s ever refactored down the line.

For more on Swift’s other selfs, Jesse Squires has you covered in a recent blog post.