Swift delight: implicit member syntax— Jordan Rose (@UINT_MIN) December 10, 2021
This 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.
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 (
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.
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?