range_extd 0.3.0 → 0.4
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.
- checksums.yaml +5 -5
- data/.gitignore +55 -0
- data/ChangeLog +14 -1
- data/Makefile +23 -0
- data/News +4 -0
- data/README.en.rdoc +398 -11
- data/README.ja.rdoc +89 -22
- data/lib/range_extd/infinity/infinity.rb +8 -6
- data/lib/range_extd/range_extd.rb +159 -20
- data/test/test_range_extd.rb +160 -59
- metadata +13 -13
- data/range_extd.gemspec +0 -48
data/README.ja.rdoc
CHANGED
@@ -22,6 +22,7 @@ For example, <tt>(3...3).valid?</tt> returns false, because the element 3 is
|
|
22
22
|
inclusive for the begin boundary, yet exclusive for the end boundary,
|
23
23
|
which are contradictory to each other. With this RangeExtd class,
|
24
24
|
it is expressed as a valid range,
|
25
|
+
|
25
26
|
* RangeExtd.new(3, 3, true, true) # => an empty range
|
26
27
|
* RangeExtd.new(3, 3, false, false) # => a single-point range (3..3)
|
27
28
|
|
@@ -31,12 +32,15 @@ so it is completely compatible with the standard Ruby.
|
|
31
32
|
To express open-ended ranges is simple; you just use either of
|
32
33
|
the two (negative and positive, or former and later) constants
|
33
34
|
defined in the class {RangeExtd::Infinity}
|
35
|
+
|
34
36
|
* RangeExtd::Infinity::NEGATIVE
|
35
37
|
* RangeExtd::Infinity::POSITIVE
|
36
38
|
|
37
39
|
They are basically the object that generalised <tt>Float::INFINITY</tt> to
|
38
40
|
any Comparable object. For example,
|
41
|
+
|
39
42
|
("a"..RangeExtd::Infinity::POSITIVE).each
|
43
|
+
|
40
44
|
gives an infinite iterator with <tt>String#succ</tt>, starting from "a"
|
41
45
|
(therefore, make sure to code so it breaks the iterator at one stage!).
|
42
46
|
|
@@ -64,10 +68,19 @@ I hope you find it to be useful.
|
|
64
68
|
|
65
69
|
==== NOTE: Relationship with Rangesmaller
|
66
70
|
|
67
|
-
This package supercedes the obsolete Rangesmaller package and class,
|
71
|
+
This package supercedes the obsolete {Rangesmaller}[https://rubygems.org/gems/rangesmaller] package and class,
|
68
72
|
with the added open-ended feature, and a different interface in
|
69
73
|
creating a new instance.
|
70
|
-
|
74
|
+
https://rubygems.org/gems/rangesmaller
|
75
|
+
|
76
|
+
==== NOTE: Relationship with Rangeary
|
77
|
+
|
78
|
+
The class to handle multiple Ranges with objects of the same class
|
79
|
+
(most typically Float),
|
80
|
+
{Rangeary}[https://rubygems.org/gems/rangeary] uses this library to
|
81
|
+
fullest, because the concept of potentially open-ended Range ato both
|
82
|
+
begin and end is essential to realise Rangeary.
|
83
|
+
https://rubygems.org/gems/rangeary
|
71
84
|
|
72
85
|
|
73
86
|
== Install
|
@@ -75,19 +88,28 @@ creating a new instance.
|
|
75
88
|
gem install range_extd
|
76
89
|
|
77
90
|
Two files
|
91
|
+
|
78
92
|
range_extd/range_extd.rb
|
79
93
|
range_extd/infinity/infinity.rb
|
94
|
+
|
80
95
|
should be installed in one of your <tt>$LOAD_PATH</tt>
|
81
96
|
|
82
97
|
Alternatively get it from
|
98
|
+
|
83
99
|
http://rubygems.org/gems/range_extd
|
84
100
|
|
85
101
|
Then all you need to do is
|
102
|
+
|
86
103
|
require 'range_extd/range_extd'
|
104
|
+
|
87
105
|
or, possibly as follows, if you manually install it
|
106
|
+
|
88
107
|
require 'range_extd'
|
108
|
+
|
89
109
|
in your Ruby script (or irb). The other file
|
110
|
+
|
90
111
|
range_extd/infinity/infinity.rb
|
112
|
+
|
91
113
|
is called (required) from it automatically.
|
92
114
|
|
93
115
|
Have fun!
|
@@ -126,7 +148,7 @@ defined by a user (see {RangeExtd.middle_strings=}() for detail), and is arguabl
|
|
126
148
|
the most visibly recognisable way for any range with <tt>exclude_begin=true</tt>.
|
127
149
|
|
128
150
|
<tt>RangeExtd.new()</tt> is the same thing.
|
129
|
-
For more detail and examples, see {RangeExtd.
|
151
|
+
For more detail and examples, see {RangeExtd.initialize}.
|
130
152
|
|
131
153
|
|
132
154
|
=== Slightly more advanced uses
|
@@ -147,6 +169,7 @@ For more detail and examples, see {RangeExtd.new}.
|
|
147
169
|
RangeExtd(?a, ?e, true, true).empty? # => false
|
148
170
|
RangeExtd::NONE.is_none? # => true
|
149
171
|
RangeExtd::ALL.is_all? # => true
|
172
|
+
(3...7).equiv?(3..6) # => true
|
150
173
|
|
151
174
|
All the methods that are in the built-in Range can be used.
|
152
175
|
|
@@ -173,7 +196,9 @@ They are the objects that generalise the concept of
|
|
173
196
|
to any Comparable objects. The methods <tt><=></tt> and <tt>succ</tt> are defined.
|
174
197
|
|
175
198
|
You can use them the same as other objects, such as,
|
199
|
+
|
176
200
|
("k"..RangeExtd::Infinity::POSITIVE)
|
201
|
+
|
177
202
|
However as they do not have any other methods,
|
178
203
|
the use out of Range-type class is probably meaningless.
|
179
204
|
|
@@ -216,9 +241,11 @@ See the document of each method for detail (some are defined only in
|
|
216
241
|
* <tt>null?</tt>
|
217
242
|
* <tt>is_none?</tt>
|
218
243
|
* <tt>is_all?</tt>
|
244
|
+
* <tt>equiv?</tt>
|
219
245
|
|
220
246
|
There are three class methods, the first of which is equivalent
|
221
247
|
to the instance method <tt>valid?</tt>:
|
248
|
+
|
222
249
|
* <tt>RangeExtd.valid?</tt>
|
223
250
|
* <tt>RangeExtd.middle_strings=(ary)</tt>
|
224
251
|
* <tt>RangeExtd.middle_strings</tt>
|
@@ -281,20 +308,28 @@ existing code in principle.
|
|
281
308
|
|
282
309
|
== Known bugs
|
283
310
|
|
284
|
-
*
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
Note this library does not work in Ruby 1.8 or earlier.
|
289
|
-
For Ruby 1.9.3 it is probably all right,
|
290
|
-
|
311
|
+
* As of Ruby 2.6, {Endless Range}[https://rubyreferences.github.io/rubychanges/2.6.html#endless-range-1]
|
312
|
+
is introduced. As a result, Range#end sometimes raises RangeError.
|
313
|
+
However, this library does not yet take it into account, and it may
|
314
|
+
raises Exception when encountering an endless Range.
|
315
|
+
* Note this library does not work in Ruby 1.8 or earlier.
|
316
|
+
For Ruby 1.9.3 it is probably all right, though I have never tested it.
|
317
|
+
* Some unusual (rare) boundary conditions are found to vary from
|
318
|
+
version to version in Ruby, such as a comparison between
|
319
|
+
Float::INFINITY-s. Though the test scripts are pretty extensive,
|
320
|
+
they have not been performed over many different versions of Ruby.
|
321
|
+
In some versions, some features may not work well, although such
|
322
|
+
occasions should be very rare.
|
323
|
+
* {RangeExtd#hash} method does not theoretically guarantee to return a unique
|
324
|
+
number for a {RangeExtd} object, though to encounter a hash number that is
|
325
|
+
used elsewhere is extremely unlikely to happen in reality.
|
291
326
|
|
292
327
|
Extensive tests have been performed, as included in the package.
|
293
328
|
|
294
329
|
|
295
330
|
== ToDo
|
296
331
|
|
297
|
-
|
332
|
+
* Handle the Ruby-2.6 new feature {Endless Range}[https://rubyreferences.github.io/rubychanges/2.6.html#endless-range-1].
|
298
333
|
|
299
334
|
|
300
335
|
== Final notes
|
@@ -359,6 +394,7 @@ Versions:: The versions of this package follow Semantic Versioning (2.0.0) http:
|
|
359
394
|
しては含まれているのに対し、終点としては除外されていて、これは相互に矛
|
360
395
|
盾しているためです。ここで導入する RangeExtdクラスにおいては、以下のよ
|
361
396
|
うにこれが有効なレンジとして定義できます。
|
397
|
+
|
362
398
|
* RangeExtd.new(3, 3, true, true) # => 空レンジ
|
363
399
|
* RangeExtd.new(3, 3, false, false) # => 一点レンジ (3..3)
|
364
400
|
|
@@ -368,12 +404,15 @@ Versions:: The versions of this package follow Semantic Versioning (2.0.0) http:
|
|
368
404
|
無限に開いたレンジを表すのは簡単です。単に {RangeExtd::Infinity}クラスで
|
369
405
|
定義されている二つの定数(無限大または無現小、あるいは無限前と無限後)の
|
370
406
|
いずれかを用います。
|
407
|
+
|
371
408
|
* RangeExtd::Infinity::NEGATIVE
|
372
409
|
* RangeExtd::Infinity::POSITIVE
|
373
410
|
|
374
411
|
これらは基本的に <tt>Float::INFINITY</tt> を全ての Comparableであるオ
|
375
412
|
ブジェクトに一般化したものです。たとえば、
|
413
|
+
|
376
414
|
("a"..RangeExtd::Infinity::POSITIVE).each
|
415
|
+
|
377
416
|
は、"a"から始まる <tt>String#succ</tt> を使った無限のイテレーターを与えます
|
378
417
|
(だから、どこかで必ず breakするようにコードを書きましょう!)。
|
379
418
|
|
@@ -396,31 +435,48 @@ Versions:: The versions of this package follow Semantic Versioning (2.0.0) http:
|
|
396
435
|
このクラスが少なからぬ人に有用なものであることを願ってここにリリースします。
|
397
436
|
|
398
437
|
|
399
|
-
==== 注: Rangesmaller
|
438
|
+
==== 注: Rangesmallerとの関係
|
400
439
|
|
401
|
-
このパッケージは、(今やサポートされていない) Rangesmaller パッケージ及びクラスを
|
440
|
+
このパッケージは、(今やサポートされていない) {Rangesmaller}[https://rubygems.org/gems/rangesmaller] パッケージ及びクラスを
|
402
441
|
後継するものです。同クラスの機能に、無限に開いた範囲を許す機能が加わり、また、オ
|
403
442
|
ブジェクト生成時のインターフェースが変更されています。
|
404
|
-
|
443
|
+
https://rubygems.org/gems/rangesmaller
|
444
|
+
|
445
|
+
==== 注: Rangearyとの関係
|
446
|
+
|
447
|
+
同クラス(典型的にはFloat)のオブジェクトからなる複数のRangeを扱うクラス
|
448
|
+
{Rangeary}[https://rubygems.org/gems/rangeary] は、本ライブラリを使い
|
449
|
+
切っています。Rangeを実現するためには、始端と終端との両方で開いた可能
|
450
|
+
性があるRangeを扱うことが必須だからです。
|
451
|
+
https://rubygems.org/gems/rangeary
|
405
452
|
|
406
453
|
== インストール
|
407
454
|
|
408
455
|
gem install range_extd
|
409
456
|
|
410
457
|
により、ファイルが 2個、
|
458
|
+
|
411
459
|
range_extd/range_extd.rb
|
412
460
|
range_extd/infinity/infinity.rb
|
461
|
+
|
413
462
|
<tt>$LOAD_PATH</tt> の一カ所にインストールされるはずです。
|
414
463
|
|
415
464
|
あるいは、パッケージを以下から入手できます。
|
465
|
+
|
416
466
|
http://rubygems.org/gems/range_extd
|
417
467
|
|
418
468
|
後は、Ruby のコード(又は irb)から
|
469
|
+
|
419
470
|
require 'range_extd/range_extd'
|
471
|
+
|
420
472
|
とするだけです。もしくは、特に手でインストールした場合は、
|
473
|
+
|
421
474
|
require 'range_extd'
|
475
|
+
|
422
476
|
とする必要があるかも知れません。もう一方のファイル
|
477
|
+
|
423
478
|
range_extd/infinity/infinity.rb
|
479
|
+
|
424
480
|
は、自動的に読み込まれます。
|
425
481
|
|
426
482
|
お楽しみあれ!
|
@@ -460,7 +516,7 @@ Versions:: The versions of this package follow Semantic Versioning (2.0.0) http:
|
|
460
516
|
視覚的には最もわかりやすい方法かも知れません。
|
461
517
|
|
462
518
|
<tt>RangeExtd.new()</tt> も上と同意味です。
|
463
|
-
さらなる解説及び例は、{RangeExtd.
|
519
|
+
さらなる解説及び例は、{RangeExtd.initialize}を参照して下さい。
|
464
520
|
|
465
521
|
|
466
522
|
=== 少し上級編
|
@@ -481,6 +537,7 @@ Versions:: The versions of this package follow Semantic Versioning (2.0.0) http:
|
|
481
537
|
RangeExtd(?a, ?e, true, true).empty? # => false
|
482
538
|
RangeExtd::NONE.is_none? # => true
|
483
539
|
RangeExtd::ALL.is_all? # => true
|
540
|
+
(3...7).equiv?(3..6) # => true
|
484
541
|
|
485
542
|
組込Rangeに含まれる全てのメソッドが使用可能です。
|
486
543
|
|
@@ -547,9 +604,11 @@ RangeExtd のインスタンスは、 Rangeと同じくイミュータブルで
|
|
547
604
|
* <tt>null?</tt>
|
548
605
|
* <tt>is_none?</tt>
|
549
606
|
* <tt>is_all?</tt>
|
607
|
+
* <tt>equiv?</tt>
|
550
608
|
|
551
609
|
クラスメソッドが三つあります。一番上のものは、
|
552
610
|
インスタンスメソッドの <tt>valid?</tt> に等価です。
|
611
|
+
|
553
612
|
* <tt>RangeExtd.valid?</tt>
|
554
613
|
* <tt>RangeExtd.middle_strings=(ary)</tt>
|
555
614
|
* <tt>RangeExtd.middle_strings</tt>
|
@@ -606,19 +665,27 @@ RangeExtd と別の RangeExtd または Rangeの比較 (<tt><=></tt>) におい
|
|
606
665
|
|
607
666
|
== 既知のバグ
|
608
667
|
|
609
|
-
* <tt>hash()</tt> メソッドは、等しい RangeExtdオブジェに対して常に唯一で排他的な
|
610
|
-
数値を返すことが保証されていません。ただし、現実的にそれが破られることは、まず
|
611
|
-
ありません。
|
612
668
|
|
613
|
-
|
614
|
-
|
669
|
+
* Ruby 2.6 では、後ろに無限に開いたRange({Endless Range}[https://rubyreferences.github.io/rubychanges/2.6.html#endless-range-1])
|
670
|
+
が導入されました。本ライブラリでは、まだそれには対応していません。
|
671
|
+
したがって、Endless Rangeを本クラスに適用した場合、問題が起きるでしょう。
|
672
|
+
* このライブラリは Ruby 1.8 およびそれ以前のバージョンでは動作しません。
|
673
|
+
Ruby 1.9.3 ではおそらく大丈夫でしょうが、私は試したことがありません。
|
674
|
+
* いくつかの極めて稀な境界条件に於ける挙動は、Rubyのバージョンごとにあ
|
675
|
+
る程度変化しています。例えば、Float::INFINITY 同士の比較などの挙動が
|
676
|
+
異なります。同梱のテストスクリプトはかなり網羅的ではあるものの、Ruby
|
677
|
+
の多数のバージョンでテストはしておりません。したがって、バージョンに
|
678
|
+
よっては、(極めて稀でしょうが)問題が発生する可能性が否定できません。
|
679
|
+
* {RangeExtd#hash} メソッドは、ある RangeExtdオブジェに対して常に唯一で排他的な
|
680
|
+
数値を返すことが理論保証はされていません。ただし、現実的にそれが破られることは、まず
|
681
|
+
ありません。
|
615
682
|
|
616
683
|
パッケージに含まれている通り、網羅的なテストが実行されています。
|
617
684
|
|
618
685
|
|
619
|
-
==
|
686
|
+
== 開発項目
|
620
687
|
|
621
|
-
|
688
|
+
* Ruby 2.6の後ろに無限に開いたRange({Endless Range}[https://rubyreferences.github.io/rubychanges/2.6.html#endless-range-1])に対応する。
|
622
689
|
|
623
690
|
|
624
691
|
== 終わりに
|
@@ -114,7 +114,9 @@ class RangeExtd < Range
|
|
114
114
|
end
|
115
115
|
|
116
116
|
# Class that accept to be compared with Infinity instances.
|
117
|
-
CLASSES_ACCEPTABLE = [self, Float,
|
117
|
+
CLASSES_ACCEPTABLE = [self, Float, Integer, Rational, Numeric, String] # Fixnum, Bignum deprecated now.
|
118
|
+
# CLASSES_ACCEPTABLE = [self, Float, Fixnum, Bignum, Rational, Numeric, String] # , BigFloat
|
119
|
+
CLASSES_ACCEPTABLE.push BigFloat if defined? BigFloat
|
118
120
|
|
119
121
|
def infinity?
|
120
122
|
true
|
@@ -128,7 +130,7 @@ class RangeExtd < Range
|
|
128
130
|
!@positive
|
129
131
|
end
|
130
132
|
|
131
|
-
|
133
|
+
alias_method :cmp_before_rangeextd_infinity?, :== if ! self.method_defined?(:cmp_before_rangeextd_infinity?) # No overwriting.
|
132
134
|
|
133
135
|
# Always -1 or 1 except for itself and the corresponding infinities (== 0). See {#==}.
|
134
136
|
# Or, nil (as defined by Object), if the argument is not Comparable, such as, nil and IO.
|
@@ -189,7 +191,7 @@ class RangeExtd < Range
|
|
189
191
|
end
|
190
192
|
end
|
191
193
|
|
192
|
-
|
194
|
+
alias_method :to_s, :inspect
|
193
195
|
|
194
196
|
|
195
197
|
# Overwrite [#<=>] method of the given class, if necessary,
|
@@ -225,7 +227,7 @@ class RangeExtd < Range
|
|
225
227
|
klass = obj.class
|
226
228
|
|
227
229
|
begin
|
228
|
-
1.0 + obj # Use "rescue ArgumentError" if using "1.0<obj"
|
230
|
+
_ = 1.0 + obj # Use "rescue ArgumentError" if using "1.0<obj"
|
229
231
|
return nil # No change for Numeric
|
230
232
|
rescue TypeError
|
231
233
|
end
|
@@ -250,7 +252,7 @@ class RangeExtd < Range
|
|
250
252
|
# Overwrite the definition of "<=>" so that it is fliped over for Infinity.
|
251
253
|
|
252
254
|
code = <<__EOF__
|
253
|
-
|
255
|
+
alias_method :compare_before_infinity, :<=> if ! self.method_defined?(:compare_before_infinity)
|
254
256
|
def <=>(c)
|
255
257
|
if defined?(self.<=) && RangeExtd::Infinity === c
|
256
258
|
if defined?(self.infinity?) && defined?(self.positive?)
|
@@ -322,7 +324,7 @@ end # class RangeExtd < Range
|
|
322
324
|
# aware of {RangeExtd::Infinity} objects (the two constants).
|
323
325
|
#
|
324
326
|
class Object
|
325
|
-
|
327
|
+
alias_method :compare_obj_before_infinity, :<=> if ! self.method_defined?(:compare_obj_before_infinity) # No overwriting.
|
326
328
|
|
327
329
|
# Overwrite {Object#<=>}(). Then, all its sub-classes can be
|
328
330
|
# aware of RangeExtd::Infinity objects (the two constants).
|
@@ -30,23 +30,6 @@ end # req_files.each do |req_file|
|
|
30
30
|
# Initial set up of 2 constants in RangeExtd.
|
31
31
|
########################################
|
32
32
|
|
33
|
-
class RangeExtd < Range
|
34
|
-
## Temporary initialize() just to define the two constants.
|
35
|
-
def initialize(rangepart, ex_begin, ex_end)
|
36
|
-
@rangepart = rangepart
|
37
|
-
@exclude_begin = ex_begin
|
38
|
-
@exclude_end = ex_end
|
39
|
-
end
|
40
|
-
|
41
|
-
# Two constants
|
42
|
-
NONE = RangeExtd.new(nil...nil, true, true) # In Ruby1.8, this causes ArgumentError: bad value for range (because (nil..nil) is unaccepted).
|
43
|
-
ALL = RangeExtd.new(Infinity::NEGATIVE..Infinity::POSITIVE, false, false)
|
44
|
-
|
45
|
-
#NONE.freeze
|
46
|
-
#ALL.freeze
|
47
|
-
end
|
48
|
-
|
49
|
-
|
50
33
|
# =Class RangeExtd
|
51
34
|
#
|
52
35
|
# Authors:: Masa Sakano
|
@@ -127,6 +110,15 @@ class RangeExtd < Range
|
|
127
110
|
# @raise [ArgumentError] particularly if the range to be created is not {#valid?}.
|
128
111
|
def initialize(*inar, **hsopt) # **k expression from Ruby 1.9?
|
129
112
|
|
113
|
+
if inar[4] == :Constant
|
114
|
+
# Special case to create two Constants
|
115
|
+
super(*inar[0..2])
|
116
|
+
@rangepart = (inar[2] ? (inar[0]...inar[1]) : (inar[0]..inar[1]))
|
117
|
+
@exclude_end, @exclude_begin = inar[2..3]
|
118
|
+
return
|
119
|
+
end
|
120
|
+
|
121
|
+
# [RangeBeginValue, RangeEndValue, exclude_end?, exclude_begin?]
|
130
122
|
arout = RangeExtd.class_eval{ _get_init_args(*inar, hsopt) } # class_eval from Ruby 1.8.7 (?)
|
131
123
|
|
132
124
|
### The following routine is obsolete.
|
@@ -165,6 +157,7 @@ class RangeExtd < Range
|
|
165
157
|
@exclude_begin = arout.pop
|
166
158
|
@exclude_end = arout[-1]
|
167
159
|
@rangepart = Range.new(*arout)
|
160
|
+
super(*arout)
|
168
161
|
|
169
162
|
end # def initialize(*inar)
|
170
163
|
|
@@ -326,6 +319,77 @@ class RangeExtd < Range
|
|
326
319
|
alias :member? :===
|
327
320
|
|
328
321
|
|
322
|
+
# Return true if self and the other are equivalent; if [#to_a] is defined, it is similar to
|
323
|
+
# (self.to_a == other.to_a)
|
324
|
+
# (though the ends are checked more rigorously), and if not, equivalent to
|
325
|
+
# (self == other)
|
326
|
+
#
|
327
|
+
# @example
|
328
|
+
# RangeExtd(2...7,true).equiv?(3..6) # => true
|
329
|
+
# RangeExtd(2...7,true).equiv?(3..6.0) # => false
|
330
|
+
# RangeExtd(2...7,true).equiv?(3.0..6.0) # => false
|
331
|
+
# RangeExtd(2...7,true).equiv?(3..6.5) # => false
|
332
|
+
# RangeExtd(2...7,true).equiv?(RangeExtd(2.0...7.0,true)) # => true
|
333
|
+
# RangeExtd(2...7,true).equiv?(3...7.0) # => true
|
334
|
+
#
|
335
|
+
# @param other [Range, RangeExtd]
|
336
|
+
def equiv?(other)
|
337
|
+
# This routine is very similar to Range#equiv? except
|
338
|
+
# exclude_begin? in this object is always defined, hence
|
339
|
+
# a more thorough check is needed.
|
340
|
+
|
341
|
+
t_or_f = (defined?(self.begin.succ) && defined?(other.begin.succ) && defined?(other.end) && defined?(other.exclude_end?))
|
342
|
+
if ! t_or_f
|
343
|
+
return(self == other) # succ() for begin is not defined.
|
344
|
+
else
|
345
|
+
# Checking the begins.
|
346
|
+
if defined?(other.exclude_begin?)
|
347
|
+
other_excl_beg = other.exclude_begin?
|
348
|
+
else
|
349
|
+
other_excl_beg = false
|
350
|
+
end
|
351
|
+
|
352
|
+
if (self.begin == other.begin)
|
353
|
+
if (exclude_begin? ^! other_excl_beg)
|
354
|
+
# Pass
|
355
|
+
else
|
356
|
+
return false
|
357
|
+
end
|
358
|
+
else
|
359
|
+
if (exclude_begin? ^! other_excl_beg)
|
360
|
+
return false
|
361
|
+
elsif (exclude_begin? && (self.begin.succ == other.begin)) ||
|
362
|
+
(other_excl_beg && (self.begin == other.begin.succ))
|
363
|
+
# Pass
|
364
|
+
else
|
365
|
+
return false
|
366
|
+
end
|
367
|
+
end # if (self.begin == other.begin) # else
|
368
|
+
|
369
|
+
# Now, the begins agreed. Checking the ends.
|
370
|
+
if (self.end == other.end)
|
371
|
+
if (exclude_end? ^! other.exclude_end?)
|
372
|
+
return true
|
373
|
+
else
|
374
|
+
return false
|
375
|
+
end
|
376
|
+
else # if (self.end == other.end)
|
377
|
+
if (exclude_end? ^! other.exclude_end?)
|
378
|
+
return false
|
379
|
+
# elsif defined?(other.last) && (self.last(1) == other.last(1)) # Invalid for Ruby 1.8 or earlier # This is not good - eg., in this case, (1..5.5).equiv?(1..5.4) would return true.
|
380
|
+
|
381
|
+
# return true
|
382
|
+
elsif ( exclude_end? && defined?(other.end.succ) && (self.end == other.end.succ)) ||
|
383
|
+
(other.exclude_end? && defined?( self.end.succ) && (self.end.succ == other.end))
|
384
|
+
return true
|
385
|
+
else
|
386
|
+
return false
|
387
|
+
end
|
388
|
+
end # if (self.end == other.end)
|
389
|
+
end # if ! t_or_f
|
390
|
+
end # def equiv?(other)
|
391
|
+
|
392
|
+
|
329
393
|
# @return [Object]
|
330
394
|
def begin()
|
331
395
|
@rangepart.begin()
|
@@ -646,6 +710,10 @@ class RangeExtd < Range
|
|
646
710
|
# in the range whereas 4.8 is not in the range by definition,
|
647
711
|
# but not the example right above.
|
648
712
|
#
|
713
|
+
# @note When both ends n are the same INFINITY (of the same parity),
|
714
|
+
# +(n..n).size+ used to be 0. As of Ruby 2.6, it is FloatDomainError: NaN.
|
715
|
+
# This routine follows what Ruby produces, depending on Ruby's version it is run on.
|
716
|
+
#
|
649
717
|
# @see http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-list/49797 [ruby-list:49797] from matz for how {Range#size} behaves (in Japanese).
|
650
718
|
#
|
651
719
|
# @return [Integer] 0 if {RangeExtd::NONE}
|
@@ -676,7 +744,9 @@ class RangeExtd < Range
|
|
676
744
|
elsif (defined?(self.begin.infinity?) && self.begin.infinity? || self.begin == -Infinity::FLOAT_INFINITY) ||
|
677
745
|
(defined?(self.end.infinity?) && self.end.infinity? || self.end == Infinity::FLOAT_INFINITY)
|
678
746
|
if self.begin == self.end
|
679
|
-
|
747
|
+
# This varies, depending on Ruby's version! It used to be 0. As of Ruby 2.6, it is FloatDomainError: NaN.
|
748
|
+
return (Float::INFINITY..Float::INFINITY).size
|
749
|
+
# return 0
|
680
750
|
else
|
681
751
|
return Infinity::FLOAT_INFINITY
|
682
752
|
end
|
@@ -804,7 +874,12 @@ class RangeExtd < Range
|
|
804
874
|
|
805
875
|
# Now, checking if the form is the String one, and if so, process it.
|
806
876
|
arMid = @@middle_strings.map{|i| Regexp.quote(i)} # See self.middle_strings=(ary) for description.
|
807
|
-
|
877
|
+
|
878
|
+
# Originally, defined?(inar[1].=~) seemed enough. But as of Ruby 2.6,
|
879
|
+
# Numeric has :=~ method as well!
|
880
|
+
if inar.size > 2 &&
|
881
|
+
inar[1].class.method_defined?(:=~) &&
|
882
|
+
inar[1].class.method_defined?(:to_str)
|
808
883
|
begin
|
809
884
|
cmp = (inar[0] <=> inar[2]).abs
|
810
885
|
rescue
|
@@ -860,6 +935,7 @@ class RangeExtd < Range
|
|
860
935
|
exclude_end = (hsopt[:exclude_end] && true)
|
861
936
|
end
|
862
937
|
|
938
|
+
# [RangeBeginValue, RangeEndValue, exclude_end?, exclude_begin?]
|
863
939
|
beginend + [exclude_end, exclude_begin]
|
864
940
|
|
865
941
|
end # def self._get_init_args(*inar)
|
@@ -1173,6 +1249,15 @@ class RangeExtd < Range
|
|
1173
1249
|
end
|
1174
1250
|
end # def re_min_max_core(method, *rest, &bloc)
|
1175
1251
|
|
1252
|
+
# No range.
|
1253
|
+
# In Ruby1.8, this causes ArgumentError: bad value for range (because (nil..nil) is unaccepted).
|
1254
|
+
NONE = RangeExtd.new(nil, nil, true, true, :Constant)
|
1255
|
+
#NONE = RangeExtd.new(nil...nil, true, true, :Constant)
|
1256
|
+
|
1257
|
+
# Range covers everything.
|
1258
|
+
ALL = RangeExtd.new(Infinity::NEGATIVE, Infinity::POSITIVE, false, false, :Constant)
|
1259
|
+
#ALL = RangeExtd.new(Infinity::NEGATIVE..Infinity::POSITIVE, false, false, :Constant)
|
1260
|
+
|
1176
1261
|
end # class RangeExtd < Range
|
1177
1262
|
|
1178
1263
|
|
@@ -1185,7 +1270,7 @@ end # class RangeExtd < Range
|
|
1185
1270
|
#
|
1186
1271
|
class Range
|
1187
1272
|
|
1188
|
-
|
1273
|
+
alias_method :equal_prerangeextd?, :== if ! self.method_defined?(:equal_prerangeextd?) # No overwriting.
|
1189
1274
|
|
1190
1275
|
# It is extended to handle {RangeExtd} objects.
|
1191
1276
|
# For each element, that is, {#begin} and {#end},
|
@@ -1345,6 +1430,60 @@ class Range
|
|
1345
1430
|
false
|
1346
1431
|
end
|
1347
1432
|
|
1433
|
+
|
1434
|
+
# Return true if self and the other are equivalent; if [#to_a] is defined, it is similar to
|
1435
|
+
# (self.to_a == other.to_a)
|
1436
|
+
# (though the ends are checked more rigorously), and if not, equivalent to
|
1437
|
+
# (self == other)
|
1438
|
+
#
|
1439
|
+
# @example
|
1440
|
+
# (3...7).equiv?(3..6) # => true
|
1441
|
+
# (3...7).equiv?(3..6.0) # => false
|
1442
|
+
# (3...7).equiv?(3.0..6.0) # => false
|
1443
|
+
# (3...7).equiv?(3..6.5) # => false
|
1444
|
+
# (3...7).equiv?(3.0...7.0) # => true
|
1445
|
+
# (3...7.0).equiv?(3..6) # => true
|
1446
|
+
# (3...7.0).equiv?(3.0..6) # => false
|
1447
|
+
#
|
1448
|
+
# @param other [Range, RangeExtd]
|
1449
|
+
def equiv?(other)
|
1450
|
+
t_or_f = (defined?(self.begin.succ) && defined?(other.begin.succ) && defined?(other.end) && defined?(other.exclude_end?))
|
1451
|
+
if ! t_or_f
|
1452
|
+
return(self == other) # succ() for begin is not defined.
|
1453
|
+
else
|
1454
|
+
# Checking the begins.
|
1455
|
+
if defined?(other.exclude_begin?) && other.exclude_begin? # The other is RangeExtd with exclude_begin?==true.
|
1456
|
+
if self.begin != other.begin.succ
|
1457
|
+
return false
|
1458
|
+
else
|
1459
|
+
# Pass
|
1460
|
+
end
|
1461
|
+
elsif (self.begin != other.begin)
|
1462
|
+
return false
|
1463
|
+
end
|
1464
|
+
|
1465
|
+
# Now, the begins agreed. Checking the ends.
|
1466
|
+
if (self.end == other.end)
|
1467
|
+
if (exclude_end? ^! other.exclude_end?)
|
1468
|
+
return true
|
1469
|
+
else
|
1470
|
+
return false
|
1471
|
+
end
|
1472
|
+
else # if (self.end == other.end)
|
1473
|
+
if (exclude_end? ^! other.exclude_end?)
|
1474
|
+
return false
|
1475
|
+
elsif ( exclude_end? && defined?(other.end.succ) && (self.end == other.end.succ)) ||
|
1476
|
+
(other.exclude_end? && defined?( self.end.succ) && (self.end.succ == other.end))
|
1477
|
+
return true
|
1478
|
+
else
|
1479
|
+
return false
|
1480
|
+
end
|
1481
|
+
end # if (self.end == other.end)
|
1482
|
+
end # if ! t_or_f
|
1483
|
+
|
1484
|
+
end # def equiv?(other)
|
1485
|
+
|
1486
|
+
|
1348
1487
|
############## pravate methods of Range ##############
|
1349
1488
|
|
1350
1489
|
private
|