Class: Range

Inherits:
Object show all
Includes:
Enumerable
Defined in:
mruby/mrblib/range.rb,
mruby/src/range.c,
mruby/mrbgems/mruby-range-ext/mrblib/range.rb

Overview

Range

ISO 15.2.14

Constant Summary

Constants included from Enumerable

Enumerable::NONE

Instance Method Summary collapse

Methods included from Enumerable

__update_hash, #all?, #any?, #chain, #collect, #count, #cycle, #detect, #drop, #drop_while, #each_cons, #each_slice, #each_with_index, #each_with_object, #filter_map, #find_all, #find_index, #flat_map, #grep, #group_by, #inject, #lazy, #max_by, #min_by, #minmax, #minmax_by, #none?, #one?, #partition, #reject, #reverse_each, #sort, #sort_by, #sum, #take, #take_while, #tally, #to_h, #uniq, #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.



160
161
162
163
164
165
166
167
168
169
170
# File 'mruby/src/range.c', line 160

static mrb_value
range_initialize(mrb_state *mrb, mrb_value range)
{
  mrb_value beg, end;
  mrb_bool exclusive = FALSE;

  mrb_get_args(mrb, "oo|b", &beg, &end, &exclusive);
  range_ptr_replace(mrb, mrb_range_raw_ptr(range), beg, end, exclusive);
  mrb_obj_freeze(mrb, range);
  return range;
}

Instance Method Details

#==(obj) ⇒ Boolean

Returns true only if 1) obj is a Range, 2) obj has equivalent beginning and end items (by comparing them with ==), 3) obj 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

Returns:

  • (Boolean)


185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
# File 'mruby/src/range.c', line 185

static mrb_value
range_eq(mrb_state *mrb, mrb_value range)
{
  struct RRange *rr;
  struct RRange *ro;
  mrb_value obj = mrb_get_arg1(mrb);
  mrb_bool v1, v2;

  if (mrb_obj_equal(mrb, range, obj)) return mrb_true_value();
  if (!mrb_obj_is_instance_of(mrb, obj, mrb_obj_class(mrb, range))) { /* same class? */
    return mrb_false_value();
  }

  rr = mrb_range_ptr(mrb, range);
  ro = mrb_range_ptr(mrb, obj);
  v1 = mrb_equal(mrb, RANGE_BEG(rr), RANGE_BEG(ro));
  v2 = mrb_equal(mrb, RANGE_END(rr), RANGE_END(ro));
  if (!v1 || !v2 || RANGE_EXCL(rr) != RANGE_EXCL(ro)) {
    return mrb_false_value();
  }
  return mrb_true_value();
}

#===(obj) ⇒ Boolean #member?(val) ⇒ Boolean #include?(val) ⇒ Boolean

Overloads:

  • #===(obj) ⇒ Boolean

    Returns:

    • (Boolean)
  • #member?(val) ⇒ Boolean

    Returns:

    • (Boolean)
  • #include?(val) ⇒ Boolean

    Returns:

    • (Boolean)


214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
# File 'mruby/src/range.c', line 214

static mrb_value
range_include(mrb_state *mrb, mrb_value range)
{
  mrb_value val = mrb_get_arg1(mrb);
  struct RRange *r = mrb_range_ptr(mrb, range);
  mrb_value beg, end;

  beg = RANGE_BEG(r);
  end = RANGE_END(r);
  if (mrb_nil_p(beg)) {
    if (RANGE_EXCL(r) ? r_gt(mrb, end, val)    /* end >  val */
                      : r_ge(mrb, end, val)) { /* end >= val */
      return mrb_true_value();
    }
  }
  else if (r_le(mrb, beg, val)) {              /* beg <= val */
    if (mrb_nil_p(end)) {
      return mrb_true_value();
    }
    if (RANGE_EXCL(r) ? r_gt(mrb, end, val)    /* end >  val */
                      : r_ge(mrb, end, val)) { /* end >= val */
      return mrb_true_value();
    }
  }
  return mrb_false_value();
}

#__num_to_aObject

15.2.14.4.15(x)



346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
# File 'mruby/src/range.c', line 346

