SE-0252: Key Path Member Lookup

(Ted Kremenek) #1

The review of SE-0252: Key Path Member Lookup begins now and runs through April 5, 2019.

The proposal is written by @Douglas_Gregor and @xedin.

Reviews are an important part of the Swift evolution process. All review feedback should be either on this forum thread or, if you would like to keep your feedback private, directly to me as the review manager via email or direct message on the forums. If you send me email, please put "SE-0252" somewhere in the subject line.

What goes into a review of a proposal?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift.

When reviewing a proposal, here are some questions to consider:

  • What is your evaluation of the proposal?

  • Is the problem being addressed significant enough to warrant a change to Swift?

  • Does this proposal fit well with the feel and direction of Swift?

  • If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

  • How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

Thank you for contributing to Swift!

Ted Kremenek
Review Manager

Toolchains

There are toolchains available to try out this proposal:

12 Likes
(Xiaodi Wu) #2

I think this proposal is an appropriate and natural augmentation of the existing dynamic member lookup facilities offered by the language.

It fits well with the rest of the language in offering additional static checking where it makes sense to a feature that previously had less static checking available.

I recognize that there is some contention that the feature should be named distinctly on the basis of its offering more static checking, but as discussed in the pitch phase and stated by proposal authors, the concept of a “dynamic member” is unchanged here. Moreover, we (not just I, but others as well, with at least one recent example in the SIMD discussion) anticipate static validation of stringly typed dynamic member lookups will naturally become possible with the future addition of orthogonal “compiler-evaluable” features.

(The opposite opinion that @dynamicMemberLookup should never have any static checking is not viable given that, as it is already designed, such static checking will naturally become possible when it is composed with an orthogonal “compiler-evaluable” feature, and it would be inconsistent with the direction of Swift to hold that one must not add static checking where possible to improve the user experience.)

I participated in the pitch phase and have considered the proposed alternatives carefully.

5 Likes
(Chris Lattner) #3

This proposal (including all the details, naming etc) are great - I love to see the exciting combination of static type information with dynamic behavior. +1.

-Chris

4 Likes
(Michael Ilseman) #4

Another alternative would be to use a different attribute to separate this feature from @dynamicMemberLookup , e.g. @keyPathMemberLookup since string based design doesn't, at the moment, provide any static checking for member access. We recognize this as a valid concern, but at the same time consider both to be fundamentally the same feature with different amount of static checking.

Is it possible to declare a type to be keypath-member-lookupable but not string-member-lookupable?

(Xiaodi Wu) #5

Neither can be added retroactively by an external extension. By declaring only the one overload and not the other, what you mention is achieved.

4 Likes
(Michael Ilseman) #6

Nice, thanks for the clarification.

+1.

  • Is the problem being addressed significant enough to warrant a change to Swift?

This dramatically improves working with wrapper types that couldn't stomach string-based member lookup.

  • Does this proposal fit well with the feel and direction of Swift?

Yes, combining KeyPaths with dynamic member lookup

  • If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

N/A

  • How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

Quick reading

1 Like
(Nate Cook) #7

I'm a big fan of this proposal! Combining the dynamic lookup with type checking earns a big +1 from me.

I have hesitation about the parameter name of the subscript. I know I said the opposite in the pitch phase, but (actually I didn't like it then either) I would prefer this member to have a different name than the original customization point for @dynamicMemberLookup. It will be cumbersome to distinguish between the two while documenting the feature if they have the same name.

Since the subscript is only ever touched/used by the implementor, the name can be more descriptive of the feature itself than it could be if it were truly API meant to be used by a caller. I'm not attached to any particular name (the originally pitched subscript(keyPathMember:) seemed fine), just a different spelling, much like how the @dynamicCallable method names differ.

Second, I didn't follow up on this in the pitch thread, but the proposal should clarify one way or the other whether all key paths would be valid for lookup. Once a user understands the feature, it could be surprising that you can access lens.topLeft.y on a Lens<Rectangle>, but not lens[2].topLeft.y on a Lens<Array<Rectangle>>. Same question about tuple members in key paths — can I access lens.1.count on a Lens<(String, String)>?

2 Likes
(Pavel Yaskevich) #8

This is mentioned in the proposal that both "dot" and "subscript" syntax are going to be supported. so both examples you gave are valid and going to produce expected results unlike string based dynamic member lookup which only handles properties.

2 Likes
(Nate Cook) #9

I must have skimmed right over that line — thanks for pointing that out!

(Xiaodi Wu) #10

I certainly don’t think in principle that a distinguishing label would be out of the question, but my trouble with keyPathMember is that (1) it restates the type contrary to API design guidelines; (2) it omits “dynamic,” which could be misinterpreted as implying that it isn’t dynamic; (3) perhaps most problematic, the member isn’t a key path (i.e., the return value of the function), it’s the lookup that’s being done by key path.

In the absence of a label that addresses these three points, it’s fine (and indeed contemplated by API design guidelines that direct us to omit restating the type) to overload.

4 Likes
(Pavel Yaskevich) #11

Toolchains

Hello all, I've built a toolchain containing an implementation of this feature. You can grab the Ubuntu 16.04 toolchain or macOS toolchain.

(Pedro José Pereira Vieito) #12

+1

Yes, it seems an interesting extension of the @dynamicMemberLookup feature. And I believe the method should be named as stated in the proposal, overloading the current String-based subscript.

Yes!

N/A.

Read the pitch and the proposal.

(Jonathan Hise Kaldma) #13

+1. This is a natural extension of the existing @dynamicMemberLookup. I’ve run into the need for this feature when writing lens projections very similar to those described in the proposal.

Yes.

Yes. It combines two orthogonal features — key paths and dynamic member lookup — in a way that is elegant and intuitive. Very Swifty.

Read the proposal, participated in the pitch thread.

(Tanner) #14

+1

(Srđan Rašić) #15

+1

I've been following the pitch and I'm really looking forward to this. It seems like a small feature, but it will greatly improve ergonomics of the types that will implement it.

(Ahmad Alhashemi) #16

+1

Yes.

Yes. In fact, I'd say Swift is less Swift-y without it.

N/A.

Quick read.

(Caleb Kleveter) #17

Almost all in favor, but there was one point that stuck out to me:

It's probably just me, but I feel like this statements assumes we can get the name of a property from the keypath, which you can't at the moment. Such a feature would come in very handy in case like this Fluent ORM change.

Yes.

Yes.

N/A

Just read the whole proposal.

(Ted Kremenek) #18

Proposal Accepted

The review of this proposal has been unanimously positive. Leading up to the end of the review period the feedback tapered off, and the Core Team decided to move ahead and conclude the review a couple days early and accept the proposal.

The Core Team agrees with the discussion in the review that this proposal augments the existing dynamic member lookup facilities with additional static checking.

Thank you to everyone who participated in this review!

11 Likes
[Accepted] SE-0252: Key Path Member Lookup
(Dan Zheng) #19

Could someone please rapid-fire some key-path member lookup use cases, other than Lens?
I personally couldn't think of any, actually.


From discussion with @rxwei and @blangmuir: static code completion for key-path member lookup types may be possible: at lens.<TAB>, make code completion look through the members of T in subscript<U>(dynamicMember keyPath: WritableKeyPath<T, U>) -> Lens<U>. Generalize this idea for all subscript(dynamicMember keyPath: ...).

(Dan Zheng) #20

An aside: on the other hand, code completion for string-based @dynamicMemberLookup is a bit dead in the water. Example: you have no idea how to code complete a function argument of type PythonObject (based on local knowledge - of which there is zero).

Wah.