最近Rubyに入門していて、それまでよく使っていたGroovyと同じだったり違ったりしていろいろと新鮮です。その一環で、両者のRangeの違いをまとめてみます。
Groovyは2.4.3、Rubyは2.3.0で試しています。
GroovyとRubyのRange
作り方
末尾を含むやつ
range = 1..5
def range = 1..5
上記のコードはどちらも1から5までの範囲のRangeを生成します。
末尾を含まないやつ
終端に5を含まない場合は、
range = 1...5
def range = 1..<5
と書きます。Groovyの書き方は、他の言語とかとも比較するとちょっと特殊かな?という感じですが、5が含まれない感が強く出ていて、個人的には好きです。
アクセスの仕方
各々こんな感じ
range = (1..5)
range.first #=> 1
range.min #=> 1
range.last #=> 5
range.max #=> 5
range.size #=> 5
range.include? 1 #=> true
def range = (1..5)
range.getFrom() // => 1
range.first() // => 1
range.getTo() // => 5
range.last() // => 5
range.size() // => 5
range.contains(1) // => true
どちらもimmutable
どちらも、一度作ったRangeの中身を変更することはできません。
range.first = 1 #=> NoMethodError
(1..5).set(3, 100) // => java.lang.UnsupportedOperationException
Rubyの場合はそもそもセットする系のメソッドが用意されていないのに対して、Groovyはメソッドは用意されている(Listを継承しているから)のですが、実際に値を変えようとするとExceptionを投げるようになっています。
繰り返し処理
RubyのRange:Enumerableをincludeしている
GroovyのRange:Groovyはjava.lang.Object
にeachを追加している
結果として、どちらも繰り返し処理ができます。
(Enumerableがeachを実装していないってのが興味深かったけど、この記事のテーマとはずれるので略)
Rangeはどうやって隣の値を判別できるのか
「隣の値」を返すメソッドを呼んで、隣の値をたどっています。
次の値を呼び出す
Rubyの場合はsucc
もしくはnext
"a".succ #=> "b"
Groovyの場合は、next()
"a".next() // => "b"
前の値を呼び出す
Rubyの場合、標準APIには該当するものがない。
その理由は、prev
といった前に戻るものには曖昧さが伴うから、らしい。
参考:http://stackoverflow.com/questions/16716522/what-is-the-opposite-of-string-next
Groovyの方は、previous()
というメソッドを呼びます。
"b".previous() // => "a"
この帰結として、Groovyでは降順のRangeを作成することができます。
def range = (5..1) // => [5, 4, 3, 2, 1]
近場のRubyistに聞いたところ、「逆順にしたいことある? 逆順にしたいならreverseしたらよくない?」と言ってました。
ちなみにこのnextあたりの処理は掘ってくといろいろ違いがあって面白かったです。
独自のクラスのRangeをつくれるようにする
それぞれやり方は下記の通り。基本思想は同じですね。
Ruby: <=>を実装する(eachを実行するにはsuccの実装も必要)
Groovy: Comparable
を実装する(昇順のRangeにしたいときはnext()
を、降順のRangeにしたいときはprevious()
を実装する必要がある)
感想
基本思想はお互い近いなーという感じ、細かいところにいろんな違いがあって面白いですね。関連してGroovyのRangeの細かい部分もいろいろわかりました。
参考にしたもの
- http://qiita.com/abey1192/items/661766fb728fd9b872e2
- http://docs.groovy-lang.org/latest/html/api/groovy/lang/Range.html
- http://docs.ruby-lang.org/ja/2.3.0/class/Range.html
- http://waman.hatenablog.com/entry/20100226/1267145610
- http://mrhaki.blogspot.jp/2009/09/groovy-goodness-keep-your-values-in.html
- http://qiita.com/tbpgr/items/f901f44df6632939eb08