SE-0249: Key Path Expressions as Functions

Hi Swift Community,

The review of SE-0249: Key Path Expressions as Functions begins now and runs through March 27, 2019.

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-0249" 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!

Ben Cohen
Review Manager

31 Likes

This is a great proposal! A very welcome addition to the language in my book.

This is something I've been hoping to see for some time. Great to see progress being made in this space.

  • What is your evaluation of the proposal?

+1. This is a small but important improvement in the expressiveness of key path literals and APIs that take function arguments. I am also a strong proponent of the future direction of making key paths callable.

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

Yes. It is often desirable for APIs accepting a function to also support key paths. Without this change overloads or custom operators are necessary to do that.

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

Yes. As a convenience feature it is very much inline with other convenience features Swift offers.

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

N/A

+1.

This feels extremely natural for key paths. I'm not overly concerned about not accepting KeyPaths either. Most of the time I've used key paths in this manner it has been cases where the path is statically known.

  • What is your evaluation of the proposal?

I love it, and I’ve been making similar functionality by adding overloads for map and filter on various types. It will be so great to have this ‘for free’.

  • Is the problem being addressed significant enough to warrant a change to Swift?
    Yes, the change seems small compared to the great benefit it will provide.

  • Does this proposal fit well with the feel and direction of Swift?
    Very much so. I feel that the code it enables is elegant and readable and thus very ‘swifty’. :slight_smile:

  • 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?
    Followed the pitch discussions and have used a primitive home baked solution for similar effects. And have reloaded the forums frequently since yesterday to see when the proposal review finally began! :slight_smile:

  • What is your evaluation of the proposal?

A strong +1. Stephen and I have two functions we use to achieve this without compiler support: ^ for those that don't mind operators (e.g. users.map(^\.name)) and get for those that are operator-phobic (e.g. users.map(get(\.name))). We have hundreds of uses of these functions across multiple code bases, and we haven't experienced any problems with it.

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

Yes. It seems to be a style of coding that naturally comes up when writing Swift. I've repeatedly seen a budding Swift developer come to the realization that they should be able to do something like array.map(\.field). They usually end up defining overloads that take key paths, or they just don't use this style of coding at all. Having language support for this style means that everyone can easily take part.

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

Yes, just as people find it nice to be able to do things like xs.reduce(0, +), it is just as nice to do things like users.map(\.name).

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

Ruby has a similar syntax for invoking methods, for example:

[1, 2, 3, 4].map { |x| x.to_s }

# versus

[1, 2, 3, 4].map(&:to_s)

Under the hood &: is serving the same purpose that \. does in Swift.

I've worked on a number of large ruby codebases, and most contributors aspired to writing their map's, select's and reduce's in the &: style when possible since it helped clear a lot of syntactic noise around data pipelines.

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

An in-depth study.

7 Likes

:heart: I fondly remember the introduction of the Ruby & "to_proc" operator: players.map(&:name). This kind of niceties are what make a great language. Thanks @stephencelis and @gregtitus for this!

5 Likes

This seems unequivocally better than the world we have today. Enthusiastic +1!

1 Like

+1!

All the reasons that have been stated here so far. Additionally, I think this change will raise awareness of and advocate for the power of key paths in general, which would be very welcome.

(For such a powerful, elegant feature, I feel like key paths are under-utilized and not widely understood by the average Swift programmer. It will be excellent to have a feature that shows off what they can do.)

1 Like

+1

Extremely useful, I've been using the ^\.property version for some time but allowing the KeyPath to automatically lift itself seems to be very natural to Swift.

2 Likes

Simple +1 here. I was wary of 'subtyping' keypath->closure proposals before but the literal approach seems much more bounded whilst retaining 90% of the convenience.

1 Like

Lovely and elegant. +1. Nicely in line with general Swift direction. The literal requirement I think is perfectly fine.

1 Like
  • What is your evaluation of the proposal?
    +1
  • Is the problem being addressed significant enough to warrant a change to Swift?
    yes
  • Does this proposal fit well with the feel and direction of Swift?
    Yes
  • If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
    This holds up and seems as powerful/convenient.
  • How much effort did you put into your review? A glance, a quick reading, or an in-depth study? read the proposal.

+1

Nice addition to the language.

  • What is your evaluation of the proposal?
    +1

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

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

  • If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
    I've used custom operators like ^ to implement this functionality. That always generates team debate about the introduction of operators. Also used functions instead of operators. Much prefer the native support for this behavior as described in the proposal.

  • How much effort did you put into your review? A glance, a quick reading, or an in-depth study?
    Read the proposal. Have some experience with alternate solutions.

2 Likes
  • What is your evaluation of the proposal?
    +1! It's a nice to have thing that warms my heart. I hate typing $0, it's such an awkward key combination
  • Is the problem being addressed significant enough to warrant a change to Swift?
    While the world would be okay without this feature, I think it's still worth adding.
  • Does this proposal fit well with the feel and direction of Swift?
    Yep! I feel like swift is all about reusing literals for many similar things, and while this isn't ExpressibleByKeyPathLiteral it feels like it.
  • 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?
    I've read the pitch thread and the proposal

+1, enables a nicer and more clear way to express higher order computation across data structures.

My only concern is whether this will cause compile time issues in the type checker due to the addition of new implicit conversions. I think the risk of this in practice is low though, because it only affects expressions that have keypath literals in them, which are comparatively rare.

Unclear to me, I'm neutral on this. This is literally saving one character (assuming the use of a ^ operator like in the alternatives section), so it is hard to argue that this is critical. That said, we don't have that operator standardized.

Yes.

No, n/a

I read the proposal in detail, but haven't followed the other discussions closely.

-Chris

1 Like
  • What is your evaluation of the proposal?
    +1 This something we need, especially if Type.mutatingMethod is never going to be made to return an (inout Type, Arguments...) -> Result function.
  • Is the problem being addressed significant enough to warrant a change to Swift?
    Yes.
  • Does this proposal fit well with the feel and direction of Swift?
    Yes.
  • 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?
    I read the proposal, and have been following previous discussion of the issue since it was first brought up as an alternative to implementing SE-402.
  • What is your evaluation of the proposal?
    I think this would cause confusion unless it also address tuples. If that is the case then that should cut the surface area of tuples which can help us get closer a 0110 being implemented.
    https://github.com/apple/swift-evolution/blob/master/proposals/0110-distingish-single-tuple-arg.md

  • Is the problem being addressed significant enough to warrant a change to Swift?
    Not by itself I am afraid. If I am able to use KeyPath notation in this way I would be confused by it as new user.

Look at the reasoning for reverting 0110 it was mostly due to closures which this proposal should address.

https://lists.swift.org/pipermail/swift-evolution-announce/2017-June/000386.html

Edit:

  let pairs = [(1, "A"), (2, "B")]
  print(pairs.map { $0.0 })

I am saying that this is a great feature but it needs to include tupples KeyPath otherwise it will cause confusion.

Can you explain what you mean by this? Key path literals, as converted in this proposal, are one-argument functions, so I'm not sure how SE-0110 applies.