はじめに
こんにちは。株式会社ユーザベース Speeda事業でソフトウェアエンジニアをしている朝比奈です。 私は現在、データフィードチームに所属しており、主な言語としてGroovyを扱っています。その際にエルビス演算子を用いてプログラムを書き、個人的な学びがあったのでブログを執筆することにしました。
エルビス演算子とは
そもそもエルビス演算子ってなに?という方向けにエルビス演算子について軽く説明します。
エルビス演算子 a ?: b は、「左側の評価結果が『使える値』であればそのまま使い、そうでなければ右側の値にフォールバックする」ための演算子です。
下記はKotlinでの実装例です。 fugaが使える値であればhogeにはfugaが代入され、そうでない値であればhogeにpiyoが代入されるという挙動になります。
val hoge = fuga ?: piyo
余談ですが、エルビス演算子の名前の由来は、エルビス・プレスリーというアメリカ歌手から来てるらしいです。
三項演算子とエルビス演算子
エルビス演算子と似た演算子として三項演算子が挙げられると思います。
三項演算子についても説明をしておくと、三項演算子condition ? valueIfTrue : valueIfFalseは、「どの条件のときにどの値を返すか」を明示的に書くことのできる演算子です。
三項演算子は「条件」と「返す値」をそれぞれ自由に組み合わせることができますが、 エルビス演算子は「左側の値が使えるかどうか」という一種類の条件に特化している代わりに、より短く書ける点がメリットになります。
実装と挙動
ここからは、Kotlin と Groovy でエルビス演算子を使ったときの挙動を、いくつかの値パターンごとに比較してみます。 今回は、個人的に馴染みのあるKotlinとGroovyの2言語で挙動を比較したいと思います。 例として値が文字列の場合、nullの場合、0の場合の3種類で挙動を比較します。
また、Kotlinがローカル環境にインストールされている場合、kotlinc -XreplでREPLを起動することができます。
Groovyも同様にgroovyshでREPLを起動することができます。
文字列の場合
Kotlin
>>> val value = "taro" >>> val result = value ?: "unknown" >>> println(result) taro
Groovy
groovy> value = "taro" groovy> result = value ?: "unknown" groovy> println(result) taro
nullの場合
Kotlin
>>> val value = null >>> val result = value ?: "unknown" >>> println(result) unknown
Groovy
groovy> value = null groovy> result = value ?: "unknown" groovy> println(result) unknown
0の場合
Kotlin
>>> val value = 0 >>> val result = value ?: "unknown" >>> println(result) 0
Groovy
groovy> value = 0 groovy> result = value ?: "unknown" groovy> println(result) unknown
0の場合はKotlinとGroovyにおけるエルビス演算子で挙動が異なることがわかりました。 それぞれのエルビス演算子がどのような挙動をするのか知るために下記に公式ドキュメントを引用します。
Kotlin: Elvis operator
If the expression to the left of
?:is not null, the Elvis operator returns it. Otherwise, the Elvis operator returns the expression to the right. The expression on the right-hand side is evaluated only if the left-hand side is null.
Groovy: Elvis operator
The "Elvis operator" is a shortening of the ternary operator. One instance of where this is handy is for returning a 'sensible default' value if an expression resolves to false-ish(as in Groovy truth)
Kotlin におけるエルビス演算子は、左側の値が null の場合に右側へフォールバックします。一方、Groovy におけるエルビス演算子は、Groovy Truth において falsy とみなされる値をフォールバック対象として扱います。
先ほど、
エルビス演算子 a ?: b を「左側の評価結果が『使える値』であればそのまま使い、そうでなければ右側の値にフォールバックする演算子」と説明しました。
ここであえて「使える値」という少し曖昧な表現にしたのは、何をフォールバック対象とみなすかが言語によって異なるためです。
また、Groovyにおけるfalsyな値を代表的なものを挙げます。 The Groovy Truth
falseBoolean[]Collections[:]Maps''Strings0NumbersnullObject
したがって先ほど例示した0の場合は、Groovyにおけるfalsyな値であるため、右側でフォールバックされ、unknownを返す挙動となっていました。
まとめ
この記事で伝えたかったことは、エルビス演算子は言語によってフォールバックの条件が異なりうる、という点です。 今回取り上げた Kotlin と Groovy だけでなく、エルビス演算子を標準でサポートしている言語はいくつか存在します。
新しく触る言語でエルビス演算子を使う際は、公式ドキュメントに目を通して「どの値がフォールバック対象になるのか」を理解してから利用すると、安全で意図したコードを書きやすくなると思います。
🎓 学生の方へ | 1day インターンイベント開催!
Speeda ソフトウェアエンジニア職 のインターンイベントを開催します!
Speedaプロダクトチームではアジャイル開発手法の一種であるXP(エクストリームプログラミング)を実践しており、今回のインターンではプラクティスの中でも特徴的なペアプログラミングをみなさんに体験していただきます!
チーム開発を更に深めることができるペアプログラミングの経験は我々の文化を体験することや、今後のエンジニアとしての活動の幅を広げるきっかけになると思います。
少しでもご興味をお持ちいただけた方は、ぜひお気軽にエントリーください。