uehaj's blog

Grな日々 - GroovyとかGrailsとかElmとかRustとかHaskellとかReactとかFregeとかJavaとか -

Groovyの奇妙な演算子(その2)

お待ちかね?「Groovyの奇妙な演算子」第二回は、

   <=>       ..        ..<       ...     *      *:

の6つについてです(予告とはちょっと違います)。

「<=>」大小比較演算子

両辺に与えた2つの数値の大小比較を行い、その結果を返します。
a<=>bの結果は

  • 1(a>b)
  • 0(a==b)
  • -1(a

のいずれかとなります。
明示的に呼び出して使うより、java.util.Comparable#compareTo()を実装するなどに使うのが主になると思われます。

「..<」半開区間をあらわす範囲オブジェクト(groovy.lang.IntRangeなど)を生成します。

「..<」は、「Javaにない演算子」ではありますが、意味はある程度自明で、つまりa,bが整数値のとき、「a ..< b」は、「new IntRange(a,b)」と等価です。
IntRangeはgroovyで定義された、整数の半開区間を表すクラスです。a ..< bは半開区間[a,b)を表します。

【用途】

IntRangeはItarableを実装しているので、拡張for文などでループ範囲の指定に使えます。

groovy> for (i in 1..<5) {
groovy>   println i
groovy> }
groovy> go
1
2
3
4

次に、IntRangeのeachメソッドを、クロージャを引数に渡して呼び出してみます。
こちらのほうがよりGroovyらしいですね。

groovy> (1..<5).each{
groovy>   println it
groovy> }
groovy> go
1
2
3
4

「..<」は、上でわかるように、「終端を含まない」範囲を指定します。

【覚え方】

覚え方としては、●−−−○という数直線の表現を連想するとか。
あるいは、<は「より小さい」だから、末端を含まないもの、とか。

「..」は、「終端を含む」範囲を指定します。

【用途】

やはり以下のようにループの繰り返し回数指定に用いることができます。

groovy> for (i in 1..5) {
groovy>  println i
groovy> }
groovy> go
1
2
3
4
5
groovy> (1..5).each{
groovy>   println it
groovy> }
groovy> go
1
2
3
4
5

「..」は「..<」と同様にIntRangeを返すのですが、IntRangeのコンストラクタは「終端を含まない」範囲を指定して呼び出す必要があるので、a..bと等価なコードは以下のようになります。

  • new groovy.lang.IntRange(a, b.next()) (b>a)
  • new groovy.lang.IntRange(a, b.previous())(b
  • new groovy.lang.EmptyRange() (b==a)

ちょっとややこしいですかね。まあおそらくあんまり気にする必要はないでしょう。

「...」(Java5と同様に)可変個数引数をあらわす指定

の様である。しかし、使えるが微妙にJava5とは異なる意味となる(バグ?)。もともと、Groovyでは、配列を引数とすることで、可変個数引数を使えるので、「...」を使う必要がない、はず。ちなみに「演算子」ではありませんね。

【Classicな人への注記】

「...」は昔「..<」に相当する半開区間を表す演算子でしたが、Java5の可変引数の指定とぶつかるためか、あるいは、覚えにくいせいか、..<になりましたので、今後は使わないように。

「*」リスト展開演算子(SPREAD LIST OPERATOR)。

リストの初期化で使用可能。
[1, *[2, 3], 4] は [1, 2, 3, 4]と等価。

「*:」マップ展開演算子(SPREAD MAP OPERATOR)。

マップの初期化で使用可能。

            m = ['a':11, 'aa':22, 'aaa':33]
            z = ['c':100, *:m]

は、

            z = ['c':100, 'a':11, 'aa':22, 'aaa':33]

と等価。Beanの初期化時にも使えます。
リストもそうですが、明示的に展開しないと展開されないというわけです。

次回予告

以下についてのその3に続く(たぶん)。

    =~      ==~     **      **=   ===
広告を非表示にする