Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Range の「要約」に加筆修正 #2187

Merged
merged 2 commits into from
Mar 4, 2020
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 64 additions & 13 deletions refm/api/src/_builtin/Range
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,74 @@

include Enumerable

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

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

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

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

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

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

#@since 2.7.0
また、Ruby 2.7.0 では始端に nil を与えることで「始端を持たない範囲オブジェクト」
を作ることもできるようになりました(どちらも持たないものも作れます)。
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

「どちらも持たないもの」を作るには、少なくとも始端/終端のどちらかに明示的にnilを与えないと作れないことを明記するのはどうでしょうか?

p(..) # Syntax Error
p(...) # 2.7で導入されたメソッド引数のforwardとして解釈されてしまう
p(..nil) # ok
p(nil..) # ok
p(nil..nil) # ok

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

これ,実は迷った末に敢えて入れていなかったのですが,これらも入れて再修正しました。
加筆・修正をさらに進めています。

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

#@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