Swift Delight: Implicit Member Syntax

Part of the Swift Regrets series.

Swift’s implicit member syntax was of course added for enums. In C an enum’s cases are in the top-level namespace, because C has no (arbitrary) nested namespaces. That leads to names like StringEncodingUTF16, because plain UTF16 might collide with something else. In Rust, and C++ enum class, names are nested under a namespace: StringEncoding::UTF16. Much tidier, but makes your switches pretty verbose! So both Rust and C++20 allow you to selectively lift enum cases up to the current scope (use / using enum). Java puts its own spin on this: if you switch over an enum, you can list the cases unadorned, case UTF16, while still using StringEncoding.UTF16 elsewhere. This is a nice, practical compromise, especially for a language with (mostly) classic bottom-up type-checking.

But Swift goes further. Swift type-checks an entire statement at once, and allows types to be inferred based on how values are used. And so Swift can provide a general syntax for anywhere you expect a StringEncoding: .utf16. (Also Swift prefers lowerCamelCase for case names.)

I think this works as well as it does because of argument labels; consider String(data: contents, encoding: .utf16). Even without the labels .utf16 would probably be clear in context, but with them there’s definitely no need to write “StringEncoding”. But I see people talking about this as “enum syntax”, and it’s not just for enums. Any type-level property will work too:

view.edgeInsets = .zero
UIGradient(starting: .black, ending: .white)
let tau = 2.0 * .pi

…as will any type-level method that returns Self, though that doesn’t come up as much as enums with payloads. Oh, and also initializers (as .init()), though that one hasn’t really caught on. At that point it’s not necessarily saving anything over writing the type name.

In SE-0287 @jumhyn bumped this up further by allowing chains, which is good for builder-style idioms:

view.backgroundColor = .white.withAlphaComponent(0.2)

But even if it were just enum cases and static constants I’d love it still. I really think this is the right way to do enums / algebraic data types in a language with namespaces and type inference.

P.S. Rust folks?