static mrb_value
range_num_to_a(mrb_state *mrb, mrb_value range)
{
  struct RRange *r = mrb_range_ptr(mrb, range);
  mrb_value beg = RANGE_BEG(r);
  mrb_value end = RANGE_END(r);
  mrb_value ary;

  mrb->c->ci->mid = 0;
  if (mrb_nil_p(end)) {
    mrb_raise(mrb, E_RANGE_ERROR, "cannot convert endless range to an array");
  }
  if (mrb_integer_p(beg)) {
    if (mrb_integer_p(end)) {
      mrb_int a = mrb_integer(beg);
      mrb_int b = mrb_integer(end);
      mrb_int len;

      if (mrb_int_sub_overflow(b, a, &len)) {
      too_long:
        mrb_raise(mrb, E_RANGE_ERROR, "integer range too long");
      }
      if (!RANGE_EXCL(r)) {
        if (len == MRB_INT_MAX) goto too_long;
        len++;
      }
      ary = mrb_ary_new_capa(mrb, len);
      for (mrb_int i=0; i<len; i++) {
        mrb_ary_push(mrb, ary, mrb_int_value(mrb, a+i));
      }
      return ary;
    }
#ifndef MRB_NO_FLOAT
    if (mrb_float_p(end)) {
      mrb_float a = (mrb_float)mrb_integer(beg);
      mrb_float b = mrb_float(end);

      ary = mrb_ary_new_capa(mrb, (mrb_int)(b - a) + 1);
      if (RANGE_EXCL(r)) {
        while (a < b) {
          mrb_ary_push(mrb, ary, mrb_int_value(mrb, (mrb_int)a));
          a += 1.0;
        }
      }
      else {
        while (a <= b) {
          mrb_ary_push(mrb, ary, mrb_int_value(mrb, (mrb_int)a));
          a += 1.0;
        }
      }
      return ary;
    }
#endif
  }
  return mrb_nil_value();
}

#firstObject #beginObject

Returns the first object in rng.

Overloads:



118
119
120
121
122
# File 'mruby/src/range.c', line 118

static mrb_value
range_beg(mrb_state *mrb, mrb_value range)
{
  return mrb_range_beg(mrb, range);
}

#each(&block) ⇒ Object

Calls the given block for each element of self and pass the respective element.

ISO 15.2.14.4.4

Raises:



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'mruby/mrblib/range.rb', line 17

def each(&block)
  return to_enum :each unless block

  val = self.begin
  last = self.end

  if val.kind_of?(Integer) && last.nil?
    i = val
    while true
      block.call(i)
      i += 1
    end
    return self
  end

  if val.kind_of?(String) && last.nil?
    if val.respond_to? :__upto_endless
      return val.__upto_endless(&block)
    else
      str_each = true
    end
  end

  if val.kind_of?(Integer) && last.kind_of?(Integer) # integers are special
    lim = last
    lim += 1 unless exclude_end?
    i = val
    while i < lim
      block.call(i)
      i += 1
    end
    return self
  end

  if val.kind_of?(String) && last.kind_of?(String) # strings are special
    if val.respond_to? :upto
      return val.upto(last, exclude_end?, &block)
    else
      str_each = true
    end
  end

  raise TypeError, "can't iterate" unless val.respond_to? :succ

  return self if (val <=> last) > 0

  while (val <=> last) < 0
    block.call(val)
    val = val.succ
    if str_each
      break if val.size > last.size
    end
  end

  block.call(val) if !exclude_end? && (val <=> last) == 0
  self
end

#endObject #lastObject

Returns the object that defines the end of rng.

(1..10).end    #=> 10
(1...10).end   #=> 10

Overloads:



134
135
136
137
138
# File 'mruby/src/range.c', line 134

static mrb_value
range_end(mrb_state *mrb, mrb_value range)
{
  return mrb_range_end(mrb, range);
}

#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).eql?(0..2)            #=> true
(0..2).eql?(Range.new(0,2))  #=> true
(0..2).eql?(0...2)           #=> false

Returns:

  • (Boolean)


307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
# File 'mruby/src/range.c', line 307

static mrb_value
range_eql(mrb_state *mrb, mrb_value range)
{
  mrb_value obj = mrb_get_arg1(mrb);
  struct RRange *r, *o;

  if (mrb_obj_equal(mrb, range, obj)) return mrb_true_value();
  if (!mrb_obj_is_kind_of(mrb, obj, mrb->range_class)) return mrb_false_value();
  if (!mrb_range_p(obj)) return mrb_false_value();

  r = mrb_range_ptr(mrb, range);
  o = mrb_range_ptr(mrb, obj);
  if (!mrb_eql(mrb, RANGE_BEG(r), RANGE_BEG(o)) ||
      !mrb_eql(mrb, RANGE_END(r), RANGE_END(o)) ||
      (RANGE_EXCL(r) != RANGE_EXCL(o))) {
    return mrb_false_value();
  }
  return mrb_true_value();
}

