Skip to content

Commit

Permalink
Merge pull request #2187 from scivola/improve-Range-summary
Browse files Browse the repository at this point in the history
Range の「要約」に加筆修正
  • Loading branch information
pocke authored Mar 4, 2020
2 parents 11415e5 + 55e28e0 commit 15c6d6f
Showing 1 changed file with 86 additions and 13 deletions.
99 changes: 86 additions & 13 deletions refm/api/src/_builtin/Range
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,96 @@

include Enumerable

範囲オブジェクトのクラス。範囲オブジェクトは範囲演算子 .. または
... によって生成されます。.. 演算子によって生成された範囲
オブジェクトは終端を含み、... 演算子によって生成された範囲オブジェ
クトは終端を含みません。
範囲オブジェクトのクラス。
範囲オブジェクトは文字どおり何らかの意味での範囲を表します。数の範囲はもちろん、
日付の範囲や、「"a" から "z" まで」といった文字列の範囲を表すこともできます。

===
==== 作り方

for i in 1..5
# 処理
end
範囲オブジェクトは、[[m:Range#new]] を用いるほか、範囲演算子(`..' または `...')を
用いた [[ref:d:spec/operator#range]] で生成できます。
いずれの方法でも始端と終端を与えます。

#@samplecode 範囲オブジェクトの例
Range.new(1, 5) # 1 以上 5 以下
1..5 # 同上
1...5 # 1 以上 5 未満
#@end

この例で分かるように、範囲オブジェクトは終端を含む範囲も含まない範囲も表せます。

#@since 2.6.0
Ruby 2.6.0 からは、終端に nil を与えることで「終端を持たない範囲オブジェクト」
を作ることができるようになりました。

#@samplecode 終端を持たない範囲オブジェクト
p Range.new(1, nil) # 1 以上(上限無し)を表す
p(1..nil) # 同上
p(1..) # 同上(略した書き方)
#@end

#@since 2.7.0
また、Ruby 2.7.0 では始端に nil を与えることで「始端を持たない範囲オブジェクト」
を作ることもできるようになりました。

#@samplecode 始端を持たない範囲オブジェクト
p Range.new(nil, 5) # 5 以下(下限無し)を表す
p(nil..5) # 同上
p(..5) # 同上(略した書き方)
#@end

始端も終端も持たない範囲オブジェクトは「全範囲」を表します。

#@samplecode 始端も終端も持たない範囲オブジェクト
# 以下はすべて同じ範囲
p Range.new(nil, nil) # => nil..nil
p(nil..nil) # => nil..nil
p(..nil) # => nil..nil
p(nil..) # => nil..nil
#@end

範囲式で両端を略した書き方はできません。

p(..) # => SyntaxError
p(...) # Ruby 2.7 で導入されたメソッド引数の forward として解釈されてしまう

#@end
#@end

==== 機能

範囲オブジェクトは範囲を表しているので、基本的な機能として「ある値がその範囲に
含まれるか否かを判定する」ということがあります。

#@samplecode 値が範囲に含まれるかどうかを判定
p (1..5).cover?(6) # => false
p (1..5).cover?(5) # => true
p (1...5).cover?(5) # => false
#@end

[[m:Range#cover?]] メソッドでの判定には演算子 <=> が使われます。

当然、始端と終端は <=> メソッドで比較可能である(nil 以外を返す)必要が
あります。

範囲オブジェクトのもう一つの基本的機能は繰り返しの範囲を表すことです。

#@samplecode 繰り返しの範囲を範囲オブジェクトで表す
(3..5).each{ |i| p i }
# => 3
# 4
# 5

(3...5).each{ |i| p i }
# => 3
# 4
#@end

これは 1 から 5 までの範囲オブジェクトを生成して、それぞれの値に対して
繰り返すと言う意味です
繰り返しの範囲を表す範囲オブジェクトは、始端が「次の値」を返す succ メソッドを
持たなければなりません

範囲演算子のオペランドは互いに <=> で比較できる必要があります。
さらに [[m:Range#each]] を実行するためには succ メソッ
ドを実行できるものでなければいけません。
Range クラスには [[c:Enumerable]] が include してあるので,[[m:Range#each]] に
基づき、Enumerable モジュールが提供する多様なメソッドを使うことができます。

=== 破壊的な変更

Expand Down

0 comments on commit 15c6d6f

Please sign in to comment.