web-dev-qa-db-ja.com

ʻa?.let {} ?: run {} `はKotlinで慣用的ですか?

S.O.で次のコメントを見ました。投稿、そして私は興味をそそられます:

nullチェックにifを使用しないのはなぜですか? a?.let{} ?: run{}はまれな場合にのみ適切であり、それ以外の場合は慣用的ではありません– voddan 2016年5月15日7:29 kotlinでnullチェックを行う最良の方法は?

その構成が「まれな場合にのみ適切」であるのはなぜですか?
Kotlinの主任エンジニアは次のように述べています。

runを使用すると、エルビス演算子の右側で複数のステートメントを使用できます https://stackoverflow.com/a/51241983/6656019

私はそれが実際に慣用的なものとしてそれを支持していないことを認めますが。これらの投稿は両方とも、非常に尊敬されているS.O.からのもののようです。 Kotlinの寄稿者。
元のコメントに影響を与えた投稿では、letが変更可能である場合、式のa部分が重要であると述べています。その場合、a?.let{} ?: run{}の代わりにif{} else {}が必要になります。

「エルビスを走らせる」構造が好きだと思います。ほとんどの場合、それを避けるべきですか?
洞察に感謝します。

9
Andy Marchewka

その場合、if {} else {}の代わりに?.let {} ?: run {}が必要になります。

いいえ、run { statement }の実行部分を省略してa?.let{} ?: statementを使用できます。

ほとんどの場合、それを避けるべきですか?

必要なときに使用してください。例えば。そのシナリオで複数のステートメントを実行する場合。それはまれなシナリオであると指摘されています。多くの場合、エルビス演算子の右側に1つのステートメントしか表示されません。
そしてもちろん、必要のないときは使用しないでください。コードはシンプルにしてください。

6
Tim Castelijns

foo?.let { bar(it) } ?: baz()if (foo != null) bar(foo) else baz()と混同するのは危険です。

あなたが関数を持っているとしましょう:fun computeElements(): List<Int>? = emptyList()

このコードを検討してください:

_val maxElement = computeElements()?.let { it.max() } ?: return
println("Max element was $maxElement")
_

に比べ:

_val list: List<Int>? = computeElements()
val maxElement = if (list != null) list.max() else return
println("Max element was $maxElement")
_

これらは2つの同等の形式であると思われるかもしれません。ただし、両方を実行すると、前者はstdoutに何も出力しないことがわかります。

これは、it.max()が空のリストに対してnullを返すため(max要素がないため)、Elvis式の右辺が評価されるため、関数returns早い。

つまり、_?.let { ... } ?: ..._ "if-else"の両方のブランチを評価できますこれは危険です。このフォームが読めないことを除けば(_if-else_は広く理解されていますが、_let-run_は理解されていません)、微妙なバグが発生する可能性があります。

5
kevinmost