Class: Range
Instance Method Summary collapse
-
#==(obj) ⇒ Boolean
Returns
true
only if obj is a Range, has equivalent beginning and end items (by comparing them with==
), and has the same #exclude_end? setting as <i>rng</t>. -
#=== ⇒ Object
Returns
true
if obj is an element of rng,false
otherwise. -
#begin ⇒ Object
Returns the first object in rng.
-
#each {|i| ... } ⇒ Object
Iterates over the elements rng, passing each in turn to the block.
-
#end ⇒ Object
Returns the object that defines the end of rng.
-
#eql?(obj) ⇒ Boolean
Returns
true
only if obj is a Range, has equivalent beginning and end items (by comparing them with #eql?), and has the same #exclude_end? setting as rng. -
#exclude_end? ⇒ Boolean
Returns
true
if rng excludes its end value. -
#first ⇒ Object
Returns the first object in rng.
-
#hash ⇒ Fixnum
Generate a hash value such that two ranges with the same start and end points, and the same value for the "exclude end" flag, generate the same hash value.
-
#include? ⇒ Object
Returns
true
if obj is an element of rng,false
otherwise. -
#new(start, end) ⇒ Object
constructor
Constructs a range using the given start and end.
-
#inspect ⇒ String
Convert this range object to a printable form (using
inspect
to convert the start and end objects). -
#last ⇒ Object
Returns the object that defines the end of rng.
-
#member? ⇒ Object
Returns
true
if obj is an element of rng,false
otherwise. -
#step(n = 1) {|obj| ... } ⇒ Object
Iterates over rng, passing each nth element to the block.
-
#to_s ⇒ String
Convert this range object to a printable form.
Methods included from Enumerable
#all?, #any?, #collect, #count, #cycle, #detect, #drop, #drop_while, #each_cons, #each_slice, #each_with_index, #entries, #enum_cons, #enum_slice, #enum_with_index, #find, #find_all, #find_index, #grep, #group_by, #inject, #map, #max, #max_by, #min, #min_by, #minmax, #minmax_by, #none?, #one?, #partition, #reduce, #reject, #reverse_each, #select, #sort, #sort_by, #take, #take_while, #to_a, #zip
Constructor Details
#new(start, end) ⇒ Object
Constructs a range using the given start and end. If the third parameter is omitted or is false
, the range will include the end object; otherwise, it will be excluded.
|
# File 'range.c'
/*
* call-seq:
* Range.new(start, end, exclusive=false) => range
*
* Constructs a range using the given <i>start</i> and <i>end</i>. If the third
* parameter is omitted or is <code>false</code>, the <i>range</i> will include
* the end object; otherwise, it will be excluded.
*/
static VALUE
range_initialize(argc, argv, range)
int argc;
VALUE *argv;
VALUE range;
{
VALUE beg, end, flags;
rb_scan_args(argc, argv, "21", &beg, &end, &flags);
/* Ranges are immutable, so that they should be initialized only once. */
if (rb_ivar_defined(range, id_beg)) {
rb_name_error(rb_intern("initialize"), "`initialize' called twice");
}
range_init(range, beg, end, RTEST(flags));
return Qnil;
}
|
Instance Method Details
#==(obj) ⇒ Boolean
Returns true
only if obj is a Range, has equivalent beginning and end items (by comparing them with ==
), and has the same #exclude_end? setting as <i>rng</t>.
(0..2) == (0..2) #=> true
(0..2) == Range.new(0,2) #=> true
(0..2) == (0...2) #=> false
|
# File 'range.c'
/*
* call-seq:
* rng == obj => true or false
*
* Returns <code>true</code> only if <i>obj</i> is a Range, has equivalent
* beginning and end items (by comparing them with <code>==</code>), and has
* the same #exclude_end? setting as <i>rng</t>.
*
* (0..2) == (0..2) #=> true
* (0..2) == Range.new(0,2) #=> true
* (0..2) == (0...2) #=> false
*
*/
static VALUE
range_eq(range, obj)
VALUE range, obj;
{
if (range == obj) return Qtrue;
if (!rb_obj_is_instance_of(obj, rb_obj_class(range)))
return Qfalse;
if (!rb_equal(rb_ivar_get(range, id_beg), rb_ivar_get(obj, id_beg)))
return Qfalse;
if (!rb_equal(rb_ivar_get(range, id_end), rb_ivar_get(obj, id_end)))
return Qfalse;
if (EXCL(range) != EXCL(obj)) return Qfalse;
return Qtrue;
}
|
#===(obj) ⇒ Boolean #member?(val) ⇒ Boolean #include?(val) ⇒ Boolean
Returns true
if obj is an element of rng, false
otherwise. Conveniently, ===
is the comparison operator used by case
statements.
case 79
when 1..50 then print "low\n"
when 51..75 then print "medium\n"
when 76..100 then print "high\n"
end
produces:
high
|
# File 'range.c'
/*
* call-seq:
* rng === obj => true or false
* rng.member?(val) => true or false
* rng.include?(val) => true or false
*
* Returns <code>true</code> if <i>obj</i> is an element of
* <i>rng</i>, <code>false</code> otherwise. Conveniently,
* <code>===</code> is the comparison operator used by
* <code>case</code> statements.
*
* case 79
* when 1..50 then print "low\n"
* when 51..75 then print "medium\n"
* when 76..100 then print "high\n"
* end
*
* <em>produces:</em>
*
* high
*/
static VALUE
range_include(range, val)
VALUE range, val;
{
VALUE beg, end;
beg = rb_ivar_get(range, id_beg);
end = rb_ivar_get(range, id_end);
if (r_le(beg, val)) {
if (EXCL(range)) {
if (r_lt(val, end)) return Qtrue;
}
else {
if (r_le(val, end)) return Qtrue;
}
}
return Qfalse;
}
|
#first ⇒ Object #begin ⇒ Object
Returns the first object in rng.
|
# File 'range.c'
/*
* call-seq:
* rng.first => obj
* rng.begin => obj
*
* Returns the first object in <i>rng</i>.
*/
static VALUE
range_first(range)
VALUE range;
{
return rb_ivar_get(range, id_beg);
}
|
#each {|i| ... } ⇒ Object
Iterates over the elements rng, passing each in turn to the block. You can only iterate if the start object of the range supports the succ
method (which means that you can't iterate over ranges of Float
objects).
(10..15).each do |n|
print n, ' '
end
produces:
10 11 12 13 14 15
|
# File 'range.c'
/*
* call-seq:
* rng.each {| i | block } => rng
*
* Iterates over the elements <i>rng</i>, passing each in turn to the
* block. You can only iterate if the start object of the range
* supports the +succ+ method (which means that you can't iterate over
* ranges of +Float+ objects).
*
* (10..15).each do |n|
* print n, ' '
* end
*
* <em>produces:</em>
*
* 10 11 12 13 14 15
*/
static VALUE
range_each(range)
VALUE range;
{
VALUE beg, end;
RETURN_ENUMERATOR(range, 0, 0);
beg = rb_ivar_get(range, id_beg);
end = rb_ivar_get(range, id_end);
if (!rb_respond_to(beg, id_succ)) {
rb_raise(rb_eTypeError, "can't iterate from %s",
rb_obj_classname(beg));
}
if (FIXNUM_P(beg) && FIXNUM_P(end)) { /* fixnums are special */
long lim = FIX2LONG(end);
long i;
if (!EXCL(range)) lim += 1;
for (i=FIX2LONG(beg); i<lim; i++) {
rb_yield(LONG2NUM(i));
}
}
else if (TYPE(beg) == T_STRING) {
VALUE args[5], iter[2];
args[0] = beg; args[1] = end; args[2] = range;
iter[0] = INT2FIX(1); iter[1] = INT2FIX(1);
rb_iterate((VALUE(*)_((VALUE)))str_step, (VALUE)args, step_i,
(VALUE)iter);
}
else {
range_each_func(range, each_i, beg, end, NULL);
}
return range;
}
|
#end ⇒ Object #last ⇒ Object
Returns the object that defines the end of rng.
(1..10).end #=> 10
(1...10).end #=> 10
|
# File 'range.c'
/*
* call-seq:
* rng.end => obj
* rng.last => obj
*
* Returns the object that defines the end of <i>rng</i>.
*
* (1..10).end #=> 10
* (1...10).end #=> 10
*/
static VALUE
range_last(range)
VALUE range;
{
return rb_ivar_get(range, id_end);
}
|
#eql?(obj) ⇒ Boolean
Returns true
only if obj is a Range, has equivalent beginning and end items (by comparing them with #eql?), and has the same #exclude_end? setting as rng.
(0..2) == (0..2) #=> true
(0..2) == Range.new(0,2) #=> true
(0..2) == (0...2) #=> false
|
# File 'range.c'
/*
* call-seq:
* rng.eql?(obj) => true or false
*
* Returns <code>true</code> only if <i>obj</i> is a Range, has equivalent
* beginning and end items (by comparing them with #eql?), and has the same
* #exclude_end? setting as <i>rng</i>.
*
* (0..2) == (0..2) #=> true
* (0..2) == Range.new(0,2) #=> true
* (0..2) == (0...2) #=> false
*
*/
static VALUE
range_eql(range, obj)
VALUE range, obj;
{
if (range == obj) return Qtrue;
if (!rb_obj_is_instance_of(obj, rb_obj_class(range)))
return Qfalse;
if (!rb_eql(rb_ivar_get(range, id_beg), rb_ivar_get(obj, id_beg)))
return Qfalse;
if (!rb_eql(rb_ivar_get(range, id_end), rb_ivar_get(obj, id_end)))
return Qfalse;
if (EXCL(range) != EXCL(obj)) return Qfalse;
return Qtrue;
}
|
#exclude_end? ⇒ Boolean
Returns true
if rng excludes its end value.
|
# File 'range.c'
/*
* call-seq:
* rng.exclude_end? => true or false
*
* Returns <code>true</code> if <i>rng</i> excludes its end value.
*/
static VALUE
range_exclude_end_p(range)
VALUE range;
{
return EXCL(range) ? Qtrue : Qfalse;
}
|
#first ⇒ Object #begin ⇒ Object
Returns the first object in rng.
|
# File 'range.c'
/*
* call-seq:
* rng.first => obj
* rng.begin => obj
*
* Returns the first object in <i>rng</i>.
*/
static VALUE
range_first(range)
VALUE range;
{
return rb_ivar_get(range, id_beg);
}
|
#hash ⇒ Fixnum
Generate a hash value such that two ranges with the same start and end points, and the same value for the "exclude end" flag, generate the same hash value.
|
# File 'range.c'
/*
* call-seq:
* rng.hash => fixnum
*
* Generate a hash value such that two ranges with the same start and
* end points, and the same value for the "exclude end" flag, generate
* the same hash value.
*/
static VALUE
range_hash(range)
VALUE range;
{
long hash = EXCL(range);
VALUE v;
v = rb_hash(rb_ivar_get(range, id_beg));
hash ^= v << 1;
v = rb_hash(rb_ivar_get(range, id_end));
hash ^= v << 9;
hash ^= EXCL(range) << 24;
return LONG2FIX(hash);
}
|
#===(obj) ⇒ Boolean #member?(val) ⇒ Boolean #include?(val) ⇒ Boolean
Returns true
if obj is an element of rng, false
otherwise. Conveniently, ===
is the comparison operator used by case
statements.
case 79
when 1..50 then print "low\n"
when 51..75 then print "medium\n"
when 76..100 then print "high\n"
end
produces:
high
|
# File 'range.c'
/*
* call-seq:
* rng === obj => true or false
* rng.member?(val) => true or false
* rng.include?(val) => true or false
*
* Returns <code>true</code> if <i>obj</i> is an element of
* <i>rng</i>, <code>false</code> otherwise. Conveniently,
* <code>===</code> is the comparison operator used by
* <code>case</code> statements.
*
* case 79
* when 1..50 then print "low\n"
* when 51..75 then print "medium\n"
* when 76..100 then print "high\n"
* end
*
* <em>produces:</em>
*
* high
*/
static VALUE
range_include(range, val)
VALUE range, val;
{
VALUE beg, end;
beg = rb_ivar_get(range, id_beg);
end = rb_ivar_get(range, id_end);
if (r_le(beg, val)) {
if (EXCL(range)) {
if (r_lt(val, end)) return Qtrue;
}
else {
if (r_le(val, end)) return Qtrue;
}
}
return Qfalse;
}
|
#inspect ⇒ String
Convert this range object to a printable form (using inspect
to convert the start and end objects).
|
# File 'range.c'
/*
* call-seq:
* rng.inspect => string
*
* Convert this range object to a printable form (using
* <code>inspect</code> to convert the start and end
* objects).
*/
static VALUE
range_inspect(range)
VALUE range;
{
VALUE str, str2;
str = rb_inspect(rb_ivar_get(range, id_beg));
str2 = rb_inspect(rb_ivar_get(range, id_end));
str = rb_str_dup(str);
rb_str_cat(str, "...", EXCL(range)?3:2);
rb_str_append(str, str2);
OBJ_INFECT(str, str2);
return str;
}
|
#end ⇒ Object #last ⇒ Object
Returns the object that defines the end of rng.
(1..10).end #=> 10
(1...10).end #=> 10
|
# File 'range.c'
/*
* call-seq:
* rng.end => obj
* rng.last => obj
*
* Returns the object that defines the end of <i>rng</i>.
*
* (1..10).end #=> 10
* (1...10).end #=> 10
*/
static VALUE
range_last(range)
VALUE range;
{
return rb_ivar_get(range, id_end);
}
|
#===(obj) ⇒ Boolean #member?(val) ⇒ Boolean #include?(val) ⇒ Boolean
Returns true
if obj is an element of rng, false
otherwise. Conveniently, ===
is the comparison operator used by case
statements.
case 79
when 1..50 then print "low\n"
when 51..75 then print "medium\n"
when 76..100 then print "high\n"
end
produces:
high
|
# File 'range.c'
/*
* call-seq:
* rng === obj => true or false
* rng.member?(val) => true or false
* rng.include?(val) => true or false
*
* Returns <code>true</code> if <i>obj</i> is an element of
* <i>rng</i>, <code>false</code> otherwise. Conveniently,
* <code>===</code> is the comparison operator used by
* <code>case</code> statements.
*
* case 79
* when 1..50 then print "low\n"
* when 51..75 then print "medium\n"
* when 76..100 then print "high\n"
* end
*
* <em>produces:</em>
*
* high
*/
static VALUE
range_include(range, val)
VALUE range, val;
{
VALUE beg, end;
beg = rb_ivar_get(range, id_beg);
end = rb_ivar_get(range, id_end);
if (r_le(beg, val)) {
if (EXCL(range)) {
if (r_lt(val, end)) return Qtrue;
}
else {
if (r_le(val, end)) return Qtrue;
}
}
return Qfalse;
}
|
#step(n = 1) {|obj| ... } ⇒ Object
Iterates over rng, passing each nth element to the block. If the range contains numbers, n is added for each iteration. Otherwise step
invokes succ
to iterate through range elements. The following code uses class Xs
, which is defined in the class-level documentation.
range = Xs.new(1)..Xs.new(10)
range.step(2) {|x| puts x}
range.step(3) {|x| puts x}
produces:
1 x
3 xxx
5 xxxxx
7 xxxxxxx
9 xxxxxxxxx
1 x
4 xxxx
7 xxxxxxx
10 xxxxxxxxxx
|
# File 'range.c'
/*
* call-seq:
* rng.step(n=1) {| obj | block } => rng
*
* Iterates over <i>rng</i>, passing each <i>n</i>th element to the block. If
* the range contains numbers, <i>n</i> is added for each iteration. Otherwise
* <code>step</code> invokes <code>succ</code> to iterate through range
* elements. The following code uses class <code>Xs</code>, which is defined
* in the class-level documentation.
*
* range = Xs.new(1)..Xs.new(10)
* range.step(2) {|x| puts x}
* range.step(3) {|x| puts x}
*
* <em>produces:</em>
*
* 1 x
* 3 xxx
* 5 xxxxx
* 7 xxxxxxx
* 9 xxxxxxxxx
* 1 x
* 4 xxxx
* 7 xxxxxxx
* 10 xxxxxxxxxx
*/
static VALUE
range_step(argc, argv, range)
int argc;
VALUE *argv;
VALUE range;
{
VALUE b, e, step, tmp;
RETURN_ENUMERATOR(range, argc, argv);
b = rb_ivar_get(range, id_beg);
e = rb_ivar_get(range, id_end);
if (argc == 0) {
step = INT2FIX(1);
}
else {
rb_scan_args(argc, argv, "01", &step);
if (!rb_obj_is_kind_of(step, rb_cNumeric)) {
step = rb_to_int(step);
}
if (rb_funcall(step, '<', 1, INT2FIX(0))) {
rb_raise(rb_eArgError, "step can't be negative");
}
else if (!rb_funcall(step, '>', 1, INT2FIX(0))) {
rb_raise(rb_eArgError, "step can't be 0");
}
}
if (FIXNUM_P(b) && FIXNUM_P(e) && FIXNUM_P(step)) { /* fixnums are special */
long end = FIX2LONG(e);
long i, unit = FIX2LONG(step);
if (!EXCL(range))
end += 1;
i = FIX2LONG(b);
while (i < end) {
rb_yield(LONG2NUM(i));
if (i + unit < i) break;
i += unit;
}
}
else if (ruby_float_step(b, e, step, EXCL(range))) {
/* done */
}
else if (rb_obj_is_kind_of(b, rb_cNumeric) ||
!NIL_P(rb_check_to_integer(b, "to_int")) ||
!NIL_P(rb_check_to_integer(e, "to_int"))) {
ID op = EXCL(range) ? '<' : rb_intern("<=");
while (RTEST(rb_funcall(b, op, 1, e))) {
rb_yield(b);
b = rb_funcall(b, '+', 1, step);
}
}
else {
tmp = rb_check_string_type(b);
if (!NIL_P(tmp)) {
VALUE args[5], iter[2];
b = tmp;
args[0] = e;
args[1] = EXCL(range) ? Qtrue : Qfalse;
iter[0] = INT2FIX(1);
iter[1] = step;
rb_block_call(b, rb_intern("upto"), 2, args, step_i, (VALUE)iter);
}
else if (rb_obj_is_kind_of(b, rb_cNumeric) ||
!NIL_P(rb_check_to_integer(b, "to_int")) ||
!NIL_P(rb_check_to_integer(e, "to_int"))) {
ID c = EXCL(range) ? '<' : rb_intern("<=");
while (RTEST(rb_funcall(b, c, 1, e))) {
rb_yield(b);
b = rb_funcall(b, '+', 1, step);
}
}
else {
VALUE args[2];
if (!rb_respond_to(b, id_succ)) {
rb_raise(rb_eTypeError, "can't iterate from %s",
rb_obj_classname(b));
}
args[0] = INT2FIX(1);
args[1] = step;
range_each_func(range, step_i, b, e, args);
}
}
return range;
}
|
#to_s ⇒ String
Convert this range object to a printable form.
|
# File 'range.c'
/*
* call-seq:
* rng.to_s => string
*
* Convert this range object to a printable form.
*/
static VALUE
range_to_s(range)
VALUE range;
{
VALUE str, str2;
str = rb_obj_as_string(rb_ivar_get(range, id_beg));
str2 = rb_obj_as_string(rb_ivar_get(range, id_end));
str = rb_str_dup(str);
rb_str_cat(str, "...", EXCL(range)?3:2);
rb_str_append(str, str2);
OBJ_INFECT(str, str2);
return str;
}
|