✏️

関数で引数ではなくKeyPath式を渡せるようになった

2022/06/24に公開

今更ですが、昨日までこの書き方知らなかったのでまとめておきます。

KeyPath式を利用して、次のように記述することができます。

let fooShort = foo.map { $0.bar }

let fooKeyPath = foo.map(\.bar)

注意点としては、下記の記事に書かれていますが、利用できるのはKeyPath式であって、KeyPathのインスタンスでは行えないというあたりだと思います。どこかに定数としてKeyPathを置いておいて、引数として利用するような使い方はできないということですね。


Swift5.2から利用できるようになったそうです。

https://qiita.com/koher/items/50baade1eda4940c279c

一次資料
https://github.com/apple/swift-evolution/blob/master/proposals/0249-key-path-literal-function-expressions.md
(Githubだとこのように表示されるんですね、すごい。)

なんのためにKeyPath式を利用するのか?

まだまだなんもわからん状態だと、そもそもKeyPath式での記述をなぜするのかと考えてしまいます。この辺りはKeyPathに慣れている人からしたら、見やすくなった、わかりやすくなったと感じられるものであるのかもしれないので、"なんのために"は単に経験の差でしかないかもしれませんが

Mediumで参考になる記事があるので紹介します。

https://betterprogramming.pub/using-key-path-expressions-as-functions-in-swift-f0fe650ef7dc

The Evolution Proposal describes this as being able to use “\Root.value wherever functions of (Root) -> Value are allowed”. What this means is that if previously you sent a Car into a method and got back its model, you can now use Car.model instead.

引数をとって、プロパティの値を返すような関数であれば、\引数.値(プロパティ) で記述することができるといったことが書かれているのですが、ありがたいことに what this means とわかりやすくその意味について書かれています。この一文を簡単に訳してみます。

このように記述することができるようになったことで意味するのは、以前であればa Carをメソッドに渡して、そのプロパティの値であるits modelを返してもらっていたけれど、今ではそのように記述する代わりにCar.modelと記述することができる。

内部的にどのような処理が行われているのかはわかりませんが、クロージャでの処理が間に挟まれていない分、KeyPath式の方がより直感的かもしれません。結局のところ、このように書けることでのメリットは、コードをシンプルに手軽に書けるようになったということのようです。

所感

個人的には、学習者目線でのメリットとしては、KeyPathを利用するハードルが下がったことではないかなと思います。KeyPathはあえて利用しようとしないと、なかなか学習の機会が訪れない気がします。自分もほとんど利用したことがありませんでした。

配列関数を利用する機会は多いので、上記のような形でKeyPath式を積極的に利用できると記憶に定着しやすくなるし、慣れ親しみやすくなりそうな気がします。

参考

KeyPathについてまとめられた記事
https://dev.classmethod.jp/articles/swift_keypath1/

通常のKeyPathに関しては理解していなかったので、上記の記事が型に関して網羅的で勉強になりました。といって、AutoLayoutのあたりでの使い方が読んでもわからず...

Discussion