Is \MyType syntax taken, would it be a good synonym for…

I struggle whenever I read or have to write MyType.self. This means you’re referring to a type and not using it … there’s a more accurate description involving instance of meta types, I know, but thinking on those terms is even more of a stumbling block for me and I’m guessing many others.

What other syntax is used for referring to something vs using it? Keypaths. \MyType.foo refers to the foo field of MyType.

So it makes sense to me that referring to a type shouldn’t use the unique syntax MyType.self but maybe instead \MyType.

Is that syntax already used for something? I can’t remember as I rarely find myself using keypaths.

Posting here before I embarrass myself on Swift Aevolution ;^)

2 Likes

Surprise! Foo.self actually evaluates to Foo for any expression whatsoever, not just a type name. For example:

print(5.self)
1 Like

Which, incidentally, is kind of confusing for types that have an implicit self, like structs and classes. Not confusing in the sense of having ambiguous syntax technically, but logically so. Especially since there's Self which is the better analogy. So arguably it should be MyType.Self.

MyType.Self would be a type (as in, a thing you can put after a colon or as?), MyType.self is a value, the same way Objective-C had a -class method rather than a -Class method.

2 Likes

Whenever I feel confused when confronted with meta types, I get myself unconfused by reading @Douglas_Gregor's Swift for C++ Practitioners, Part 5: Type erasure & metatypes:

Metatypes

In the prior post on generics, I noted that Swift doesn't have an equivalent to the decltype type in C++. Swift does, however, have a function named type(of:), which produces the type of its argument. However, it's not producing a type, but a value representing the type, i.e., a metatype.

Metatypes in Swift are spelled with the .Type suffix, so if we have a type Point:

struct Point {
  var x: Double
  var y: Double
  
  static var origin: Point = Point(x: 0, y: 0)
}

The metatype of Point has the type Point.Type. One can form a value of this type with the expression Point.self.

let pointType: Point.Type = Point.self

What can you do with a metatype? For one thing, you can access static methods and properties, or call an initializer of that type to produce a new value, like this:

let point = pointType.init(x: 0.0, y: 0.0)
let origin = pointType.origin

Technically, when you write Point(x: 0.0, y: 0.0), you're using syntactic sugar for PointType.self.init(x: 0.0, y: 0.0).

2 Likes

I think MyType.self makes fair sense. To be more direct I’d treat the hardcoded type name as a reference to the thing itself…

let a = MyType

But we don’t have that. To refer to the type thing itself as a variable you need to use the self accessor...

let a = MyType.self

I can kinda see how this confuses with self on an instance, but they are representing similar things: give me a handle to yourself. It’s just that with a type name the self accessor is the only way to get a reference to that thing while with an instance it feels like there’s two because you’re usually inside self.

Not in and of itself, but nested types exist in Swift, and \MyType.NestedType would definitely be interpreted as a key path.

Or similarly, Type.self meaning "the type itself"

Thanks for taking this seriously all. Yeah, \Type is surely a bad idea.