こんにちは、Native チームの @geckour です。
今回は、Kotlin の便利な関数である scope functions の概要と、そのうまい使い所の話をします。
Scope functions
Kotlin の scope functions として紹介されているものはいくつかのタイプに分類することができます。
関数名 | 拡張関数である | コンテキストの参照方法 | 返却する値 |
---|---|---|---|
let |
◯ | it |
スコープで最後に評価した値 |
run |
× | - | スコープで最後に評価した値 |
with |
×: コンテキストを引数として指定する | this |
スコープで最後に評価した値 |
apply |
◯ | this |
コンテキスト |
also |
◯ | it |
コンテキスト |
use |
◯ | it |
スコープで最後に評価した値 |
そんな中で、同じような働きをする let
apply
also
の使い分けで悩んだことがある方も多いのではないでしょうか。
そこで、私達のチーム (僕) が辿った思考/志向の推移を紹介します。
パターン1: 返す値の特性で考える
少し話はそれますが、僕は .forEach {}
で済むところにわざわざ .map {}
を使うのは邪道である、という考えを持っています。
.map {}
は拡張元のリストをスコープ内で加工した値のリストに変換して返却しますが、その返却された値を使わないのであれば .forEach {}
を使えばいいし、不用意に .map {}
を使うと「ああこの値は後で使うんだな」というミスリーティングを招いたり、他人がそのコードをいじる際にバグを生みやすくなると考えているからです。
その考え方をもとに、 let
は加工した値を返すので、その値をスコープ外で必要としていない場合には使用を避けるべきでは?という考えに至りました。
つまり、基本的には apply
/ also
を使って、加工した値が必要なときだけ let
を使うという方針です。
よーし、これで心置きなく scope functions を使えるぞ、と思っていた矢先、公式ドキュメント に不穏な(?)記述を発見しました。
let
can be used to invoke one or more functions on results of call chains.
let
is often used for executing a code block only with non-null values. To perform actions on a non-null object, use the safe call operator?.
on it and calllet
with the actions in its lambda.
Another case for usinglet
is introducing local variables with a limited scope for improving code readability.
つまり、「一時的なスコープ作るのに便利だよ」と言っているくらいなので、値を返すかどうかなどどうでも良さげなスタンスだったのです。
では apply
の立場は…?と思い確認すると
Use
apply
for code blocks that don't return a value and mainly operate on the members of the receiver object. The common case forapply
is the object configuration. Such calls can be read as “apply the following assignments to the object.”
とあり、つまりは「その名の通りオブジェクトをいじるときに使えるぜ」ということらしいのです。
パターン2: メソッド名に従う
はて…ならば全てメソッド名が示すとおりに使い分ければいいのでは?と思い、最近はこのパターンを採用しています。
- Safe call operator (
?.
) を使うときはlet
- あるオブジェクトに対する処理をまとめたいときは
apply
- ネストが深くなって
this
が何なのかわかりづらくなるがスコープは作りたいときはlet
- ネストが深くなって
- あるオブジェクトを生成するついでに何かしたいときも
apply
のような感じです。
おや、 also
はどこに…?と気付いた方。ほぼ使わなくなりました。
終わりに
Kotlin は柔軟で自由である分、正攻法がわからず困ってしまう場面も多いと思います。
正解がわからずとも、これからもより良い方法を考えていく所存です。
皆さんのプラクティスもぜひ聞かせてください!
Quipper では一緒に働く仲間たちを募集しています。
是非お気軽にカジュアル面談にお越しください!