implicit def を使って、Scala で null 結合演算子を実現してみた

Scala の implicit def を利用して、C# などにある null 結合演算子を実現してみました。null 結合演算子というのは、対象としている値が null だった場合に別の値を返す演算子です。*1

たとえば以下の C# コードでは、value3 の "foo" が表示されます。

string value1 = null;
string value2 = null;
string value3 = "foo";
string value4 = "bar";

Console.WriteLine(value1 ?? value2 ?? value3 ?? value4);


さて、この機能を implicit def を使用して Scala でも実現してみました。以下のコードになります。

object NullCoalescingOperator {
  implicit def anyRefToNullCoalescingOperator[T<:AnyRef](value: T) = new NullCoalescingOperator(value)
  class NullCoalescingOperator[T<:AnyRef](value: T) {
    def ??(default: =>T) = if (null != value) value else default
  }

  def main(args: Array[String]) = {
    val value1: String = null
    val value2: String = null
    val value3: String = "foo"
    val value4: String = "bar"

    println(value1 ?? value2 ?? value3 ?? value4)
  }
}

実行すると、ちゃんと "foo" が出力されました。
この null 結合演算子ですが && や || と同じように、値が確定したところで評価をやめます。なので、以下のコードを実行すると、"[expr value4]"は出力されません。

  def main(args: Array[String]) = {
    val value1: String = null
    val value2: String = null
    val value3: String = "foo"
    val value4: String = "bar"

    println({println("[expr value1]");value1} ??
            {println("[expr value2]");value2} ??
            {println("[expr value3]");value3} ??
            {println("[expr value4]");value4})
  }

実行結果は以下のとおり。


[expr value1]
[expr value2]
[expr value3]
foo

やはり、Scala は強力だなぁ・・・とおもった今日この頃。

補足

implicit def ですが、機能の名称としては implicit conversion ですね。ド忘れしてました(汗

*1:Oracle なんかでも nvl 関数として存在している機能です。