rangeary 0.3.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.
- checksums.yaml +5 -5
- data/.gitignore +55 -0
- data/ChangeLog +10 -0
- data/Makefile +23 -0
- data/News +4 -0
- data/README.ja.rdoc +326 -80
- data/lib/rangeary/rangeary.rb +791 -358
- data/test/test_rangeary.rb +158 -32
- metadata +11 -11
- data/rangeary.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: 0776d13fb0ae08187d7ff2dfaa89e8bd2a2e360fdebe7e62f94dfbd82f210d06
|
4
|
+
data.tar.gz: b39226c861c431fd132f2a215572ad5ea1a8bd843bcf2045be5ab8940667bd0c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2a1987ea2dd74dda7656ef8722af870bc713194dc51ee67dfdaa167b0d463ba0e18cdfb4d01f9841bb242ea0605c5916e3c6195aacec6b65e46543999169d727
|
7
|
+
data.tar.gz: 921b2ae2084d3f0f2230fd919f711ec47cf94b22438fa88ca0ae738f2d7193fb28b2794e0ef7ce484e54a74aa4bfd75fc22f8cf43b593a786b0e4193ba33fcc0
|
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,3 +1,13 @@
|
|
1
|
+
-----
|
2
|
+
(Version: 1.0)
|
3
|
+
2019-11-01 Masa Sakano
|
4
|
+
* Release of Ver.1! Fully compatible of Endless Range introduced in Ruby 2.6.
|
5
|
+
* requiring RangeExtd Ver.1.1 or later.
|
6
|
+
* Now requiring Ruby-2.1.
|
7
|
+
* The method infinities is now written explicitly, as opposed to attr_reader.
|
8
|
+
* Class method comparable_end is added.
|
9
|
+
* Major refactoring in the initialisation routine and Array#== .
|
10
|
+
|
1
11
|
-----
|
2
12
|
(Version: 0.3.0)
|
3
13
|
2016-05-27 Masa Sakano
|
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.ja.rdoc
CHANGED
@@ -2,13 +2,15 @@
|
|
2
2
|
= Rangeary - Multiple Range(Extd) class
|
3
3
|
|
4
4
|
This package defines Rangeary class, which contains any multiple
|
5
|
-
1-dimensional ranges ({RangeExtd} objects). For example, a multiple
|
5
|
+
1-dimensional ranges ({RangeExtd}[http://rubygems.org/gems/range_extd] objects). For example, a multiple
|
6
6
|
range of
|
7
|
+
|
7
8
|
0.5 < x <= 2.5, 6.0 <= x < 8.0, 10.0 <= x (<= Infinity)
|
9
|
+
|
8
10
|
for <tt>x</tt> can be defined in this class.
|
9
11
|
|
10
12
|
The element objects for {Rangeary} can be anthing that can form
|
11
|
-
|
13
|
+
RangeExtd objects; not only Numeric (or Real) but anything
|
12
14
|
Comparable. {Rangeary} accepts the built-in Range-class objects for
|
13
15
|
the elements in initialisation, too.
|
14
16
|
|
@@ -21,7 +23,7 @@ All the four standard logical operations, that is, negation
|
|
21
23
|
alter the contents.
|
22
24
|
|
23
25
|
Practically, {Rangeary} is a sub-class of Array, works as an array of
|
24
|
-
|
26
|
+
RangeExtd, and inherits most of the methods, hence you can apply most
|
25
27
|
operations to {Rangeary} that Array accpets, within the restriction of
|
26
28
|
immutability of {Rangeary}. In addition, {Rangeary} offers several
|
27
29
|
methods that directly work on its element as a range. In the above
|
@@ -33,35 +35,47 @@ With this class, logical operations of 1-dimensional range objects are
|
|
33
35
|
now possible and easy.
|
34
36
|
I hope you find it to be useful.
|
35
37
|
|
38
|
+
=== News: Endless Range supported
|
39
|
+
|
40
|
+
Now, as of 2019 October, this fully supports {Endless Range}[https://rubyreferences.github.io/rubychanges/2.6.html#endless-range-1]
|
41
|
+
introduced in Ruby 2.6. It is released as Version 1.* finally!
|
42
|
+
|
36
43
|
|
37
44
|
== Install
|
38
45
|
|
39
|
-
First, you need {RangeExtd} class library (basically, two files of pure ruby code), which is in gem:
|
46
|
+
First, you need {RangeExtd}[https://rubygems.org/gems/range_extd] class library (basically, two files of pure ruby code), which is in gem:
|
47
|
+
|
40
48
|
gem install range_extd
|
49
|
+
|
41
50
|
Or, get it from
|
42
|
-
|
51
|
+
https://rubygems.org/gems/range_extd
|
43
52
|
if you have not yet installed it.
|
44
53
|
|
45
54
|
Then, install this library.
|
55
|
+
|
46
56
|
gem install rangeary
|
47
57
|
|
48
58
|
A file
|
59
|
+
|
49
60
|
rangeary/rangeary.rb
|
61
|
+
|
50
62
|
should be installed in one of your <tt>$LOAD_PATH</tt>.
|
51
63
|
Alternatively, get it from
|
52
|
-
|
64
|
+
http://rubygems.org/gems/rangeary
|
53
65
|
|
54
66
|
Then all you need to do is
|
67
|
+
|
55
68
|
require 'rangeary/rangeary'
|
69
|
+
|
56
70
|
or, possibly as follows, if you manually install it
|
71
|
+
|
57
72
|
require 'rangeary'
|
73
|
+
|
58
74
|
in your Ruby script (or irb). The library files like
|
59
|
-
<tt>range_extd/range_extd.rb</tt> for
|
75
|
+
<tt>range_extd/range_extd.rb</tt> for RangeExtd are automatically
|
60
76
|
loaded.
|
61
77
|
|
62
|
-
{Rangeary} itself may work in Ruby 1.8, but
|
63
|
-
Ruby 2.0 (or maybe 1.9.3) and above, hence {Rangeary} does not work in
|
64
|
-
Ruby 1.8 or earlier.
|
78
|
+
{Rangeary} itself may work in Ruby 1.8, but RangeExtd works in only Ruby 2.1 or later.
|
65
79
|
|
66
80
|
Have fun!
|
67
81
|
|
@@ -79,9 +93,9 @@ Here are some simple examples.
|
|
79
93
|
Rangeary(true..true) # => ArgumentError
|
80
94
|
|
81
95
|
Basically, <tt>Rangeary()</tt> or <tt>Rangeary.new()</tt> accepts
|
82
|
-
an arbitrary number of either
|
96
|
+
an arbitrary number of either Range, RangeExtd, {Rangeary}, or a
|
83
97
|
combination of them. Note Range objects that return false in
|
84
|
-
|
98
|
+
+Range#valid?+ will raise an exception.
|
85
99
|
|
86
100
|
For more detail and examples, see {Rangeary.new}.
|
87
101
|
|
@@ -103,22 +117,25 @@ For more detail and examples, see {Rangeary.new}.
|
|
103
117
|
rb + Rangeary(3..7) # => [2...9]
|
104
118
|
rb - Rangeary(3..7) # => [2...3, RangeExtd(7,'<...',9)]
|
105
119
|
rb * Rangeary(4..5, 8..10) # => [4..4, 8...9]
|
106
|
-
rb
|
120
|
+
~rb # => [-Float::INFINITY...2, RangeExtd(4,'<...',6), 9..Float::INFINITY]
|
121
|
+
|
122
|
+
rc = Rangeary(?d...?x, negative: ?a, positive: ?z)
|
123
|
+
~rc # => [?a...?d, ?x..?z]
|
124
|
+
|
125
|
+
where +~rb+ is equivalent to +rb.negation+. In the last example, it
|
126
|
+
provides the user-defined *infinities*.
|
107
127
|
|
108
128
|
Most of the methods that are in the built-in Array can be used, as long as
|
109
129
|
it does not violate the immutability of {Rangeary} objects, such as
|
110
|
-
|
130
|
+
+Array#push+.
|
111
131
|
|
112
132
|
|
113
133
|
== Description
|
114
134
|
|
115
|
-
Once the file <tt>rangeary.rb</tt> is required,
|
135
|
+
Once the file <tt>rangeary.rb</tt> is required, the class +Rangeary+ is defined, in
|
116
136
|
addtion to the two defined in the RangeExtd library
|
117
137
|
(<tt>RangeExtd</tt> and <tt>RangeExtd::Infinity</tt>).
|
118
138
|
|
119
|
-
* Rangeary
|
120
|
-
|
121
|
-
|
122
139
|
=== Rangeary Class
|
123
140
|
|
124
141
|
{Rangeary} objects are immutable, the same as Range and RangeExtd.
|
@@ -126,73 +143,185 @@ Hence once an instance is created, it would not change.
|
|
126
143
|
|
127
144
|
How to create an instance is explained above (in the Examples
|
128
145
|
sections). Any attempt to try to create an instance with one of
|
129
|
-
elements being not "valid" as a range, that is,
|
146
|
+
elements being not "valid" as a range, that is, +Range#valid?+ returns
|
130
147
|
false, raises an exception (<tt>ArgumentError</tt>), and fails.
|
131
148
|
|
132
|
-
Note
|
133
|
-
|
134
|
-
|
135
|
-
|
149
|
+
Note +RangeExtd+ (or +Range+) objects used to initialise {Rangeary}
|
150
|
+
instances can contain negative and/or positive infinity objects.
|
151
|
+
Since Ruby 2.6 the latter is called {Endless Range}[https://rubyreferences.github.io/rubychanges/2.6.html#endless-range-1]
|
152
|
+
and is supported as built-in Range. The former is defined only in
|
153
|
+
{RangeExtd}[https://rubygems.org/gems/range_extd] class.
|
154
|
+
In default they are of the type of either +Float::INFINITY+ or
|
155
|
+
either of the two instances of
|
156
|
+
{RangeExtd::Infinity}[https://www.rubydoc.info/gems/range_extd/RangeExtd/Infinity]
|
157
|
+
class, +POSITIVE+ or +NEGATIVE+. See {Rangeary.new} for detail about
|
158
|
+
how to initialise.
|
136
159
|
|
137
160
|
When multiple ranges are given in initialising, they are sorted in
|
138
|
-
storing, and if there
|
161
|
+
storing, and if there are any overlaps among any of the elements, they
|
139
162
|
are treated as disjunction (that is, simple summation). That means
|
140
163
|
the objects a {Rangeary} instance holds internally can be different from
|
141
|
-
the objects given in initialisation,
|
164
|
+
the objects given in initialisation, namely, their {#object_id} may be
|
142
165
|
different. In particular, if built-in Range objects are given,
|
143
|
-
they are always converted into
|
166
|
+
they are always converted into RangeExtd objects internally.
|
144
167
|
|
145
168
|
If any of the given range in the intialisation is empty, that is,
|
146
|
-
|
169
|
+
+Range#empty?+ returns true, they are ignored, unless all of the
|
147
170
|
ranges given are empty ranges, in which case the "smallest" one will be
|
148
171
|
preserved.
|
149
172
|
|
150
173
|
If the result of the operation is empty, only the element of the
|
151
|
-
resultant {Rangeary} is
|
174
|
+
resultant {Rangeary} is +RangeExtd::NONE+, and hence
|
152
175
|
{Rangeary#empty_element?} will return true.
|
153
176
|
|
154
177
|
For any Rangeary objects, {Rangeary#to_a}.size is always
|
155
178
|
positive and not zero for that reason, or {Rangeary#empty?} returns
|
156
|
-
always false, as {Rangeary#empty?} is a method inherited from Array
|
157
|
-
|
158
|
-
empty or not as a range
|
179
|
+
always false, as {Rangeary#empty?} is a method inherited from Array.
|
180
|
+
Use {Rangeary#empty_element?} instead to check whether the instance is
|
181
|
+
*practically* empty or not as a range.
|
182
|
+
|
159
183
|
Rangeary(RangeExtd::NONE).empty? # => false
|
160
184
|
Rangeary(RangeExtd::NONE).empty_element? # => true
|
161
185
|
|
162
|
-
As mentioned
|
186
|
+
As mentioned, all the methods of Array but a few are inherited
|
163
187
|
to this {Rangeary} class, and they work based on each element
|
164
|
-
|
188
|
+
RangeExtd. Four methods work differently: {Rangeary#+} and
|
165
189
|
{Rangeary#*} are the alias to {Rangeary#disjunction} and
|
166
190
|
{Rangeary#conjunction}, repectively. {Rangeary#===} performs
|
167
|
-
|
191
|
+
+Range#===+ for all the Rangeary element ranges and return true if any
|
168
192
|
of them returns true. Therefore, {Rangeary#===}(RangeExtd(**))
|
169
|
-
returns always false.
|
170
|
-
|
171
|
-
and [#reverse] are undefined.
|
172
|
-
|
173
|
-
{Rangeary#==} and {Rangeary#eql?} work the same as Array, hence
|
174
|
-
[2..4, 6..8] == Rangeary(2..4, 6..8) # => true
|
175
|
-
But please note
|
176
|
-
[2..4, 6..8] == Rangeary(6..8, 2..4) # => true
|
177
|
-
[6..8, 2..4] == Rangeary(6..8, 2..4) # => false
|
178
|
-
In short the direct comparison with a standard Array is not recommended.
|
179
|
-
Instead compare with other {Rangeary} objects.
|
193
|
+
returns always false. Also, +#length+
|
194
|
+
and +#reverse+ are undefined. Finally, {Array#==} is modified (see below).
|
180
195
|
|
181
196
|
All the other methods operating on the element of ranges, rather than
|
182
197
|
on the ranges themselves, have a suffix of <tt>_element</tt>, if there
|
183
198
|
is the same method name in the built-in Array. For example,
|
184
|
-
{Rangeary#size} returns the number of
|
185
|
-
and {Rangeary#size_element} returns the total
|
186
|
-
the
|
199
|
+
{Rangeary#size} returns the number of RangeExtd objects it holds,
|
200
|
+
and {Rangeary#size_element} returns the total +Range#size+ of all
|
201
|
+
the RangeExtd objects it holds.
|
202
|
+
|
187
203
|
Rangeary(1..3, 5..8).size # => 2
|
188
204
|
Rangeary(1..3, 5..8).size_element # => 7
|
189
205
|
|
206
|
+
Or, {Rangeary#flatten_element} returns the concatnated
|
207
|
+
single array of {Rangeary#to_a} for all the discrete range elements
|
208
|
+
(the element ranges have to be discrete like Integer).
|
209
|
+
|
210
|
+
The complete reference of the class and methods is available at
|
211
|
+
{Rubygems website}[http://rubygems.org/gems/rangeary], or you can compile the
|
212
|
+
reference with +yard+ from the source package (+make doc+ at the
|
213
|
+
package root directory would do).
|
214
|
+
|
215
|
+
=== Array#==
|
216
|
+
|
217
|
+
Equal method of +Rangeary#==+ should work differently from Array.
|
218
|
+
First, it behaves differently for *empty* objects, as Rangeary objects are
|
219
|
+
never empty in the sense of Array. Second, handling of
|
220
|
+
{Endless Range}[https://rubyreferences.github.io/rubychanges/2.6.html#endless-range-1]
|
221
|
+
introduced in Ruby 2.6 is conceptionally not straightforward.
|
222
|
+
For example, in Ruby 2.6,
|
223
|
+
|
224
|
+
(?a..).size # => nil
|
225
|
+
(10..).size # => Infinity
|
226
|
+
(10..Float::INFINITY)).size # => Infinity
|
227
|
+
(1.0..) != (1.0..Float::INFINITY)
|
228
|
+
|
229
|
+
These are not trivial, or even a little inconsistent. For Range#size method, if it is for
|
230
|
+
Numeric (but Complex), Endless Range behaves like the number Infinity,
|
231
|
+
yet they (the mathematical infinity and the end of Endless Range) do
|
232
|
+
not compare, and are not equal.
|
233
|
+
|
234
|
+
Rangeary offers functions of logical operations of arrays of Ranges.
|
235
|
+
A consistent definitions of infinity is essential. For example, the
|
236
|
+
negation of +[5..Infinity]+ is
|
237
|
+
|
238
|
+
[-Infinity...5]
|
239
|
+
|
240
|
+
that is, from the negative infinity to 5, excluding the end. Then the
|
241
|
+
negation of it must recover the original Rangeary +(5..Infinity)+.
|
242
|
+
|
243
|
+
Obviously, it could not be done with +Endless Range+, as it defines only the positive infinity,
|
244
|
+
or more accurately *positive endlessness*. For that reason, the use of
|
245
|
+
+RangeExtd+ is crucial for Rangeary.
|
246
|
+
|
247
|
+
In the Rangeary operation (of negation in this case), the following can happen:
|
248
|
+
|
249
|
+
r1 = Rangeary(5..) # => [(5..)] (equivalent to (5..nil))
|
250
|
+
r2 = ~Rangeary(5..) # => [(-Float::INFINITY...5)]
|
251
|
+
r3 = ~~Rangeary(5..) # => [(5..Float::INFINITY)]
|
252
|
+
|
253
|
+
r4 = Rangeary(?a..) # => [(?a..)] (equivalent to (?a..nil))
|
254
|
+
r5 = ~Rangeary(?a..) # => [(RangeExtd::Infinity::NEGATIVE...?a)]
|
255
|
+
r6 = ~~Rangeary(?a..) # => [(?a..RangeExtd::Infinity::POSITIVE)]
|
256
|
+
|
257
|
+
There is no reason for this operation to result in the (Ruby-2.6) Endless Range
|
258
|
+
that began with, after the negation operation from the negative infinity.
|
259
|
+
Nevertheless, +r1==r3+ and +r4==r6+ must hold.
|
260
|
+
|
261
|
+
+RangeExtd#==+ behaves in an almost identical way to +Range#==+
|
262
|
+
(except it has +exclude_begin+), such as,
|
263
|
+
|
264
|
+
(1.0..) != (1.0..Float::INFINITY)
|
265
|
+
RangeExtd(1.0..) != RangeExtd(1.0..Float::INFINITY)
|
266
|
+
|
267
|
+
To maintain the mathematical consistency, Rangeary needs modify the
|
268
|
+
equal operator so +r1==r3+ and +r4==r6+ hold, as the standard equal operator of Array would not do the job.
|
269
|
+
Hence, Rangeary now regards an Endless Range and a Range that ends with another Infinity
|
270
|
+
as equal, as long as all the other Range parameters like the "begin"
|
271
|
+
and +exclude_end+ are equal.
|
272
|
+
|
273
|
+
In practice, +Array#==+ is modified in
|
274
|
+
this library (which is naturally inherited to Rangeary), and hence the
|
275
|
+
commutativity of the equal operator is assured.
|
276
|
+
|
277
|
+
Note that +Rangeary#equiv+ method may behave differently from the equal operator.
|
278
|
+
For example,
|
279
|
+
|
280
|
+
Rangeary(RangeExtd(1,"<...",4), 5...8).equiv?(Rangeary(2..3, 5..7))
|
281
|
+
|
282
|
+
returns true. To describe this, this left and right Rangearies are arrays of
|
283
|
+
ranges of Integers which consist of
|
284
|
+
|
285
|
+
* (Left)
|
286
|
+
1. Range that starts at, but excluding, 1, ending at, but excluding 4
|
287
|
+
2. Range that starts at 5 (inclusive), ending at 8 (exclusive).
|
288
|
+
* (Right)
|
289
|
+
1. Range that starts and ending at 2 and 3, respectively, both inclusive.
|
290
|
+
2. Range that starts and ending at 5 and 7, respectively, both inclusive.
|
291
|
+
|
292
|
+
According to +Integer#succ+ (+Range#each+) method, the left and right ones are equivalent.
|
293
|
+
Therefore +Rangeary#equiv+ returns true, wheras the equal operator
|
294
|
+
returns false for this.
|
295
|
+
|
296
|
+
=== Infinities
|
297
|
+
|
298
|
+
The infinities are vital in the logical operation of Rangeary. In
|
299
|
+
default, the general infinities of
|
300
|
+
<tt>RangeExtd::Infinity::POSITIVE</tt> and <tt>RangeExtd::Infinity::NEGATIVE</tt>
|
301
|
+
are used (see ({RangeExtd}[http://rubygems.org/gems/range_extd] for
|
302
|
+
detail), except for comparable Numerics (Integer, Rational, Float
|
303
|
+
etc), for which +Float::INFINITY is used in default. However, a user
|
304
|
+
can specify their own infinities in initialisation with the options of
|
305
|
+
+positive:+ and +negative:+.
|
306
|
+
|
307
|
+
Note once an infinity is defined for a Rangeary object, any other
|
308
|
+
Rangeary objects with which operations are performed should have the
|
309
|
+
same infinities. In default, if different infinities are specified
|
310
|
+
(or if only one of them has a pair of specified infinities and the
|
311
|
+
others have the default values), the values that is smallest for the
|
312
|
+
Positive infinity and largest for the Negative are used, though a
|
313
|
+
warning may be issued (only if the built-in global variable +$VERBOSE+
|
314
|
+
is true). An exception is when a user explicitly specifies the infinities in the
|
315
|
+
option in creating a new Rangeary out of other Rangeary objects and else, in which case the infinities from the
|
316
|
+
other "inherited" Rangeary included in the main parameter are ignored.
|
317
|
+
|
318
|
+
The last example above shows how it works.
|
190
319
|
|
191
320
|
== Known bugs
|
192
321
|
|
193
322
|
* None is known.
|
194
323
|
|
195
|
-
This library requires Ruby 2.
|
324
|
+
This library requires Ruby 2.1 or above (it may work all right with
|
196
325
|
Ruby 1.9.3, however I have never tested it).
|
197
326
|
|
198
327
|
Extensive tests have been performed, as included in the package.
|
@@ -203,7 +332,7 @@ Extensive tests have been performed, as included in the package.
|
|
203
332
|
Nothing planned.
|
204
333
|
|
205
334
|
|
206
|
-
== Final
|
335
|
+
== Final comment
|
207
336
|
|
208
337
|
This work is inspired by Ian Stewart, who developped a (numeric)
|
209
338
|
multiple-range library in Fortran90 for the SAS software package for
|
@@ -212,7 +341,8 @@ XMM-Newton telescope. I appreciate his work.
|
|
212
341
|
The implementation to Ruby was not straightforward, though, partly
|
213
342
|
because the built-in Range does not allow to exclude the begin
|
214
343
|
boundary, and partly because the infinity is not defined for general
|
215
|
-
objects but Numeric (Real) in Ruby
|
344
|
+
objects but Numeric (Real) in Ruby (which later changed partially with
|
345
|
+
the introduction of Endless Range in Ruby 2.6 released in 2018 December). RangeExtd class I have developed
|
216
346
|
makes this library possible. I am glad the completeness of ranges in
|
217
347
|
the 1-dimensional space for arbitrary Comparable object is achieved now.
|
218
348
|
|
@@ -224,22 +354,22 @@ Enjoy.
|
|
224
354
|
|
225
355
|
== Copyright etc
|
226
356
|
|
227
|
-
Author:: Masa Sakano <
|
357
|
+
Author:: Masa Sakano < info a_t wisebabel dot com >
|
228
358
|
License:: MIT.
|
229
359
|
Warranty:: No warranty whatsoever.
|
230
360
|
Versions:: The versions of this package follow Semantic Versioning (2.0.0) http://semver.org/
|
231
361
|
|
232
|
-
|
362
|
+
-------------------------------------------
|
233
363
|
|
234
364
|
= Rangeary - 複数Range(Extd)クラス
|
235
365
|
|
236
|
-
このパッケージは、1次元の任意の数のレンジ({RangeExtd} オブジェクト)を
|
366
|
+
このパッケージは、1次元の任意の数のレンジ({RangeExtd}[http://rubygems.org/gems/range_extd] オブジェクト)を
|
237
367
|
保持する Rangeary クラスを定義しています。たとえば、<tt>x</tt> に
|
238
368
|
対する複数レンジの
|
239
369
|
0.5 < x <= 2.5, 6.0 <= x < 8.0, 10.0 <= x (<= 無限大)
|
240
370
|
がこのクラスで定義できます。
|
241
371
|
|
242
|
-
|
372
|
+
RangeExtd の要素たり得るオブジェクトは全て {Rangeary} の要素となり
|
243
373
|
得ます。Numeric(の実数)に限らず、Comparable であるオブジェクトは全て
|
244
374
|
可能です。また、{Rangeary} は、組込Rangeクラスのオブジェクトも初期化に
|
245
375
|
使えます。
|
@@ -253,7 +383,7 @@ Versions:: The versions of this package follow Semantic Versioning (2.0.0) http:
|
|
253
383
|
{Rangeary} オブジェクトはイミュータブルです。すなわち、
|
254
384
|
一度インスタンスが生成されると、要素を書換えることはできません。
|
255
385
|
|
256
|
-
実用的には、{Rangeary} は、Arrayのサブクラスとなっていて、
|
386
|
+
実用的には、{Rangeary} は、Arrayのサブクラスとなっていて、RangeExtd
|
257
387
|
の配列として振舞います。また、Arrayのほとんどのメソッドを継承していま
|
258
388
|
す。したがって、イミュータブルな{Rangeary}に許される限りにおいて、
|
259
389
|
Arrayに使えるほとんどの操作を{Rangeary}に適用できます。加えて、
|
@@ -267,7 +397,7 @@ Arrayに使えるほとんどの操作を{Rangeary}に適用できます。加
|
|
267
397
|
|
268
398
|
== インストール
|
269
399
|
|
270
|
-
まず、
|
400
|
+
まず、RangeExtd クラスのライブラリ(純粋に rubyで書かれたファイル 2個
|
271
401
|
です)が必要です。gem を使ってインストールできます。
|
272
402
|
gem install range_extd
|
273
403
|
もしくは以下から入手して下さい。
|
@@ -286,12 +416,10 @@ http://rubygems.org/gems/rangeary
|
|
286
416
|
require 'rangeary/rangeary'
|
287
417
|
とするだけです。もしくは、特に手でインストールした場合は、
|
288
418
|
require 'rangeary'
|
289
|
-
とする必要があるかも知れません。他のファイル(
|
419
|
+
とする必要があるかも知れません。他のファイル(RangeExtd 用の
|
290
420
|
<tt>range_extd/range_extd.rb</tt>)は、自動的に読込まれます。
|
291
421
|
|
292
|
-
{Rangeary}
|
293
|
-
{RangeExtd} が Ruby 2.0 (ひょっとしたら 1.9.3)以上でしか動かないため、
|
294
|
-
実質的には {Rangeary} は Ruby 1.8 以前のバージョンでは動作しません。
|
422
|
+
{Rangeary} は Ruby 2.1 以上で動きます。
|
295
423
|
|
296
424
|
お楽しみあれ!
|
297
425
|
|
@@ -309,8 +437,8 @@ http://rubygems.org/gems/rangeary
|
|
309
437
|
Rangeary(true..true) # => ArgumentError
|
310
438
|
|
311
439
|
基本的に、<tt>Rangeary()</tt> または <tt>Rangeary.new()</tt> は、任意
|
312
|
-
の数の
|
313
|
-
て取ります。ただし、
|
440
|
+
の数の Range、RangeExtd、{Rangeary} あるいはその組合わせを引数とし
|
441
|
+
て取ります。ただし、Rangeクラスのオブジェクトで +Range#valid?+ が偽
|
314
442
|
を返すものは、例外が発生します。
|
315
443
|
|
316
444
|
さらなる解説及び例は、{Rangeary.new}を参照して下さい。
|
@@ -333,9 +461,16 @@ http://rubygems.org/gems/rangeary
|
|
333
461
|
rb + Rangeary(3..7) # => [2...9]
|
334
462
|
rb - Rangeary(3..7) # => [2...3, RangeExtd(7,'<...',9)]
|
335
463
|
rb * Rangeary(4..5, 8..10) # => [4..4, 8...9]
|
336
|
-
rb
|
464
|
+
~rb # => [-Float::INFINITY...2, RangeExtd(4,'<...',6), 9..Float::INFINITY]
|
337
465
|
|
338
|
-
|
466
|
+
rc = Rangeary(?d...?x, negative: ?a, positive: ?z)
|
467
|
+
~rc # => [?a...?d, ?x..?z]
|
468
|
+
|
469
|
+
ここで、+~rb+ は +rb.negation+ と等価で論理否定を意味します。最後の例
|
470
|
+
では、ユーザー指定の*無限大/無限小*値を定義しています。
|
471
|
+
|
472
|
+
|
473
|
+
組込Arrayクラスに含まれるほとんどのメソッドが、たとえば+Array#push+のように
|
339
474
|
{Rangeary} がイミュータブルであることに抵触しない限りにおいて、使用可能です。
|
340
475
|
|
341
476
|
|
@@ -354,13 +489,13 @@ http://rubygems.org/gems/rangeary
|
|
354
489
|
す。だから、一度インスタンスが生成されると、変化しません。
|
355
490
|
|
356
491
|
インスタンスの生成方法は上述の通りです(「使用例」の章)。レンジとして"valid"と見
|
357
|
-
なされないインスタンスを生成しようとすると、すなわち
|
492
|
+
なされないインスタンスを生成しようとすると、すなわち +Range#valid?+ が
|
358
493
|
偽を返すレンジを使おうとすると、例外(<tt>ArgumentError</tt>)が発生し、
|
359
494
|
失敗します。
|
360
495
|
|
361
496
|
なお、ユーザーは、{Rangeary} インスタンス生成の時、レンジ要素に対応し
|
362
497
|
た正負の無限大オブジェクトを付加することができます。デフォルトでは、
|
363
|
-
|
498
|
+
+Float::INFINITY+ または +RangeExtd::Infinity::POSITIVE+ の類に
|
364
499
|
なります。詳しくは {Rangeary.new} を参照下さい。
|
365
500
|
|
366
501
|
生成時に複数のレンジが引数として与えられた時、ソートされて保持されます。
|
@@ -368,14 +503,14 @@ http://rubygems.org/gems/rangeary
|
|
368
503
|
(つまり、単純に足し合わされます)。これはつまり、{Rangeary} が内部的に
|
369
504
|
保持するオブジェクトは生成時に与えられたものとは異なる、すなわち
|
370
505
|
{#object_id} が異なるかも知れないことを意味します。特に、組込Rangeが引
|
371
|
-
数として与えられた時は、常に
|
506
|
+
数として与えられた時は、常に RangeExtd オブジェクトに内部で変換されます。
|
372
507
|
|
373
|
-
もし生成時に与えられたレンジのどれかが空、すなわち
|
508
|
+
もし生成時に与えられたレンジのどれかが空、すなわち +Range#empty?+ が真
|
374
509
|
を返す場合、それらは無視されます。ただし、引数の全てのレンジが空であっ
|
375
510
|
た場合は、「最小」のものが残されます。
|
376
511
|
|
377
512
|
もし演算の結果として空の{Rangeary}が返される場合、その唯一の要素は
|
378
|
-
|
513
|
+
+RangeExtd::NONE+となり、したがって
|
379
514
|
{Rangeary#empty_element?} が真を返します。
|
380
515
|
|
381
516
|
そのため、どの Rangeary オブジェクトも、{Rangeary#to_a}.size は常に正
|
@@ -386,14 +521,13 @@ http://rubygems.org/gems/rangeary
|
|
386
521
|
Rangeary(RangeExtd::NONE).empty_element? # => true
|
387
522
|
|
388
523
|
前述のように、ごく一部を除いた全ての Arrayクラスのメソッドがこの
|
389
|
-
{Rangeary} クラスに継承されていて、それらは各
|
524
|
+
{Rangeary} クラスに継承されていて、それらは各RangeExtd要素に対して
|
390
525
|
動作します。ただし、4個のメソッドの挙動が異なります。
|
391
526
|
{Rangeary#+} と {Rangeary#*} とは、それぞれ {Rangeary#disjunction} と
|
392
527
|
{Rangeary#conjunction} とへのエイリアスとなっています。{Rangeary#===}
|
393
|
-
は、全ての
|
528
|
+
は、全てのRangeExtd要素に対して+Range#===+を実行し、それらの一つでも
|
394
529
|
真を返せば真を返します。したがって、{Rangeary#===}(RangeExtd(**))は常
|
395
|
-
に偽を返します。
|
396
|
-
{Rangeary#to_a} を実行して、その結果を結合した配列を返します。
|
530
|
+
に偽を返します。
|
397
531
|
また、[#length] と [#reverse] とは未定義化されています。
|
398
532
|
|
399
533
|
{Rangeary#==} と {Rangeary#eql?} は、Arrayと同様に動作します。だから
|
@@ -407,19 +541,131 @@ http://rubygems.org/gems/rangeary
|
|
407
541
|
レンジ要素に対してではなく、レンジを構成する要素に対して動作する他の
|
408
542
|
全てのメソッドは、組込Arrayクラスに同名のメソッドが存在する場合、接尾辞
|
409
543
|
<tt>_element</tt> がつきます。たとえば、{Rangeary#size} は、保持する
|
410
|
-
|
411
|
-
保持するすべての
|
544
|
+
RangeExtd オブジェクトの数を返し、一方、{Rangeary#size_element}は、
|
545
|
+
保持するすべての RangeExtdオブジェクトに対して +Range#size+ を行った
|
412
546
|
その総和を返します。
|
413
547
|
Rangeary(1..3, 5..8).size # => 2
|
414
548
|
Rangeary(1..3, 5..8).size_element # => 7
|
415
549
|
|
550
|
+
{Rangeary#flatten_element} は、全てのRangeExtd要素に対して
|
551
|
+
{Rangeary#to_a} を実行して、その結果を結合した配列を返します。
|
552
|
+
|
553
|
+
クラスとメソッドの完全なマニュアルは、
|
554
|
+
{Rubygems のウェブサイト}[http://rubygems.org/gems/rangeary]上にあります。
|
555
|
+
あるいは、ソースパッケージを展開して、ルートディレクトリで +make doc+
|
556
|
+
することで、手元でコンパイルすることもできます(RubyGems の +yard+
|
557
|
+
がインストールされている必要があります)。
|
558
|
+
|
559
|
+
=== Array#==
|
560
|
+
|
561
|
+
等号メソッド +Rangeary#==+ は、Array とは異なった挙動をするべきであり、
|
562
|
+
実際します。まず、*empty?* の際の意味が、異なります。なぜならば、
|
563
|
+
Rangeary オブジェクトは、Array的な意味では、empty になることは決してな
|
564
|
+
いからです。次に、Ruby 2.6で導入された
|
565
|
+
{Endless Range}[https://rubyreferences.github.io/rubychanges/2.6.html#endless-range-1]
|
566
|
+
は、概念的にそう素直には組み込まれません。例えば、Ruby 2.6 では以下の
|
567
|
+
ような挙動を示します。
|
568
|
+
|
569
|
+
(?a..).size # => nil
|
570
|
+
(10..).size # => Infinity
|
571
|
+
(10..Float::INFINITY)).size # => Infinity
|
572
|
+
(1.0..) != (1.0..Float::INFINITY)
|
573
|
+
|
574
|
+
これらは、当たり前の挙動ではありませんし、若干矛盾があるとさえ言えるかも
|
575
|
+
知れません。Range#size メソッドに関しては、Numericクラス(Complexを除く)
|
576
|
+
のオブジェクトに関しては、Endless Range は、数学的無限のように振舞いま
|
577
|
+
す。しかし、両者を比較することはできず、等号比較すると、偽が返ります。
|
578
|
+
|
579
|
+
Rangeary は、複数の Range からなる数列(array)に対して、論理演算する機
|
580
|
+
能を提供します。そのためには、一貫した「無限」の定義が不可欠です。例え
|
581
|
+
ば、 +[5..Infinity]+ の否定は、
|
582
|
+
|
583
|
+
[-Infinity...5]
|
584
|
+
|
585
|
+
すなわち、無限小から始まり、5 で終わるが、終端は含まれない、ということ
|
586
|
+
になります。これに対して再度否定演算を行うと、元の Rangeary +(5..Infinity)+
|
587
|
+
が再度得られなければなりません。
|
588
|
+
|
589
|
+
この演算は、当然、+Endless Range+ だけでは不可能です。+Endless Range+
|
590
|
+
は正の無限大、あるいは正確には、正の方向に開いたもの、しか定義していないからです。
|
591
|
+
このため、+RangeExtd+ を使用することは、Rangeary では決定的に重要なの
|
592
|
+
です。
|
593
|
+
|
594
|
+
Rangearyの演算(ここでは否定演算)においては、以下のようになります。
|
595
|
+
|
596
|
+
r1 = Rangeary(5..) # => [(5..)] (equivalent to (5..nil))
|
597
|
+
r2 = ~Rangeary(5..) # => [(-Float::INFINITY...5)]
|
598
|
+
r3 = ~~Rangeary(5..) # => [(5..Float::INFINITY)]
|
599
|
+
|
600
|
+
r4 = Rangeary(?a..) # => [(?a..)] (equivalent to (?a..nil))
|
601
|
+
r5 = ~Rangeary(?a..) # => [(RangeExtd::Infinity::NEGATIVE...?a)]
|
602
|
+
r6 = ~~Rangeary(?a..) # => [(?a..RangeExtd::Infinity::POSITIVE)]
|
603
|
+
|
604
|
+
この演算において、負の無限大も経過した最後の結果が、元々の出発点である(Ruby2.6で言う)
|
605
|
+
Endless Rangeにならなければいけない理由はないことになります。しかしながら、
|
606
|
+
+r1==r3+ および +r4==r6+ は成立すべきです。
|
607
|
+
|
608
|
+
+RangeExtd#==+ は、+Range#==+ とほぼ同一に振舞います(前者は
|
609
|
+
+exclude_begin+ メソッドを持つことを除いて)。例えば、
|
610
|
+
|
611
|
+
(1.0..) != (1.0..Float::INFINITY)
|
612
|
+
RangeExtd(1.0..) != RangeExtd(1.0..Float::INFINITY)
|
613
|
+
|
614
|
+
+r1==r3+ や +r4==r6+ も成立するよう、数学的一貫性を保つために、Rangeary では、
|
615
|
+
等号の定義を変更する必要がありました。Array クラスのデフォルトの標準等
|
616
|
+
号ではダメだからです。
|
617
|
+
そこで、Rangeary では、Endless Range と終端が何か別の無限大である
|
618
|
+
Rangeとは、他のパラメーター(例えば始端や+exclude_end+)が等しい限り、等
|
619
|
+
しいと見なします。
|
620
|
+
|
621
|
+
実装としては、本ライブラリ内で +Array#==+ (Rangearyに自然に継承される)を変更しています。
|
622
|
+
そのため、等号の可換性が保たれています。
|
623
|
+
|
624
|
+
なお、+Rangeary#equiv+ メソッドは、等号とは異なる挙動をすることがあり
|
625
|
+
ます。例えば、
|
626
|
+
|
627
|
+
Rangeary(RangeExtd(1,"<...",4), 5...8).equiv?(Rangeary(2..3, 5..7))
|
628
|
+
|
629
|
+
は真になります。以下のような説明になります。左右の Rangearyは、整数の
|
630
|
+
Rangeからなる配列で、
|
631
|
+
|
632
|
+
* (左側の Rangeary)
|
633
|
+
1. 始端が1 (但し始端自体は含まない)で、終端が4 (但し終端自体は含まない)
|
634
|
+
2. 始端が5 (始端を含む)で、終端が8 (但し終端自体は含まない)
|
635
|
+
* (右側の Rangeary)
|
636
|
+
1. 始端が2、終端が3 (両端を含む)
|
637
|
+
2. 始端が5、終端が7 (両端を含む)
|
638
|
+
|
639
|
+
+Integer#succ+ (あるいは、+Range#each+)メソッド的には、左側と右側とは等価です。したがって、
|
640
|
+
+Rangeary#equiv+ でこの両者を比較すると真を返します。一方、等号は負を
|
641
|
+
返します。
|
642
|
+
|
643
|
+
=== 無限大
|
644
|
+
|
645
|
+
正負の無限大は、Rangearyの演算に不可欠です。デフォルトでは、正負の一般無限大は
|
646
|
+
<tt>RangeExtd::Infinity::POSITIVE</tt> と <tt>RangeExtd::Infinity::NEGATIVE</tt>
|
647
|
+
が使われます(詳細は {RangeExtd}[http://rubygems.org/gems/range_extd] 参照)。
|
648
|
+
但し、例外が、比較可能な Numerics (Integer, Rational, Floatなど)で、
|
649
|
+
+Float::INFINITY がデフォルトで使われます。しかし、ユーザーは、オブジェ
|
650
|
+
クト作成の時、+positive:+ および +negative:+ で自分の無限大を定義することもできます。
|
651
|
+
|
652
|
+
なお、一旦、無限大が定義されると、そのオブジェクトと演算を行う全ての
|
653
|
+
Rangearyオブジェクトも同じ無限大をもつべきです。デフォルトでは、演算す
|
654
|
+
るオブジェクト間でもし異なる無限大が使われている場合(端的には、一つの
|
655
|
+
オブジェクトにだけ無限大を定義して他はデフォルトで済ませている場合)は、
|
656
|
+
正の無限大には最小の値、負の無限大には最大の値が選ばれます。但し、警告
|
657
|
+
メッセージが出るかもしれません(組込グローバル変数 +$VERBOSE+が真の時のみ)。
|
658
|
+
例外は、複数のRangearyから新しいRangeryオブジェクトを作成の際に、オプ
|
659
|
+
ションで陽に無限大を指定した時で、その時は、それらRangearyから継承した
|
660
|
+
値は考慮されず、指定した値が使われます。
|
661
|
+
|
662
|
+
上記の最後の例が、指定する例です。
|
416
663
|
|
417
664
|
== 既知のバグ
|
418
665
|
|
419
666
|
* 無し。
|
420
667
|
|
421
|
-
このライブラリは Ruby 2.
|
422
|
-
知れませんが、私は試したことがありません)。
|
668
|
+
このライブラリは Ruby 2.1 以上を必要とします。
|
423
669
|
|
424
670
|
パッケージに含まれている通り、網羅的なテストが実行されています。
|
425
671
|
|
@@ -438,7 +684,7 @@ Fortran90ライブラリにアイデアを得たものです。彼の仕事に
|
|
438
684
|
しかし、Rubyへの実装は、一筋縄ではいきませんでした。一つには組込Range
|
439
685
|
クラスでは始点を除外することができないこと、また一つには Rubyでは数値
|
440
686
|
を除いて一般オブジェクトに対しての無限大が定義されていないからです。
|
441
|
-
小生の開発した
|
687
|
+
小生の開発した RangeExtd によって初めてこのライブラリが可能となりま
|
442
688
|
した。これにより、今、比較可能な任意のオブジェクトについて、1次元上の
|
443
689
|
レンジの完全性が実現できたことを嬉しく思います。
|
444
690
|
|
@@ -449,7 +695,7 @@ Fortran90ライブラリにアイデアを得たものです。彼の仕事に
|
|
449
695
|
|
450
696
|
== 著作権他情報
|
451
697
|
|
452
|
-
著者:: Masa Sakano <
|
698
|
+
著者:: Masa Sakano < info a_t wisebabel dot com >
|
453
699
|
利用許諾条項:: MIT.
|
454
700
|
保証:: 一切無し。
|
455
701
|
バージョン:: Semantic Versioning (2.0.0) http://semver.org/
|