#exclude_end?Boolean

Returns true if range excludes its end value.

Returns:

  • (Boolean)


146
147
148
149
150
# File 'mruby/src/range.c', line 146

static mrb_value
range_excl(mrb_state *mrb, mrb_value range)
{
  return mrb_bool_value(mrb_range_excl_p(mrb, range));
}

#first(*args) ⇒ Object

call-seq:

rng.first    -> obj
rng.first(n) -> an_array

Returns the first object in the range, or an array of the first n elements.

(10..20).first     #=> 10
(10..20).first(3)  #=> [10, 11, 12]

Raises:



118
119
120
121
122
# File 'mruby/src/range.c', line 118

static mrb_value
range_beg(mrb_state *mrb, mrb_value range)
{
  return mrb_range_beg(mrb, range);
}

#hashObject

redefine #hash 15.3.1.3.15



76
77
78
79
80
# File 'mruby/mrblib/range.rb', line 76

def hash
  h = first.hash ^ last.hash
  h += 1 if self.exclude_end?
  h
end

#===(obj) ⇒ Boolean #member?(val) ⇒ Boolean #include?(val) ⇒ Boolean

Overloads:

  • #===(obj) ⇒ Boolean

    Returns:

    • (Boolean)
  • #member?(val) ⇒ Boolean

    Returns:

    • (Boolean)
  • #include?(val) ⇒ Boolean

    Returns:

    • (Boolean)


214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
# File 'mruby/src/range.c', line 214

static mrb_value
range_include(mrb_state *mrb, mrb_value range)
{
  mrb_value val = mrb_get_arg1(mrb);
  struct RRange *r = mrb_range_ptr(mrb, range);
  mrb_value beg, end;

  beg = RANGE_BEG(r);
  end = RANGE_END(r);
  if (mrb_nil_p(beg)) {
    if (RANGE_EXCL(r) ? r_gt(mrb, end, val)    /* end >  val */
                      : r_ge(mrb, end, val)) { /* end >= val */
      return mrb_true_value();
    }
  }
  else if (r_le(mrb, beg, val)) {              /* beg <= val */
    if (mrb_nil_p(end)) {
      return mrb_true_value();
    }
    if (RANGE_EXCL(r) ? r_gt(mrb, end, val)    /* end >  val */
                      : r_ge(mrb, end, val)) { /* end >= val */
      return mrb_true_value();
    }
  }
  return mrb_false_value();
}

#initialize_copyObject

15.2.14.4.15(x)



328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
# File 'mruby/src/range.c', line 328

static mrb_value
range_initialize_copy(mrb_state *mrb, mrb_value copy)
{
  mrb_value src = mrb_get_arg1(mrb);
  struct RRange *r;

  if (mrb_obj_equal(mrb, copy, src)) return copy;
  if (!mrb_obj_is_instance_of(mrb, src, mrb_obj_class(mrb, copy))) {
    mrb_raise(mrb, E_TYPE_ERROR, "wrong argument class");
  }

  r = mrb_range_ptr(mrb, src);
  range_ptr_replace(mrb, mrb_range_raw_ptr(copy), RANGE_BEG(r), RANGE_END(r), RANGE_EXCL(r));
  mrb_obj_freeze(mrb, copy);

  return copy;
}

#inspectString

Convert this range object to a printable form (using inspect to convert the start and end objects).

Returns:



272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
# File 'mruby/src/range.c', line 272

static mrb_value
range_inspect(mrb_state *mrb, mrb_value range)
{
  mrb_value str;
  struct RRange *r = mrb_range_ptr(mrb, range);

  if (!mrb_nil_p(RANGE_BEG(r))) {
    str  = mrb_inspect(mrb, RANGE_BEG(r));
    str  = mrb_str_dup(mrb, str);
    mrb_str_cat(mrb, str, "...", RANGE_EXCL(r) ? 3 : 2);
  }
  else {
    str = mrb_str_new(mrb, "...", RANGE_EXCL(r) ? 3 : 2);
  }
  if (!mrb_nil_p(RANGE_END(r))) {
    mrb_value str2 = mrb_inspect(mrb, RANGE_END(r));
    mrb_str_cat_str(mrb, str, str2);
  }

  return str;
}

