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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 9e1551349faa64451f2d3cb0d0105e0e36d031822fd6d614ff6c641be3ae6091
|
4
|
+
data.tar.gz: 9cfe5dce8e2e887bd8536c37e6e81e47566c477158cdecc5e4dba4ed48aed058
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fed26ea14419c50417d319f54e1fc40d33e5fd95d92f2e19b110c6ebb001fb86581097de95c4551e1d50a4c4919e9c33ffef11a2c8837ffc03f3413cf6a091cf
|
7
|
+
data.tar.gz: e3cd288b44a7d42c9a8b8e947cb4bf030e4b906096bd779d304690708815e8eeabf916893ab334456a69a153504e73364f57e9a5167607b73d64f02f372fb5e4
|
data/.gitignore
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
# See https://help.github.com/articles/ignoring-files for more about ignoring files.
|
2
|
+
#
|
3
|
+
# If you find yourself ignoring temporary files generated by your text editor
|
4
|
+
# or operating system, you probably want to add a global ignore instead:
|
5
|
+
# git config --global core.excludesfile '~/.gitignore_global'
|
6
|
+
|
7
|
+
# Ignore bundler config.
|
8
|
+
/.bundle
|
9
|
+
/vendor/bundle
|
10
|
+
|
11
|
+
# Ignore all logfiles and tempfiles.
|
12
|
+
/log/*
|
13
|
+
/tmp/*
|
14
|
+
!/log/.keep
|
15
|
+
!/tmp/.keep
|
16
|
+
|
17
|
+
.rbenv-version
|
18
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
19
|
+
.rvmrc
|
20
|
+
|
21
|
+
/node_modules
|
22
|
+
/yarn-error.log
|
23
|
+
|
24
|
+
.byebug_history
|
25
|
+
|
26
|
+
*.[oa]
|
27
|
+
*.so
|
28
|
+
*~
|
29
|
+
*.nogem
|
30
|
+
*nogem.*
|
31
|
+
*.bak
|
32
|
+
*.BAK
|
33
|
+
*.backup
|
34
|
+
*.org
|
35
|
+
*.orig
|
36
|
+
*.elc
|
37
|
+
*.pyc
|
38
|
+
\#*\#
|
39
|
+
.\#*
|
40
|
+
|
41
|
+
# Elastic Beanstalk Files
|
42
|
+
.elasticbeanstalk/*
|
43
|
+
!.elasticbeanstalk/*.cfg.yml
|
44
|
+
!.elasticbeanstalk/*.global.yml
|
45
|
+
|
46
|
+
# macOS
|
47
|
+
.DS_Store
|
48
|
+
|
49
|
+
# yard
|
50
|
+
*.yardoc
|
51
|
+
|
52
|
+
# Ruby Gem doc
|
53
|
+
*.gem
|
54
|
+
doc/*
|
55
|
+
|
data/ChangeLog
CHANGED
@@ -1,6 +1,19 @@
|
|
1
|
+
-----
|
2
|
+
(Version: 0.4)
|
3
|
+
2019-10-30 Masa Sakano
|
4
|
+
* Many minor bug fixes (mostly suppressing Warnings) to catch up with Ruby 2.6.
|
5
|
+
* Because quite a few (boundary) behaviours have changed from previous versions a few years ago, such as the comparison between two INFINITY.
|
6
|
+
* Endless range not yet fully incorporated.
|
7
|
+
|
8
|
+
-----
|
9
|
+
(Version: 0.4.0)
|
10
|
+
2014-05-10 Masa Saskano
|
11
|
+
* Added Range#equiv? and RangeExtd#equiv? methods.
|
12
|
+
|
1
13
|
-----
|
2
14
|
(Version: 0.3.0)
|
3
|
-
2014-05-02 Masa
|
15
|
+
2014-05-02 Masa Sakano
|
16
|
+
|
4
17
|
* Added a String expression form of RangeExtd.new and RangeExtd.valid?(), modifying RangeExtd._get_init_args().
|
5
18
|
|
6
19
|
-----
|
data/Makefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
ALL =
|
2
|
+
|
3
|
+
objs =
|
4
|
+
|
5
|
+
.SUFFIXES: .so .o .c .f
|
6
|
+
|
7
|
+
#.o.so:
|
8
|
+
# ${LD} ${LFLAGS} -o $@ $< ${LINK_LIB}
|
9
|
+
|
10
|
+
all: ${ALL}
|
11
|
+
|
12
|
+
|
13
|
+
.PHONY: clean test doc
|
14
|
+
clean:
|
15
|
+
$(RM) bin/*~
|
16
|
+
|
17
|
+
## You may need RUBYLIB=`pwd`/lib:$RUBYLIB
|
18
|
+
test:
|
19
|
+
rake test
|
20
|
+
|
21
|
+
doc:
|
22
|
+
yard doc; [[ -x ".github" && ( "README.ja.rdoc" -nt ".github/README.md" ) ]] && ( ruby -r rdoc -e 'puts RDoc::Markup::ToMarkdown.new.convert ARGF.read' < README.ja.rdoc > .github/README.md ; echo ".github/README.md is updated." ) || exit 0
|
23
|
+
|
data/News
CHANGED
data/README.en.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
|
@@ -334,3 +369,355 @@ License:: MIT.
|
|
334
369
|
Warranty:: No warranty whatsoever.
|
335
370
|
Versions:: The versions of this package follow Semantic Versioning (2.0.0) http://semver.org/
|
336
371
|
|
372
|
+
|
373
|
+
|
374
|
+
= RangeExtd - 拡張Rangeクラス - exclude_begin と無限大に開いた範囲と
|
375
|
+
|
376
|
+
このパッケージは、Range を拡張した RangeExtd クラスを定義しています。
|
377
|
+
以下の特徴を持ちます。
|
378
|
+
|
379
|
+
1. メソッド exclude_begin? の導入 (レンジの始点を除外できる),
|
380
|
+
2. (無限大に)開いたレンジ
|
381
|
+
3. NONE (空レンジ) と ALL (全範囲レンジ)定数の導入
|
382
|
+
4. 初めて自己論理的に完結したレンジ構造の達成
|
383
|
+
5. 組込Rangeとの完全後方互換性
|
384
|
+
|
385
|
+
組込Rangeにある exclude_end に加えて、exclude_beginを導入したこと、及
|
386
|
+
び無限大へ開いた範囲を許可したことで、一次元上の範囲の論理的完全性を実
|
387
|
+
現しました。
|
388
|
+
|
389
|
+
これにより、レンジの有効性を厳密に定義しています。それに従って、数個の
|
390
|
+
メソッドを Range及び(自然に)そのサブクラスに追加しました。なかでも特徴的なのが、
|
391
|
+
{Range#valid?} と {Range#empty?} です。
|
392
|
+
|
393
|
+
たとえば、<tt>(3...3).valid?</tt> は偽を返します。要素の 3 が、始点と
|
394
|
+
しては含まれているのに対し、終点としては除外されていて、これは相互に矛
|
395
|
+
盾しているためです。ここで導入する RangeExtdクラスにおいては、以下のよ
|
396
|
+
うにこれが有効なレンジとして定義できます。
|
397
|
+
|
398
|
+
* RangeExtd.new(3, 3, true, true) # => 空レンジ
|
399
|
+
* RangeExtd.new(3, 3, false, false) # => 一点レンジ (3..3)
|
400
|
+
|
401
|
+
しかしながら、組込Rangeの範囲内に収まっている限り、何も変わっていませ
|
402
|
+
ん。つまり、標準の Rubyとの完全な後方互換性を実現しています。
|
403
|
+
|
404
|
+
無限に開いたレンジを表すのは簡単です。単に {RangeExtd::Infinity}クラスで
|
405
|
+
定義されている二つの定数(無限大または無現小、あるいは無限前と無限後)の
|
406
|
+
いずれかを用います。
|
407
|
+
|
408
|
+
* RangeExtd::Infinity::NEGATIVE
|
409
|
+
* RangeExtd::Infinity::POSITIVE
|
410
|
+
|
411
|
+
これらは基本的に <tt>Float::INFINITY</tt> を全ての Comparableであるオ
|
412
|
+
ブジェクトに一般化したものです。たとえば、
|
413
|
+
|
414
|
+
("a"..RangeExtd::Infinity::POSITIVE).each
|
415
|
+
|
416
|
+
は、"a"から始まる <tt>String#succ</tt> を使った無限のイテレーターを与えます
|
417
|
+
(だから、どこかで必ず breakするようにコードを書きましょう!)。
|
418
|
+
|
419
|
+
組込 Rangeは大変有用なクラスであり、Rubyユーザーに容易なプログラミングを可能にす
|
420
|
+
るツールでした。しかし、始点を除外することができないのが玉に瑕でありました。
|
421
|
+
|
422
|
+
ただし、それにはれっきとした理由があることは分かります。Rubyの Rangeは、Numeric
|
423
|
+
(厳密にはその実数を表現したもの)だけに限ったものではありません。 <tt>succ()</tt> メソッ
|
424
|
+
ドを持つオブジェクトによる Rangeは極めて有用です。一方、<tt>succ()</tt> の逆に相
|
425
|
+
当するメソッドは一般的には定義されていません。そういう意味で、Rangeは本質的に非
|
426
|
+
対称です。加えて、よく使われる Rangeオブジェクトのうちあるもの(たとえば Float)は
|
427
|
+
連続的なのに対し、そうでないものも普通です(たとえば Integer や String)。この状況
|
428
|
+
が厳密な定義をする時の混乱に拍車をかけています。
|
429
|
+
|
430
|
+
ここで始点を除外可能としたことは、そういう意味で、道筋が100パーセント明らかなも
|
431
|
+
のではありませんでした。ここで私が採用した RangeExtdクラスの定義は、おそらく、考え
|
432
|
+
られる唯一のものではないでしょう。とはいえ、個人的には満足のいくものに仕上がりま
|
433
|
+
したし、このレンジという枠内での論理的完全性をうまく達成できたと思います。
|
434
|
+
|
435
|
+
このクラスが少なからぬ人に有用なものであることを願ってここにリリースします。
|
436
|
+
|
437
|
+
|
438
|
+
==== 注: Rangesmallerとの関係
|
439
|
+
|
440
|
+
このパッケージは、(今やサポートされていない) {Rangesmaller}[https://rubygems.org/gems/rangesmaller] パッケージ及びクラスを
|
441
|
+
後継するものです。同クラスの機能に、無限に開いた範囲を許す機能が加わり、また、オ
|
442
|
+
ブジェクト生成時のインターフェースが変更されています。
|
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
|
452
|
+
|
453
|
+
== インストール
|
454
|
+
|
455
|
+
gem install range_extd
|
456
|
+
|
457
|
+
により、ファイルが 2個、
|
458
|
+
|
459
|
+
range_extd/range_extd.rb
|
460
|
+
range_extd/infinity/infinity.rb
|
461
|
+
|
462
|
+
<tt>$LOAD_PATH</tt> の一カ所にインストールされるはずです。
|
463
|
+
|
464
|
+
あるいは、パッケージを以下から入手できます。
|
465
|
+
|
466
|
+
http://rubygems.org/gems/range_extd
|
467
|
+
|
468
|
+
後は、Ruby のコード(又は irb)から
|
469
|
+
|
470
|
+
require 'range_extd/range_extd'
|
471
|
+
|
472
|
+
とするだけです。もしくは、特に手でインストールした場合は、
|
473
|
+
|
474
|
+
require 'range_extd'
|
475
|
+
|
476
|
+
とする必要があるかも知れません。もう一方のファイル
|
477
|
+
|
478
|
+
range_extd/infinity/infinity.rb
|
479
|
+
|
480
|
+
は、自動的に読み込まれます。
|
481
|
+
|
482
|
+
お楽しみあれ!
|
483
|
+
|
484
|
+
|
485
|
+
== 単純な使用例
|
486
|
+
|
487
|
+
=== RangeExtd インスタンスを作成する方法
|
488
|
+
|
489
|
+
以下に幾つかの基本的な使用例を列挙します。
|
490
|
+
|
491
|
+
r = RangeExtd(?a...?d, true) # => a<...d
|
492
|
+
r.exclude_begin? # => true
|
493
|
+
r.to_a # => ["b", "c"]
|
494
|
+
RangeExtd(1...2) == (1...2) # => true
|
495
|
+
RangeExtd(1, 2, false, true)== (1...2) # => true
|
496
|
+
RangeExtd(1, 1, false, false)==(1..1) # => true
|
497
|
+
RangeExtd(1, 1, true, true) == RangeExtd::NONE # => true
|
498
|
+
RangeExtd(1, 1, false, true) # => ArgumentError
|
499
|
+
(RangeExtd::Infinity::NEGATIVE..RangeExtd::Infinity::POSITIVE) \
|
500
|
+
== RangeExtd::ALL # => true
|
501
|
+
|
502
|
+
インスタンスを作成するのには、三通りあります。
|
503
|
+
|
504
|
+
RangeExtd(range, [exclude_begin=false, [exclude_end=false]], opts)
|
505
|
+
RangeExtd(obj_begin, obj_end, [exclude_begin=false, [exclude_end=false]], opts)
|
506
|
+
RangeExtd(obj_begin, string_form, obj_end, [exclude_begin=false, [exclude_end=false]], opts)
|
507
|
+
|
508
|
+
大括弧の中の二つのパラメーターが、それぞれ始点と終点とを除外する(true)、または含む
|
509
|
+
(false)を指示します。もし、その二つのパラメーターが最初のパラメーターのレンジ
|
510
|
+
(Range or RangeExtd) と矛盾する場合は、ここで与えた二つのパラメーターが優先され
|
511
|
+
ます。同じパラメーターをオプションHash
|
512
|
+
(<tt>:exclude_begin</tt> と <tt>:exclude_end</tt>)で指定することもできて、
|
513
|
+
もし指定されればそれらが最高の優先度を持ちます。
|
514
|
+
第三の方法の <tt>string_form</tt> とは、".." や "<..."のことで、ユーザー定義
|
515
|
+
も可能です(詳しくは {RangeExtd.middle_strings=}() を参照のこと)。これが、
|
516
|
+
視覚的には最もわかりやすい方法かも知れません。
|
517
|
+
|
518
|
+
<tt>RangeExtd.new()</tt> も上と同意味です。
|
519
|
+
さらなる解説及び例は、{RangeExtd.initialize}を参照して下さい。
|
520
|
+
|
521
|
+
|
522
|
+
=== 少し上級編
|
523
|
+
|
524
|
+
(1..RangeExtd::Infinity::POSITIVE).each do |i|
|
525
|
+
print i
|
526
|
+
break if i >= 9
|
527
|
+
end # => self ( "123456789" => STDOUT )
|
528
|
+
(nil..nil).valid? # => false
|
529
|
+
(1...1).valid? # => false
|
530
|
+
(1...1).null? # => true
|
531
|
+
RangeExtd.valid?(1...1) # => false
|
532
|
+
RangeExtd(1, 1, true, true).valid? # => true
|
533
|
+
RangeExtd(1, 1, true, true).empty? # => true
|
534
|
+
RangeExtd(?a, ?b, true, true).to_a? # => []
|
535
|
+
RangeExtd(?a, ?b, true, true).empty? # => true
|
536
|
+
RangeExtd(?a, ?e, true, true).to_a? # => ["b", "c", "d"]
|
537
|
+
RangeExtd(?a, ?e, true, true).empty? # => false
|
538
|
+
RangeExtd::NONE.is_none? # => true
|
539
|
+
RangeExtd::ALL.is_all? # => true
|
540
|
+
(3...7).equiv?(3..6) # => true
|
541
|
+
|
542
|
+
組込Rangeに含まれる全てのメソッドが使用可能です。
|
543
|
+
|
544
|
+
|
545
|
+
== 詳説
|
546
|
+
|
547
|
+
ファイル range_extd.rb が読まれた段階で、次の二つのクラスが定義されます。
|
548
|
+
|
549
|
+
* RangeExtd
|
550
|
+
* RangeExtd::Infinity
|
551
|
+
|
552
|
+
加えて、Range クラスに数個のメソッドが追加また改訂されます。Rangeクラスに加えら
|
553
|
+
れる改変は、全て後方互換性を保っています。
|
554
|
+
|
555
|
+
=== RangeExtd::Infinity クラス
|
556
|
+
|
557
|
+
{RangeExtd::Infinity} クラスは、基本、定数二つのみを保持するものです。
|
558
|
+
|
559
|
+
* RangeExtd::Infinity::NEGATIVE
|
560
|
+
* RangeExtd::Infinity::POSITIVE
|
561
|
+
|
562
|
+
これらは、 <tt>Float::INFINITY</tt> を全ての Comparable なオブジェクトに一般化し
|
563
|
+
たものです。メソッド <tt><=></tt> と <tt>succ</tt> が定義されています。
|
564
|
+
|
565
|
+
これらは、他のオブジェクトと同様に普通に使用可能です。たとえば、
|
566
|
+
("k"..RangeExtd::Infinity::POSITIVE)
|
567
|
+
とはいえ、他には何もメソッドを持っていないため、 Range型のクラスの中以外での使用
|
568
|
+
はおそらく意味がないでしょう。
|
569
|
+
|
570
|
+
なお、Numericのオブジェクトに対しては、原則として <tt>Float::INFINITY</tt> の方
|
571
|
+
を使って下さい。
|
572
|
+
|
573
|
+
ユーザー定義のどの Comparable なクラスに属するどのオブジェクトも、これら二定数と
|
574
|
+
可換的に比較可能です。その際、同クラスに置ける比較メソッドがマナー良く書かれてあ
|
575
|
+
る、という前提で。
|
576
|
+
|
577
|
+
さらに詳しくは、マニュアルを参照して下さい(YARD または RDoc形式で書かれた文書が
|
578
|
+
コード内部に埋込まれていますし、それが RubyGemsのウェブサイトでも閲覧できます。
|
579
|
+
|
580
|
+
|
581
|
+
=== RangeExtd クラス
|
582
|
+
|
583
|
+
RangeExtd のインスタンスは、 Rangeと同じくイミュータブルです。だから、一度インス
|
584
|
+
タンスが生成されると、変化しません。
|
585
|
+
|
586
|
+
インスタンスの生成方法は上述の通りです(「使用例」の章)。レンジとして"valid"(後述)と見
|
587
|
+
なされないインスタンスを生成しようとすると、例外(<tt>ArgumentError</tt>)が発生し、
|
588
|
+
失敗します。
|
589
|
+
|
590
|
+
このクラスには、二つの定数が定義されています。
|
591
|
+
|
592
|
+
* RangeExtd::NONE
|
593
|
+
* RangeExtd::ALL
|
594
|
+
|
595
|
+
前者は、空レンジを表し、後者は全てを含むレンジ、すなわち正負両方向に開いたレンジを表します。
|
596
|
+
|
597
|
+
{Range}クラスの通常のメソッド全てに加え、以下が {RangeExtd} と {Range}クラス両方に加え
|
598
|
+
られています。詳細は、各メソッドのマニュアルを参照下さい(注: 幾つかのメソッドは
|
599
|
+
{Range}クラスのみで定義されていて、 {RangeExtd} はそれを継承しています)。
|
600
|
+
|
601
|
+
* <tt>exclude_begin?</tt> ({Range}クラスでは未定義)
|
602
|
+
* <tt>valid?</tt>
|
603
|
+
* <tt>empty?</tt>
|
604
|
+
* <tt>null?</tt>
|
605
|
+
* <tt>is_none?</tt>
|
606
|
+
* <tt>is_all?</tt>
|
607
|
+
* <tt>equiv?</tt>
|
608
|
+
|
609
|
+
クラスメソッドが三つあります。一番上のものは、
|
610
|
+
インスタンスメソッドの <tt>valid?</tt> に等価です。
|
611
|
+
|
612
|
+
* <tt>RangeExtd.valid?</tt>
|
613
|
+
* <tt>RangeExtd.middle_strings=(ary)</tt>
|
614
|
+
* <tt>RangeExtd.middle_strings</tt>
|
615
|
+
|
616
|
+
何がレンジとして有効 (<tt>#valid?</tt> => true) かの定義は以下です。
|
617
|
+
|
618
|
+
1. 始点と終点とが互いに Comparable であり、かつその比較結果に矛盾がないこと。
|
619
|
+
この唯一の例外は {RangeExtd::NONE} で、これは valid です。
|
620
|
+
たとえば、<tt>(nil..nil)</tt> は valid では「ありません」(参考までに、この例は
|
621
|
+
Ruby 1.8 では例外を生じていました)。
|
622
|
+
2. 始点は終点と等しい(<tt>==</tt>)か小さくなければなりません。すなわし、
|
623
|
+
<tt>(begin <=> end)</tt> は、-1 または 0 を返すこと。
|
624
|
+
3. もし始点と終点とが等しい時、すなわち <tt>(begin <=> end) == 0</tt>ならば、
|
625
|
+
端を除外するかどうかのフラグは両端で一致していなければなりません。
|
626
|
+
すなわち、もし始点が除外ならば、終点も除外されていなくてはならず、逆も真です。
|
627
|
+
その一例として、 <tt>(1...1)</tt> は、"valid" では「ありません」。なぜならば
|
628
|
+
組込レンジでは、始点を常に含むからです。
|
629
|
+
|
630
|
+
さらなる詳細は {RangeExtd.valid?} と {Range#valid?} のマニュアルを
|
631
|
+
参照して下さい。
|
632
|
+
|
633
|
+
何がレンジとして空(<tt>#empty?</tt> => true)かの定義は以下の通りです。
|
634
|
+
|
635
|
+
1. レンジは、valid であること: <tt>valid?</tt> => true
|
636
|
+
2. もしレンジの要素が離散的であれば、すなわち始点の要素がメソッド <tt>succ</tt>
|
637
|
+
を持っていれば、レンジ内部に要素が一つも無いことが条件(当然、始点のフラグ
|
638
|
+
は除外になっていなければなりません): <tt>to_a.empty?</tt> => true
|
639
|
+
3. もしレンジが連続的であれば、すなわち始点の要素がメソッド <tt>succ</tt> を持っ
|
640
|
+
ていなければ、始点と終点とが等しく (<tt>(begin <=> end)</tt> => 0)、かつ両端
|
641
|
+
のフラグが除外になっていること: <tt>(exclude_begin? && exclude_end?)</tt> => true.
|
642
|
+
|
643
|
+
なお、始点と終点とが等しい一方でその除外フラグが一致しない場合は、前節で述べたよ
|
644
|
+
うに "valid"ではありません。組込レンジは、始点除外フラグが常に偽(<tt>false</tt>)で
|
645
|
+
す。そのため、組込Rangeのオブジェクトで、<tt>empty?</tt> が真(<tt>true</tt>)にな
|
646
|
+
ることはありません。
|
647
|
+
|
648
|
+
さらなる詳細は {Range#empty?} のマニュアルを
|
649
|
+
参照して下さい。
|
650
|
+
|
651
|
+
|
652
|
+
最後、 {Range#null?} は、「<tt>empty?</tt> または "valid"でない」ことに等
|
653
|
+
価です。従って、 RangeExtd オブジェクトにとっては、<tt>null?</tt> は
|
654
|
+
<tt>empty?</tt> に等価です。
|
655
|
+
|
656
|
+
RangeExtd と別の RangeExtd または Rangeの比較 (<tt><=></tt>) においては、これら
|
657
|
+
の定義が考慮されます。そのうちの幾つかは、上の「使用例」の項に示されています。
|
658
|
+
さらなる詳細は {Range#==}、{RangeExtd#==} および
|
659
|
+
<tt>#eql?</tt> のマニュアルを参照して下さい。
|
660
|
+
|
661
|
+
なお、処理が Rangeオブジェクト内部で閉じている限り、その振舞いは標準 Rubyと同一
|
662
|
+
で、互換性を保っています。したがって、このライブラリを読込むことで既存のコードに
|
663
|
+
影響を与えることは原理的にないはずです。
|
664
|
+
|
665
|
+
|
666
|
+
== 既知のバグ
|
667
|
+
|
668
|
+
|
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
|
+
ありません。
|
682
|
+
|
683
|
+
パッケージに含まれている通り、網羅的なテストが実行されています。
|
684
|
+
|
685
|
+
|
686
|
+
== 開発項目
|
687
|
+
|
688
|
+
* Ruby 2.6の後ろに無限に開いたRange({Endless Range}[https://rubyreferences.github.io/rubychanges/2.6.html#endless-range-1])に対応する。
|
689
|
+
|
690
|
+
|
691
|
+
== 終わりに
|
692
|
+
|
693
|
+
RangeExtd内部に閉じた(Rangeでなく)挙動、たとえば RangeExtd同士の比較などは、
|
694
|
+
全てユーザーにとって自然なもののはずです(と期待します?)。少なくとも、RangeExtdに
|
695
|
+
よってレンジの論理構造が完結した今、これはよく定義されかつ自己矛盾が無いものと言
|
696
|
+
えましょう。ただ、端の無限に開いた、あるいは始点が除外されたレンジの挙動には、
|
697
|
+
一瞬ぎょっとするものが無くはないかも知れないことに注意して下さい。たとえば、
|
698
|
+
片端が小さい方向に無限に開いて離散的な要素を持つレンジに対してメソッド
|
699
|
+
<tt>member?(obj)</tt> を実行すると、 <tt>nil</tt>が返ります。これは、無限(小)に
|
700
|
+
は実質的な意味を持つ <tt>succ()</tt> メソッドが定義されていないためで、したがっ
|
701
|
+
て与えられた objがレンジの要素(member)かどうかを調べることが、一般論としては理論
|
702
|
+
的に不可能だからです。これはちょっと不思議に思うかも知れませんが、それはつまり定
|
703
|
+
命の私たちには無限という概念を計り知るのが容易でない、というだけの話でしょう!
|
704
|
+
|
705
|
+
一方、RangeExtd と Range との比較は、それ以上に驚くことがあるかも知れません。こ
|
706
|
+
れは、組込Rangeクラスで許容されているレンジの一部は、始点を除外することを認めた
|
707
|
+
枠組の中では、前述のように最早有効(valid)と見なされないからです。この枠組に慣れるに
|
708
|
+
したがって、それらが自然だと思えるようになればいいのですが。保証しますが、一旦こ
|
709
|
+
れに慣れてしまえば、論理的不完全さ極まる混沌とした世界、つまりは Rangeの現在の挙
|
710
|
+
動には二度と戻りたくなくなることでしょう!
|
711
|
+
|
712
|
+
お楽しみ下さい。
|
713
|
+
|
714
|
+
|
715
|
+
== その他
|
716
|
+
|
717
|
+
== 著作権他情報
|
718
|
+
|
719
|
+
著者:: Masa Sakano < imagine a_t sakano dot co dot uk >
|
720
|
+
利用許諾条項:: MIT.
|
721
|
+
保証:: 一切無し。
|
722
|
+
バージョン:: Semantic Versioning (2.0.0) http://semver.org/
|
723
|
+
|