[swift-evolution] [Pitch or bug?] Expanding the capability of `.` prefixed lookup
Matt Gallagher
mattxg at gmail.com
Thu Jun 29 07:19:39 CDT 2017
Super short summary:
I think a function argument or right-hand-side expression prefixed with `.` should allow access to *any* static member on the expected type, dropping the existing limitations of this syntax.
Detail:
At the moment in Swift, you can use a `.` (period or dot) prefix to perform a scoped lookup of static vars and funcs on the expected type, if those static vars or funcs return that type.
For example:
// If we have a type `SomeNontrivialTypeName`
struct SomeNontrivialTypeName {
// With a static function returning `SomeNontrivialTypeName`
static func a() -> SomeNontrivialTypeName
}
// And a function that requires a `SomeNontrivialTypeName` parameter
func f(a: SomeNontrivialTypeName)
// We can call the function like this:
f(a: .a())
The `.` prefix allows us to omit the typename `SomeNontrivialTypeName`; since the parameter already expects `SomeNontrivialTypeName`, the `.` already implies lookup in the list of static func/vars for `SomeNontrivialTypeName`.
The purpose is syntactic efficiency and it's used to great extent across a wide range of Swift/AppKit/Foundation interfaces for enum-like value lookups. It lets us have very simple names that won't clash with names in the global namespace because they're not in the global namespace – and yet, they're only a single `.` more syntactic overhead.
Unfortunately, there is no extendability. This approach will look up only static vars or funcs that immediately return the expected type and you can't transform the result – it's one function and done. For example, if `SomeNontrivialTypeName` has a fluent-style interface (i.e. an interface where instance methods return mutated `self` or new instances of `SomeNontrivialTypeName`):
extension SomeNontrivialTypeName {
func addThings() -> SomeNontrivialTypeName
}
trying to append this function won't work, even though the return type remains correct:
f(a: .a().addThings())
This fails and claims that we've forgotten to provide a parameter (!).
A completely different kind of transformation might go via a different type
extension SomeNontrivialTypeName {
static func another() -> AnotherType
}
struct AnotherType {
func back() -> SomeNontrivialTypeName
}
It would be nice to be able to use this "there-and-back-again" transformation:
f(a: .another().back())
But it also won't work.
I realize that this is a point about minor syntactic efficiency. Yes, you could simply write:
f(a: SomeNontrivialTypeName.another().back())
but it's clunky and the type name gets in the way.
There's also an element of consistency. Swift already lets us look up static functions in this way – but:
* only functions that return the expected type
* and we can't *use* the function result ourselves, it must be immediately yielded to the parameter or left-hand-side
Seems more than a little strange.
Anyone else care or have thoughts on this point?
Regards,
Matt Gallagher.
More information about the swift-evolution
mailing list