There two small gaps in key paths that'd be nice to fill in:
There's no way to form an identity key path today, short of writing a property definition. The identity keypath is useful to be able to pass to APIs that take a key path to describe what part of a value to manipulate in order to say "all of it", among other things. We have the magic .self member in every type, and we could conceivably spell the identity key path that way, as \.self. The identity keypath would be a WritableKeyPath<T, T>, and appending an identity key path would be an identity operation, so that (\.self).appending(x) == x and x.appending(\.self) == x.
Tuple elements should be allowed in key paths, either labeled or indexed, and form WritableKeyPath<(..., T, ...), T> values.
Of course, there are infinite other features that could be considered, but I'd like to focus on these two because they're small incremental features that fit easily into the current model. The identity key path also would need a small amount of runtime support to get the correct appending behavior that would be good to get into the runtime before it stabilizes. How does this sound?
+1 on both concepts, and the second one seems like obvious goodness. For the first one, I hope we can find a more clear way of expressing this. I get what you're going for with .self, but that is an ObjC thing, not a Swift thing.
Aside from the question wether that is a good idea or not, I'd prefer a solution that simply can't interfere with real properties.
Forbidding "self" as a member name would be one way around that issue, the other would be a string that can never be the name of a property. \. is probably the most obvious one (and if Swift would use slashes instead of points for path separation, Unix guys would feel home right away ;-)
The quoted identifier `self` is different from the keyword self, though. I agree that \.self is not the ideal syntax, especially because with an explicit root type it looks like \T.self, which is only one character away from a type value reference T.self. Ideally, if we ever get around to revisiting SE-90, we would be able to kill the .self member entirely. \. is cute but maybe a little mysterious. What about a static member of AnyKeyPath?
In a current discussion about single element tuples there was mention of this thread, and a suggestion to use \.0 as the identity keypath element, here.
This would effectively be coercing T to an unlabeled single element tuple (T) getting it's first element, and coercing back to T, except unlabeled single element tuples don't exist.
And even labeled single element tuples only exist in some parts of the compiler.
Personally, I think \. is short, sweet, and, erhm, to the point! More to the point, perhaps, it seems easy to come up with: it's the first thing I'd think of for how to spell the identity keypath, and I could remember it rather than having to google for how to spell it otherwise. When you first suggested this concept my first thought was "hmm, too bad it can't be spelled \. because that would be so obvious."
Agree, but it's worth considering. It is somewhat reminiscent of using . to refer to the current working directory. That analogy might be enough to help people remember what it means.
One theoretical downside to \., besides the cryptic nature, is it makes more partially-written code valid. Probably not a big deal in practice though, especially since keypaths are a somewhat niche feature at the moment.
FWIW, I ran into a use case yesterday where the identity key path is exactly what I need. I can work around not having it, but it would be much better if I didn't have to.
About small improvements to key paths, it would be nice to know if a key path is a property (like \Value.field) or a sub-property (like \Value.field.subField). And to be able to decompose a key path if it is a sub-property.
I needed that once, when I handled lazy-loading with key paths. To lazily load the sub-property of a value, you have to lazily load the property then the sub-property. So you need the decomposition of the key path.
I prefer a bare \ for the identity KeyPath. My rationale:
It feels like root, akin to the / directory
Unlike \., it obeys the rule that, textually, you append one KeyPath to another by adding a dot and the attribute name, e.g., the name of \.father is \.father.name. Accordingly, if you iteratively stripped away attributes in that KeyPath, you'd be left with \.father.name → \.father → \ .
Key path decomposition would be another thing that's straightforward to add to the current implementation, but I'd appreciate if we could discuss it as a separate topic.