#last(*args) ⇒ Object

call-seq:

rng.last    -> obj
rng.last(n) -> an_array

Returns the last object in the range, or an array of the last n elements.

Note that with no arguments last will return the object that defines the end of the range even if #exclude_end? is true.

(10..20).last      #=> 20
(10...20).last     #=> 20
(10..20).last(3)   #=> [18, 19, 20]
(10...20).last(3)  #=> [17, 18, 19]

Raises:



134
135
136
137
138
# File 'mruby/src/range.c', line 134

static mrb_value
range_end(mrb_state *mrb, mrb_value range)
{
  return mrb_range_end(mrb, range);
}

#max(&block) ⇒ Object

Raises:



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'mruby/mrbgems/mruby-range-ext/mrblib/range.rb', line 56

def max(&block)
  val = self.begin
  last = self.end
  return super(&block) if block

  raise RangeError, "cannot get the maximum of endless range" if last.nil?

  # fast path for numerics
  if val.kind_of?(Numeric) && last.kind_of?(Numeric)
    raise TypeError if exclude_end? && !last.kind_of?(Integer)
    return nil if val > last
    return nil if val == last && exclude_end?

    max = last
    max -= 1 if exclude_end?
    return max
  end

  # delegate to Enumerable
  super()
end

#===(obj) ⇒ Boolean #member?(val) ⇒ Boolean #include?(val) ⇒ Boolean

Overloads:

  • #===(obj) ⇒ Boolean

    Returns:

    • (Boolean)
  • #member?(val) ⇒ Boolean

    Returns:

    • (Boolean)
  • #include?(val) ⇒ Boolean

    Returns:

    • (Boolean)


214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
# File 'mruby/src/range.c', line 214

static mrb_value
range_include(mrb_state *mrb, mrb_value range)
{
  mrb_value val = mrb_get_arg1(mrb);
  struct RRange *r = mrb_range_ptr(mrb, range);
  mrb_value beg, end;

  beg = RANGE_BEG(r);
  end = RANGE_END(r);
  if (mrb_nil_p(beg)) {
    if (RANGE_EXCL(r) ? r_gt(mrb, end, val)    /* end >  val */
                      : r_ge(mrb, end, val)) { /* end >= val */
      return mrb_true_value();
    }
  }
  else if (r_le(mrb, beg, val)) {              /* beg <= val */
    if (mrb_nil_p(end)) {
      return mrb_true_value();
    }
    if (RANGE_EXCL(r) ? r_gt(mrb, end, val)    /* end >  val */
                      : r_ge(mrb, end, val)) { /* end >= val */
      return mrb_true_value();
    }
  }
  return mrb_false_value();
}

#min(&block) ⇒ Object



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'mruby/mrbgems/mruby-range-ext/mrblib/range.rb', line 78

def min(&block)
  val = self.begin
  last = self.end
  if block
    raise RangeError, "cannot get the minimum of endless range with custom comparison method" if last.nil?
    return super(&block)
  end
  return val if last.nil?

  # fast path for numerics
  if val.kind_of?(Numeric) && last.kind_of?(Numeric)
    return nil if val > last
    return nil if val == last && exclude_end?

    min = val
    return min
  end

  # delegate to Enumerable
  super()
end

#to_aObject Also known as: entries

call-seq:

rng.to_a                   -> array
rng.entries                -> array

Returns an array containing the items in the range.

(1..7).to_a  #=> [1, 2, 3, 4, 5, 6, 7]
(1..).to_a   #=> RangeError: cannot convert endless range to an array


91
92
93
94
95
# File 'mruby/mrblib/range.rb', line 91

def to_a
  a = __num_to_a
  return a if a
  super
end

#to_sString

Convert this range object to a printable form.

Returns:



248
249
250
251
252
253
254
255
256
257
258
259
260
261
# File 'mruby/src/range.c', line 248

static mrb_value
range_to_s(mrb_state *mrb, mrb_value range)
{
  mrb_value str, str2;
  struct RRange *r = mrb_range_ptr(mrb, range);

  str  = mrb_obj_as_string(mrb, RANGE_BEG(r));
  str2 = mrb_obj_as_string(mrb, RANGE_END(r));
  str  = mrb_str_dup(mrb, str);
  mrb_str_cat(mrb, str, "...", RANGE_EXCL(r) ? 3 : 2);
  mrb_str_cat_str(mrb, str, str2);

  return str;
}