Groovy3 Tips エルビス代入演算子とは

まえがき

この記事では、Groovy3から新たに追加された演算子。
エルビス代入: Elvis assignment operator (?=) というものを簡単に紹介しようと思います。

Elvis assignment operator

エルビス代入演算子とは、
変数がnullまたは、false (式としてfalse判定)だったら、右辺の値を代入しますよ。
という挙動になります。

if文による、nullチェックや、三項演算子で書くよりも簡素に書けるショートハンドとなります。

また、Groovyでは元々、
エルビス演算子(?:)というものがありますが、今回お話するのはエルビス代入演算子(?=)です。

旧来の書き方

// if文を使った代入
if (i == null) {
    i = 100
}

// 三項演算子を使った代入
i = (i == null) ? 100 : i

// エルビス演算子を使った代入
i = i ?: 100

↑これらが、エルビス代入演算子を使うと、もっと簡素に書けるようになります。

// エルビス代入演算子を使った代入
i =? 100

より簡素になりました。

エルビス代入演算子の場合、
もし、変数が(null or false判定)じゃなかったなら、変数はそのままの値になります。

変数がfalse判定される時とは

エルビス代入演算子では、変数がnull、または式としてfalse判定される場合に、
代入されるので注意が必要です。
※変数がnullじゃなくても、false判定の場合には代入される。

例えば、下記条件であれば代入が発生します。

  • int, Integerでは、ゼロだった場合にも代入が発生します。
  • Stringは、空文字列("")の場合にも、代入が発生します。
  • リスト([])、マップ([:]) の場合もサイズがゼロの場合に代入が発生します。

Truth Rulesについては、こちらのドキュメントを参照

http://groovy-lang.org/semantics.html#Groovy-Truth
Groovy decides whether a expression is true or false by applying the rules ...

エルビス代入のコード例

下記に、Elvis assignment operator の例を記載します。

Integer i = null

// エルビス代入 (nullの場合、代入される)
i ?= 100         

assert 100 == i
Integer i = 0

// エルビス代入 (nullじゃないけど、false判定されるので代入される)
i ?= 100         

assert 100 == i
Integer i = 200

// エルビス代入 (nullじゃない、false判定されない場合は、そのままの値)
i ?= 100         

assert 200 == i

テストコード

いろんなパターンで動作確認してみましょう。
Spockによるテストコードを載せておきます。

for Integer

def "test elvis assignment for Integer"() {
    when:
    // エルビス代入
    i ?= 100

    then:
    ret == i

    where:
    ret || i
    100 || null // nullの場合は、代入される
    100 || 0    // ゼロの場合でも、代入される
    200 || 200  // 値が設定されてる場合は、元の値と同じ
}

for String

def "test elvis assignment for String"() {
    when:
    // エルビス代入
    s ?= "Hello"

    then:
    ret == s

    where:
    ret      || s
    "Hello"  || null     // nullの場合は、代入される
    "Hello"  || ""       // 空文字列は、false判定されるので代入される
    "Groovy" || "Groovy" // 値が設定されてる場合は、元の値と同じ
}

for List

def "test elvis assignment for List"() {
    when:
    // エルビス代入
    list ?= ["Hello"]

    then:
    ret == list

    where:
    ret        || list
    ["Hello"]  || null       // nullの場合は、代入される
    ["Hello"]  || []         // 空リストは、false判定されるので、代入される
    ["Groovy"] || ["Groovy"] // 値が設定されてる場合は、元の値と同じ
}

for Map

def "test elvis assignment for Map"() {
    when:
    // エルビス代入
    map ?= [message: "Hello"]

    then:
    ret == map

    where:
    ret                 || map
    [message: "Hello"]  || null                // nullの場合は、代入される
    [message: "Hello"]  || [:]                 // 空マップは、false判定されるので、代入される
    [message: "Groovy"] || [message: "Groovy"] // 値が設定されてる場合は、元の値と同じ
}

上記のコードはGroovy 3.0.5. で動作確認しています。

コメントを残す