range_extd 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ddcd6d0416bca878881275877c7b388867fbd51d
4
+ data.tar.gz: 68631346bbd9735b6362e179294b854429a36d47
5
+ SHA512:
6
+ metadata.gz: 0b0b845ea47998f05ffdbcbf4adddafd129ba25418df63fdaaefb21748aa84d9a133618e880edd2009701141a9e1209ca6b67194f57b4c07da2fde4cc1a2c7b3
7
+ data.tar.gz: cfccffebf7081da3260b93f939a25e7c4f0c7374437a1a264786b727b5bfa7a362b41285d94bc04e868ef36eb44c264a4187351c08d08144011cae5f0b727887
@@ -0,0 +1,14 @@
1
+ -----
2
+ (Version: 0.1.0)
3
+ 2014-04-27 Masa Saskano
4
+ * Fix range_extd.gemspec
5
+
6
+ -----
7
+ 2014-04-27 Masa Sakano
8
+
9
+ * Initial commit of doc modification.
10
+
11
+ -----
12
+ 2014-04-27 Masa Sakano
13
+
14
+ * Initial commit of range_extd.
@@ -0,0 +1,317 @@
1
+
2
+ = RangeExtd - Extended Range class with exclude_begin and open-ends
3
+
4
+ This package contains RangeExtd class, the Extended Range class that features:
5
+
6
+ 1. includes exclude_begin? (to exclude the "begin" boundary),
7
+ 2. allows open-ended range (to the infinity),
8
+ 3. defines NONE and EVERYTHING constants,
9
+ 4. the first self-consistent logical structure,
10
+ 5. complete backward-compatibility within the built-in Range.
11
+
12
+ With the introduction of the excluded status of begin, in addition
13
+ to the end as in built-in Range, and open-ended feature,
14
+ the logical completeness of the 1-dimensional range is realised.
15
+
16
+ Then the validity of range is strictly defined now.
17
+ Following that, this package adds a few methods, most notably
18
+ {Range#valid?} and {Range#empty?}
19
+ to Range, and accordingly its any sub-classes,
20
+
21
+ For example, <tt>(3...3).valid?</tt> returns false, because the element 3 is
22
+ inclusive for the begin boundary, yet exclusive for the end boundary,
23
+ which are contradictory to each other. With this RangeExtd class,
24
+ it is expressed as a valid range,
25
+ * RangeExtd.new(3, 3, true, true) # => an empty range
26
+ * RangeExtd.new(3, 3, false, false) # => a single-point range (3..3)
27
+
28
+ However, as long as it is within built-in Range, nothing has changed,
29
+ so it is completely compatible with the standard Ruby.
30
+
31
+ To express open-ended ranges is simple; you just use either of
32
+ the two (negative and positive, or former and later) constants
33
+ defined in the class {RangeExtd::Infinity}
34
+ * RangeExtd::Infinity::NEGATIVE
35
+ * RangeExtd::Infinity::POSITIVE
36
+
37
+ They are basically the object that generalised <tt>Float::INFINITY</tt> to
38
+ any Comparable object. For example,
39
+ ("a"..RangeExtd::Infinity::POSITIVE).each
40
+ gives an infinite iterator with <tt>String#succ</tt>, starting from "a"
41
+ (therefore, make sure to code so it breaks the iterator at one stage!).
42
+
43
+
44
+ The built-in Range class is very useful, and has given Ruby users
45
+ a power to make easy coding. Yet, the lack of definition of
46
+ exclusive begin boundary is a nuisance in some cases.
47
+
48
+ Having said that, there is a definite and understandable reason;
49
+ Range in Ruby is not limited at all to Numeric (or strictly speaking,
50
+ Real number or its representative). Range with any object that has a method
51
+ of <tt>succ()</tt> is found to be useful, whereas there is no reverse method for
52
+ <tt>succ()</tt> in general.
53
+ In that sense Range is inherently not symmetric. In addition
54
+ some regular Range objects are continuous (like Float), while others are discrete
55
+ (like Integer or String). That may add some confusion to the strict definition.
56
+
57
+ To add the feature of the exclusive begin boundary is in that sense
58
+ not 100 per cent trivial. The definition I adopt for the behaviour of
59
+ RangeExtd is probably not the only solution. Personally, I am content
60
+ with it, and I think it achieves the good logical completeness within the frame.
61
+
62
+ I hope you find it to be useful.
63
+
64
+
65
+ == Install
66
+
67
+ gem install range_extd
68
+
69
+ Two files
70
+ range_extd/range_extd.rb
71
+ range_extd/infinity/infinity.rb
72
+ should be installed in one of your <tt>$LOAD_PATH</tt>
73
+
74
+ Alternatively get it from
75
+ http://rubygems.org/gems/range_extd
76
+
77
+ Then all you need to do is
78
+ require 'range_extd/range_extd'
79
+ or, possibly as follows, if you manually install it
80
+ require 'range_extd'
81
+ in your Ruby script (or irb). The other file
82
+ range_extd/infinity/infinity.rb
83
+ is called (required) from it automatically.
84
+
85
+ Have fun!
86
+
87
+
88
+ == Simple Examples
89
+
90
+ === How to create a RangeExtd instance
91
+
92
+ Here are some simple examples.
93
+
94
+ r = RangeExtd(?a...?d, true) # => a<...d
95
+ r.exclude_begin? # => true
96
+ r.to_a # => ["b", "c"]
97
+ RangeExtd(1...2) == (1...2) # => true
98
+ RangeExtd(1, 2, false, true)== (1...2) # => true
99
+ RangeExtd(1, 1, false, false)==(1..1) # => true
100
+ RangeExtd(1, 1, true, true) == RangeExtd::NONE # => true
101
+ RangeExtd(1, 1, false, true) # => ArgumentError
102
+ (RangeExtd::Infinity::NEGATIVE..RangeExtd::Infinity::POSITIVE) \
103
+ == RangeExtd::EVERYTHING # => true
104
+
105
+ Basically, there are two forms:
106
+
107
+ RangeExtd(range, [exclude_begin=false, [exclude_end=false]])
108
+ RangeExtd(obj_begin, obj_end, [exclude_begin=false, [exclude_end=false]])
109
+
110
+ The last two parameters specify the respective boundary to be excluded if true,
111
+ or included if false (Default). If they contradict to the first
112
+ parameter of the range (Range or RangeExtd), those latter two parameters are used.
113
+ <tt>RangeExtd.new()</tt> is the same thing.
114
+
115
+ === Slightly more advanced uses
116
+
117
+ (1..RangeExtd::Infinity::POSITIVE).each do |i|
118
+ print i
119
+ break if i >= 9
120
+ end # => self ( "123456789" => STDOUT )
121
+ (nil..nil).valid? # => false
122
+ (1...1).valid? # => false
123
+ (1...1).null? # => true
124
+ RangeExtd.valid?(1...1) # => false
125
+ RangeExtd(1, 1, true, true).valid? # => true
126
+ RangeExtd(1, 1, true, true).empty? # => true
127
+ RangeExtd(?a, ?b, true, true).to_a? # => []
128
+ RangeExtd(?a, ?b, true, true).empty? # => true
129
+ RangeExtd(?a, ?e, true, true).to_a? # => ["b", "c", "d"]
130
+ RangeExtd(?a, ?e, true, true).empty? # => false
131
+ RangeExtd::NONE.is_none? # => true
132
+ RangeExtd::EVERYTHING.is_everything? # => true
133
+
134
+ All the methods that are in the built-in Range can be used.
135
+
136
+
137
+ == Description
138
+
139
+ Once the file range_extd.rb is required, the two classes are defined:
140
+
141
+ * RangeExtd
142
+ * RangeExtd::Infinity
143
+
144
+ Also, several methods are added or altered in Range class.
145
+ All the changes made in Range are backward-compatible with the original.
146
+
147
+ === RangeExtd::Infinity Class
148
+
149
+ Class {RangeExtd::Infinity} has basically only two constant instances.
150
+
151
+ * RangeExtd::Infinity::NEGATIVE
152
+ * RangeExtd::Infinity::POSITIVE
153
+
154
+ They are the objects that generalise the concept of
155
+ <tt>Float::INFINITY</tt>
156
+ to any Comparable objects. The methods <tt><=></tt> and <tt>succ</tt> are defined.
157
+
158
+ You can use them the same as other objects, such as,
159
+ ("k"..RangeExtd::Infinity::POSITIVE)
160
+ However as they do not have any other methods,
161
+ the use out of Range-type class is probably meaningless.
162
+
163
+ Note for any Numeric object, please use <tt>Float::INFINITY</tt> instead in principle.
164
+
165
+ Any objects in any user-defined Comparable class are commutatively comparable with
166
+ those two constants, as long as the cmp method of the class is written
167
+ politely.
168
+
169
+ For more detail, see its documents (YARD or RDoc-style
170
+ documents embedded in the code, or see RubyGems webpage).
171
+
172
+
173
+ === RangeExtd Class
174
+
175
+ RangeExtd objects are immutable, the same as Range.
176
+ Hence once an instance is created, it would not change.
177
+
178
+ How to create an instance is explained above (in the Examples
179
+ sections). Any attempt to try to create an instance that is not
180
+ "valid" as a range (see below) raises an exception (<tt>ArgumentError</tt>), and fails.
181
+
182
+ There are two constants defined in this class:
183
+
184
+ * RangeExtd::NONE
185
+ * RangeExtd::EVERYTHING
186
+
187
+ The former represents the empty range and the latter does the range
188
+ covers everything, namely open-ended for the both negative and
189
+ positive directions.
190
+
191
+ In addition to all the standard methods of Range, the following
192
+ methods are added to both RangeExtd and Range classes.
193
+ See the document of each method for detail (some are defined only in
194
+ Range class, as RangeExtd inherits it).
195
+
196
+ * <tt>exclude_begin?</tt>
197
+ * <tt>valid?</tt>
198
+ * <tt>empty?</tt>
199
+ * <tt>null?</tt>
200
+ * <tt>is_none?</tt>
201
+ * <tt>is_everything?</tt>
202
+
203
+ There is a class method, which is equivalent to the instance
204
+ method <tt>valid?</tt>.
205
+ * <tt>RangeExtd.valid?</tt>
206
+
207
+ What is valid (<tt>#valid?</tt> => true) as a range is defined as follows.
208
+
209
+ 1. Both <tt>begin</tt> and <tt>end</tt> elements must be Comparable to each other,
210
+ and the comparison results must be consistent between the two.
211
+ The sole exception is {RangeExtd::NONE}, which is valid.
212
+ For example, <tt>(nil..nil)</tt> is NOT valid (nb., it raised Exception in Ruby 1.8).
213
+ 2. begin must be smaller than or equal (<tt>==</tt>) to end,
214
+ that is, <tt>(begin <=> end)</tt> must be either -1 or 0.
215
+ 3. If begin is equal to end, namely, <tt>(begin <=> end) == 0</tt>,
216
+ the exclude status of the both ends must agree.
217
+ That is, if the <tt>begin</tt> is excluded, <tt>end</tt> must be also excluded,
218
+ and vice versa.
219
+ For example, <tt>(1...1)</tt> is NOT valid for that reason,
220
+ because any built-in Range object has the exclude status
221
+ of false (namely, inclusive) for <tt>begin</tt>.
222
+
223
+ For more detail and examples see the documents of
224
+ {RangeExtd.valid?} and {Range#valid?}
225
+
226
+ The definition of what is empty (<tt>#empty?</tt> => true) as a range is as follows;
227
+
228
+ 1. the range must be valid: <tt>valid?</tt> => true
229
+ 2. if the range id discrete, that is, begin has
230
+ <tt>succ</tt> method, there must be no member within the range
231
+ (which means the begin must be excluded, too):
232
+ <tt>to_a.empty?</tt> => true
233
+ 3. if the range is continuous, that is, begin does not have
234
+ <tt>succ</tt> method, begin and end must be equal
235
+ (<tt>(begin <=> end)</tt> => 0) and both the boundaries must
236
+ be excluded: <tt>(exclude_begin? && exclude_end?)</tt> => true.
237
+
238
+ Note that ranges with equal <tt>begin</tt> and <tt>end</tt> with inconsistent two
239
+ exclude status are not valid, as mentioned in the previous paragraph.
240
+ The built-in Range always has the begin-exclude status of
241
+ <tt>false</tt>. For that reason, no instance of built-in Range
242
+ has the status of <tt>empty?</tt> of <tt>true</tt>.
243
+
244
+ For more detail and examples see the documents of
245
+ {Range#empty?}
246
+
247
+ Finally, {Range#null?} is equivalent to "either empty or not valid".
248
+ Therefore, for RangeExtd objects <tt>null?</tt> is equivalent to
249
+ <tt>empty?</tt>.
250
+
251
+ In comparison (<tt><=></tt>) between a RangeExtd and another RangeExtd or Range
252
+ object, those definitions are taken into account.
253
+ Some of them are shown in the above Examples section.
254
+ For more detail, see {Range#==}> and {RangeExtd#==}>, as
255
+ well as <tt>#eql?</tt>.
256
+
257
+ Note that as long as the operation is within Range objects, the
258
+ behaviour is identical to the standard Ruby -- it is completely
259
+ compatible. Therefore, requiring this library would not affect any
260
+ existing code in principle.
261
+
262
+
263
+ == Known bugs
264
+
265
+ * <tt>hash()</tt> method does not always guarantee to return a unique
266
+ and exclusive number for the equal RangeExtd object, though such an
267
+ exception is extremely unlikely to happen in reality.
268
+
269
+ Note this library does not work in Ruby 1.8 or earlier.
270
+ For Ruby 1.9.3 it is probably all right, however I have never tested
271
+ it.
272
+
273
+ Extensive tests have been performed, as included in the package.
274
+
275
+
276
+ == ToDo
277
+
278
+ Nothing planned.
279
+
280
+
281
+ == Final notes
282
+
283
+ All the behaviours within RangeExtd (not Range), such as
284
+ any comparison between two RangeExtd, should be (or hopefully?)
285
+ natural for you. At least it is well-defined and self-consistent, as
286
+ the logical structure of the ranges is now complete with RangeExtd.
287
+ Note some behaviours for open-ended or begin-excluded ranges may
288
+ give you a little shock at first. For example, the method
289
+ <tt>member?(obj)</tt> for an open-ended range for the negative direction with
290
+ discrete elements returns <tt>nil</tt>. That is because no meaningful method
291
+ of <tt>succ()</tt> is defined for the (negative) infinity, hence it is
292
+ theoretically impossible in general to check whether the given obj is a member of
293
+ the range or not. You may find it to be weird, but that just means
294
+ the concept of the infinity is unfamiliar to us mortals!
295
+
296
+ On the other hand, the comparison between RangeExtd and Range may have
297
+ more occasional surprises. That is because some of the accepted
298
+ ranges by built-in Range class are no longer valid in this framework with the
299
+ inclusion of exclude-status of the begin boundary, as explained.
300
+ Hopefully you will feel it to be natural as you get accustomed to it.
301
+ And I bet once you have got accustomed to it, you will never want to
302
+ go back to the messy world of logical incompleteness, that is, the
303
+ current behaviour of Range!
304
+
305
+ Enjoy.
306
+
307
+
308
+
309
+ == Miscellaneous
310
+
311
+ == Copyright etc
312
+
313
+ Author:: Masa Sakano < imagine a_t sakano dot co dot uk >
314
+ License:: MIT.
315
+ Warranty:: No warranty whatsoever.
316
+ Versions:: The versions of this package follow Semantic Versioning (2.0.0) http://semver.org/
317
+
@@ -0,0 +1,300 @@
1
+
2
+ = RangeExtd - 拡張Rangeクラス - exclude_begin と無限大に開いた範囲と
3
+
4
+ このパッケージは、Range を拡張した RangeExtd クラスを定義しています。
5
+ 以下の特徴を持ちます。
6
+
7
+ 1. メソッド exclude_begin? の導入 (レンジの始点を除外できる),
8
+ 2. (無限大に)開いたレンジ
9
+ 3. NONE (空レンジ) と EVERYTHING (全範囲レンジ)定数の導入
10
+ 4. 初めて自己論理的に完結したレンジ構造の達成
11
+ 5. 組込Rangeとの完全後方互換性
12
+
13
+ 組込Rangeにある exclude_end に加えて、exclude_beginを導入したこと、及
14
+ び無限大へ開いた範囲を許可したことで、一次元上の範囲の論理的完全性を実
15
+ 現しました。
16
+
17
+ これにより、レンジの有効性を厳密に定義しています。それに従って、数個の
18
+ メソッドを Range及び(自然に)そのサブクラスに追加しました。なかでも特徴的なのが、
19
+ {Range#valid?} と {Range#empty?} です。
20
+
21
+ たとえば、<tt>(3...3).valid?</tt> は偽を返します。要素の 3 が、始点と
22
+ しては含まれているのに対し、終点としては除外されていて、これは相互に矛
23
+ 盾しているためです。ここで導入する RangeExtdクラスにおいては、以下のよ
24
+ うにこれが有効なレンジとして定義できます。
25
+ * RangeExtd.new(3, 3, true, true) # => 空レンジ
26
+ * RangeExtd.new(3, 3, false, false) # => 一点レンジ (3..3)
27
+
28
+ しかしながら、組込Rangeの範囲内に収まっている限り、何も変わっていませ
29
+ ん。つまり、標準の Rubyとの完全な後方互換性を実現しています。
30
+
31
+ 無限に開いたレンジを表すのは簡単です。単に {RangeExtd::Infinity}クラスで
32
+ 定義されている二つの定数(無限大または無現小、あるいは無限前と無限後)の
33
+ いずれかを用います。
34
+ * RangeExtd::Infinity::NEGATIVE
35
+ * RangeExtd::Infinity::POSITIVE
36
+
37
+ これらは基本的に <tt>Float::INFINITY</tt> を全ての Comparableであるオ
38
+ ブジェクトに一般化したものです。たとえば、
39
+ ("a"..RangeExtd::Infinity::POSITIVE).each
40
+ は、"a"から始まる <tt>String#succ</tt> を使った無限のイテレーターを与えます
41
+ (だから、どこかで必ず breakするようにコードを書きましょう!)。
42
+
43
+ 組込 Rangeは大変有用なクラスであり、Rubyユーザーに容易なプログラミングを可能にす
44
+ るツールでした。しかし、始点を除外することができないのが玉に瑕でありました。
45
+
46
+ ただし、それにはれっきとした理由があることは分かります。Rubyの Rangeは、Numeric
47
+ (厳密にはその実数を表現したもの)だけに限ったものではありません。 <tt>succ()</tt> メソッ
48
+ ドを持つオブジェクトによる Rangeは極めて有用です。一方、<tt>succ()</tt> の逆に相
49
+ 当するメソッドは一般的には定義されていません。そういう意味で、Rangeは本質的に非
50
+ 対称です。加えて、よく使われる Rangeオブジェクトのうちあるもの(たとえば Float)は
51
+ 連続的なのに対し、そうでないものも普通です(たとえば Integer や String)。この状況
52
+ が厳密な定義をする時の混乱に拍車をかけています。
53
+
54
+ ここで始点を除外可能としたことは、そういう意味で、道筋が100パーセント明らかなも
55
+ のではありませんでした。ここで私が採用した RangeExtdクラスの定義は、おそらく、考え
56
+ られる唯一のものではないでしょう。とはいえ、個人的には満足のいくものに仕上がりま
57
+ したし、このレンジという枠内での論理的完全性をうまく達成できたと思います。
58
+
59
+ このクラスが少なからぬ人に有用なものであることを願ってここにリリースします。
60
+
61
+
62
+ == インストール
63
+
64
+ gem install range_extd
65
+
66
+ により、ファイルが 2個、
67
+ range_extd/range_extd.rb
68
+ range_extd/infinity/infinity.rb
69
+ <tt>$LOAD_PATH</tt> の一カ所にインストールされるはずです。
70
+
71
+ あるいは、パッケージを以下から入手できます。
72
+ http://rubygems.org/gems/range_extd
73
+
74
+ 後は、Ruby のコード(又は irb)から
75
+ require 'range_extd/range_extd'
76
+ とするだけです。もしくは、特に手でインストールした場合は、
77
+ require 'range_extd'
78
+ とする必要があるかも知れません。もう一方のファイル
79
+ range_extd/infinity/infinity.rb
80
+ は、自動的に読み込まれます。
81
+
82
+ お楽しみあれ!
83
+
84
+
85
+ == 単純な使用例
86
+
87
+ === RangeExtd インスタンスを作成する方法
88
+
89
+ 以下に幾つかの基本的な使用例を列挙します。
90
+
91
+ r = RangeExtd(?a...?d, true) # => a<...d
92
+ r.exclude_begin? # => true
93
+ r.to_a # => ["b", "c"]
94
+ RangeExtd(1...2) == (1...2) # => true
95
+ RangeExtd(1, 2, false, true)== (1...2) # => true
96
+ RangeExtd(1, 1, false, false)==(1..1) # => true
97
+ RangeExtd(1, 1, true, true) == RangeExtd::NONE # => true
98
+ RangeExtd(1, 1, false, true) # => ArgumentError
99
+ (RangeExtd::Infinity::NEGATIVE..RangeExtd::Infinity::POSITIVE) \
100
+ == RangeExtd::EVERYTHING # => true
101
+
102
+ インスタンスを作成するのには、二通りあります。
103
+
104
+ RangeExtd(range, [exclude_begin=false, [exclude_end=false]])
105
+ RangeExtd(obj_begin, obj_end, [exclude_begin=false, [exclude_end=false]])
106
+
107
+ 後ろの二つのパラメーターが、それぞれ始点と終点とを除外する(true)、または含む
108
+ (false)を指示します。もし、その二つのパラメーターが最初のパラメーターのレンジ
109
+ (Range or RangeExtd) と矛盾する場合は、ここで与えた二つのパラメーターが優先され
110
+ ます。 <tt>RangeExtd.new()</tt> も上と同意味です。
111
+
112
+
113
+ === 少し上級編
114
+
115
+ (1..RangeExtd::Infinity::POSITIVE).each do |i|
116
+ print i
117
+ break if i >= 9
118
+ end # => self ( "123456789" => STDOUT )
119
+ (nil..nil).valid? # => false
120
+ (1...1).valid? # => false
121
+ (1...1).null? # => true
122
+ RangeExtd.valid?(1...1) # => false
123
+ RangeExtd(1, 1, true, true).valid? # => true
124
+ RangeExtd(1, 1, true, true).empty? # => true
125
+ RangeExtd(?a, ?b, true, true).to_a? # => []
126
+ RangeExtd(?a, ?b, true, true).empty? # => true
127
+ RangeExtd(?a, ?e, true, true).to_a? # => ["b", "c", "d"]
128
+ RangeExtd(?a, ?e, true, true).empty? # => false
129
+ RangeExtd::NONE.is_none? # => true
130
+ RangeExtd::EVERYTHING.is_everything? # => true
131
+
132
+ 組込Rangeに含まれる全てのメソッドが使用可能です。
133
+
134
+
135
+ == 詳説
136
+
137
+ ファイル range_extd.rb が読まれた段階で、次の二つのクラスが定義されます。
138
+
139
+ * RangeExtd
140
+ * RangeExtd::Infinity
141
+
142
+ 加えて、Range クラスに数個のメソッドが追加また改訂されます。Rangeクラスに加えら
143
+ れる改変は、全て後方互換性を保っています。
144
+
145
+ === RangeExtd::Infinity クラス
146
+
147
+ {RangeExtd::Infinity} クラスは、基本、定数二つのみを保持するものです。
148
+
149
+ * RangeExtd::Infinity::NEGATIVE
150
+ * RangeExtd::Infinity::POSITIVE
151
+
152
+ これらは、 <tt>Float::INFINITY</tt> を全ての Comparable なオブジェクトに一般化し
153
+ たものです。メソッド <tt><=></tt> と <tt>succ</tt> が定義されています。
154
+
155
+ これらは、他のオブジェクトと同様に普通に使用可能です。たとえば、
156
+ ("k"..RangeExtd::Infinity::POSITIVE)
157
+ とはいえ、他には何もメソッドを持っていないため、 Range型のクラスの中以外での使用
158
+ はおそらく意味がないでしょう。
159
+
160
+ なお、Numericのオブジェクトに対しては、原則として <tt>Float::INFINITY</tt> の方
161
+ を使って下さい。
162
+
163
+ ユーザー定義のどの Comparable なクラスに属するどのオブジェクトも、これら二定数と
164
+ 可換的に比較可能です。その際、同クラスに置ける比較メソッドがマナー良く書かれてあ
165
+ る、という前提で。
166
+
167
+ さらに詳しくは、マニュアルを参照して下さい(YARD または RDoc形式で書かれた文書が
168
+ コード内部に埋込まれていますし、それが RubyGemsのウェブサイトでも閲覧できます。
169
+
170
+
171
+ === RangeExtd クラス
172
+
173
+ RangeExtd のインスタンスは、 Rangeと同じくイミュータブルです。だから、一度インス
174
+ タンスが生成されると、変化しません。
175
+
176
+ インスタンスの生成方法は上述の通りです(「使用例」の章)。レンジとして"valid"(後述)と見
177
+ なされないインスタンスを生成しようとすると、例外(<tt>ArgumentError</tt>)が発生し、
178
+ 失敗します。
179
+
180
+ このクラスには、二つの定数が定義されています。
181
+
182
+ * RangeExtd::NONE
183
+ * RangeExtd::EVERYTHING
184
+
185
+ 前者は、空レンジを表し、後者は全てを含むレンジ、すなわち正負両方向に開いたレンジを表します。
186
+
187
+ Rangeクラスの通常のメソッド全てに加え、以下が RangeExtd と Rangeクラス両方に加え
188
+ られています。詳細は、各メソッドのマニュアルを参照下さい(注: 幾つかのメソッドは
189
+ Rangeクラスのみで定義されていて、 RangeExtd はそれを継承しています)。
190
+
191
+ * <tt>exclude_begin?</tt>
192
+ * <tt>valid?</tt>
193
+ * <tt>empty?</tt>
194
+ * <tt>null?</tt>
195
+ * <tt>is_none?</tt>
196
+ * <tt>is_everything?</tt>
197
+
198
+ インスタンスメソッドの <tt>valid?</tt> に等価なクラスメソッドも一つあります。
199
+ * <tt>RangeExtd.valid?</tt>
200
+
201
+ 何がレンジとして有効 (<tt>#valid?</tt> => true) かの定義は以下です。
202
+
203
+ 1. 始点と終点とが互いに Comparable であり、かつその比較結果に矛盾がないこと。
204
+ この唯一の例外は {RangeExtd::NONE} で、これは valid です。
205
+ たとえば、<tt>(nil..nil)</tt> は valid では「ありません」(参考までに、この例は
206
+ Ruby 1.8 では例外を生じていました)。
207
+ 2. 始点は終点と等しい(<tt>==</tt>)か小さくなければなりません。すなわし、
208
+ <tt>(begin <=> end)</tt> は、-1 または 0 を返すこと。
209
+ 3. もし始点と終点とが等しい時、すなわち <tt>(begin <=> end) == 0</tt>ならば、
210
+ 端を除外するかどうかのフラグは両端で一致していなければなりません。
211
+ すなわち、もし始点が除外ならば、終点も除外されていなくてはならず、逆も真です。
212
+ その一例として、 <tt>(1...1)</tt> は、"valid" では「ありません」。なぜならば
213
+ 組込レンジでは、始点を常に含むからです。
214
+
215
+ さらなる詳細は {RangeExtd.valid?} と {Range#valid?} のマニュアルを
216
+ 参照して下さい。
217
+
218
+ 何がレンジとして空(<tt>#empty?</tt> => true)かの定義は以下の通りです。
219
+
220
+ 1. レンジは、valid であること: <tt>valid?</tt> => true
221
+ 2. もしレンジの要素が離散的であれば、すなわち始点の要素がメソッド <tt>succ</tt>
222
+ を持っていれば、レンジ内部に要素が一つも無いことが条件(当然、始点のフラグ
223
+ は除外になっていなければなりません): <tt>to_a.empty?</tt> => true
224
+ 3. もしレンジが連続的であれば、すなわち始点の要素がメソッド <tt>succ</tt> を持っ
225
+ ていなければ、始点と終点とが等しく (<tt>(begin <=> end)</tt> => 0)、かつ両端
226
+ のフラグが除外になっていること: <tt>(exclude_begin? && exclude_end?)</tt> => true.
227
+
228
+ なお、始点と終点とが等しい一方でその除外フラグが一致しない場合は、前節で述べたよ
229
+ うに "valid"ではありません。組込レンジは、始点除外フラグが常に偽(<tt>false</tt>)で
230
+ す。そのため、組込Rangeのオブジェクトで、<tt>empty?</tt> が真(<tt>true</tt>)にな
231
+ ることはありません。
232
+
233
+ さらなる詳細は {Range#empty?} のマニュアルを
234
+ 参照して下さい。
235
+
236
+
237
+ 最後、 {Range#null?} は、「<tt>empty?</tt> または "valid"でない」ことに等
238
+ 価です。従って、 RangeExtd オブジェクトにとっては、<tt>null?</tt> は
239
+ <tt>empty?</tt> に等価です。
240
+
241
+ RangeExtd と別の RangeExtd または Rangeの比較 (<tt><=></tt>) においては、これら
242
+ の定義が考慮されます。そのうちの幾つかは、上の「使用例」の項に示されています。
243
+ さらなる詳細は {Range#==}、{RangeExtd#==} および
244
+ <tt>#eql?</tt> のマニュアルを参照して下さい。
245
+
246
+ なお、処理が Rangeオブジェクト内部で閉じている限り、その振舞いは標準 Rubyと同一
247
+ で、互換性を保っています。したがって、このライブラリを読込むことで既存のコードに
248
+ 影響を与えることは原理的にないはずです。
249
+
250
+
251
+ == 既知のバグ
252
+
253
+ * <tt>hash()</tt> メソッドは、等しい RangeExtdオブジェに対して常に唯一で排他的な
254
+ 数値を返すことが保証されていません。ただし、現実的にそれが破られることは、まず
255
+ ありません。
256
+
257
+ このライブラリは Ruby 1.8 およびそれ以前のバージョンでは動作しません。
258
+ Ruby 1.9.3 ではおそらく大丈夫でしょうが、私は試したことがありません。
259
+
260
+ パッケージに含まれている通り、網羅的なテストが実行されています。
261
+
262
+
263
+ == 未処理事項
264
+
265
+ 特になし。
266
+
267
+
268
+ == 終わりに
269
+
270
+ RangeExtd内部に閉じた(Rangeでなく)挙動、たとえば RangeExtd同士の比較などは、
271
+ 全てユーザーにとって自然なもののはずです(と期待します?)。少なくとも、RangeExtdに
272
+ よってレンジの論理構造が完結した今、これはよく定義されかつ自己矛盾が無いものと言
273
+ えましょう。ただ、端の無限に開いた、あるいは始点が除外されたレンジの挙動には、
274
+ 一瞬ぎょっとするものが無くはないかも知れないことに注意して下さい。たとえば、
275
+ 片端が小さい方向に無限に開いて離散的な要素を持つレンジに対してメソッド
276
+ <tt>member?(obj)</tt> を実行すると、 <tt>nil</tt>が返ります。これは、無限(小)に
277
+ は実質的な意味を持つ <tt>succ()</tt> メソッドが定義されていないためで、したがっ
278
+ て与えられた objがレンジの要素(member)かどうかを調べることが、一般論としては理論
279
+ 的に不可能だからです。これはちょっと不思議に思うかも知れませんが、それはつまり定
280
+ 命の私たちには無限という概念を計り知るのが容易でない、というだけの話でしょう!
281
+
282
+ 一方、RangeExtd と Range との比較は、それ以上に驚くことがあるかも知れません。こ
283
+ れは、組込Rangeクラスで許容されているレンジの一部は、始点を除外することを認めた
284
+ 枠組の中では、前述のように最早有効(valid)と見なされないからです。この枠組に慣れるに
285
+ したがって、それらが自然だと思えるようになればいいのですが。保証しますが、一旦こ
286
+ れに慣れてしまえば、論理的不完全さ極まる混沌とした世界、つまりは Rangeの現在の挙
287
+ 動には二度と戻りたくなくなることでしょう!
288
+
289
+ お楽しみ下さい。
290
+
291
+
292
+ == その他
293
+
294
+ == 著作権他情報
295
+
296
+ 著者:: Masa Sakano < imagine a_t sakano dot co dot uk >
297
+ 利用許諾条項:: MIT.
298
+ 保証:: 一切無し。
299
+ バージョン:: Semantic Versioning (2.0.0) http://semver.org/
300
+