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.
@@ -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
- {https://rubygems.org/gems/rangesmaller}
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.new}.
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
- * <tt>hash()</tt> method does not always guarantee to return a unique
285
- and exclusive number for the equal RangeExtd object, though such an
286
- exception is extremely unlikely to happen in reality.
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, however I have never tested
290
- it.
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
- Nothing planned.
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
- {https://rubygems.org/gems/rangesmaller}
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.new}を参照して下さい。
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
- このライブラリは Ruby 1.8 およびそれ以前のバージョンでは動作しません。
614
- Ruby 1.9.3 ではおそらく大丈夫でしょうが、私は試したことがありません。
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, Fixnum, Bignum, Rational, Numeric, String] # , BigFloat
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
- alias :cmp_before_rangeextd_infinity? :== if ! self.method_defined?(:cmp_before_rangeextd_infinity?) # No overwriting.
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
- alias :to_s :inspect
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
- alias :compare_before_infinity :== if ! self.method_defined?(:compare_before_infinity)
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
- alias :compare_obj_before_infinity :== if ! self.method_defined?(:compare_obj_before_infinity) # No overwriting.
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
- return 0
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
- if inar.size > 2 && defined?(inar[1].=~)
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
- alias :equal_prerangeextd? :== if ! self.method_defined?(:equal_prerangeextd?) # No overwriting.
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