When I turned each, I did nothing and did not get an error, and I was addicted to it because the processing continued as it was, so I made a memorandum.
Instances can be created without problems in either case of start point <end point, start point> end point.
aaa = Range.new(1,5)
=> 1..5
bbb = 1..5
=> 1..5
ccc = Range.new(5,1)
=> 5..1
ddd = 5..1
=> 5..1
Range#each
The problem is when you turn each in the Range generated in reverse order.
aaa.each {|i| puts i}
1
2
3
4
5
=> 1..5
ccc.each {|i|puts i}
=> 5..1
According to Rurima, Range # each is iterated with succ. https://docs.ruby-lang.org/ja/latest/method/Range/i/each.html
Looking at the description of succ for Integer, it seems that it simply returns the next integer.
aaa.begin.class
=> Integer
https://docs.ruby-lang.org/ja/2.5.0/method/Integer/i/next.html
aaa.begin
=> 1
aaa.begin.succ
=> 2
ccc.begin
=> 5
ccc.begin.succ
=> 6
Probably static VALUE range_each (VALUE range) is called, and since the while condition is not satisfied after that, it seems that the processing is completed without looping even one lap.
https://github.com/ruby/ruby/blob/trunk/range.c#L833
static VALUE
range_each(VALUE range)
{
//...abridgement
if (!NIL_P(end))
range_each_func(range, each_i, 0);
else
for (;; beg = rb_funcallv(beg, id_succ, 0, 0))
rb_yield(beg);
//...abridgement
}
https://github.com/ruby/ruby/blob/trunk/range.c#L239
static void
range_each_func(VALUE range, int (*func)(VALUE, VALUE), VALUE arg)
{
int c;
VALUE b = RANGE_BEG(range);
VALUE e = RANGE_END(range);
VALUE v = b;
if (EXCL(range)) {
while (r_less(v, e) < 0) {
if ((*func)(v, arg)) break;
v = rb_funcallv(v, id_succ, 0, 0);
}
}
else {
while ((c = r_less(v, e)) <= 0) {
if ((*func)(v, arg)) break;
if (!c) break;
v = rb_funcallv(v, id_succ, 0, 0);
}
}
}
https://github.com/ruby/ruby/blob/trunk/range.c#L157
/* compares _a_ and _b_ and returns:
* < 0: a < b
* = 0: a = b
* > 0: a > b or non-comparable
*/
static int
r_less(VALUE a, VALUE b)
{
VALUE r = rb_funcall(a, id_cmp, 1, b);
if (NIL_P(r))
return INT_MAX;
return rb_cmpint(r, a, b);
}
Recommended Posts