Module: Comparable
- Included in:
- File::Stat, IO::Buffer, Numeric, String, Symbol, Time
- Defined in:
- compar.c
Overview
The Comparable mixin is used by classes whose objects may be ordered. The class must define the <=>
operator, which compares the receiver against another object, returning a value less than 0, returning 0, or returning a value greater than 0, depending on whether the receiver is less than, equal to, or greater than the other object. If the other object is not comparable then the <=>
operator should return nil
. Comparable uses <=>
to implement the conventional comparison operators (<
, <=
, ==
, >=
, and >
) and the method between?
.
class StringSorter
include Comparable
attr :str
def <=>(other)
str.size <=> other.str.size
end
def initialize(str)
@str = str
end
def inspect
@str
end
end
s1 = StringSorter.new("Z")
s2 = StringSorter.new("YY")
s3 = StringSorter.new("XXX")
s4 = StringSorter.new("WWWW")
s5 = StringSorter.new("VVVVV")
s1 < s2 #=> true
s4.between?(s1, s3) #=> false
s4.between?(s3, s5) #=> true
[ s3, s2, s5, s4, s1 ].sort #=> [Z, YY, XXX, WWWW, VVVVV]
What’s Here
Module Comparable provides these methods, all of which use method <=>
:
-
#<: Returns whether
self
is less than the given object. -
#<=: Returns whether
self
is less than or equal to the given object. -
#==: Returns whether
self
is equal to the given object. -
#>: Returns whether
self
is greater than the given object. -
#>=: Returns whether
self
is greater than or equal to the given object. -
#between?: Returns
true
ifself
is between two given objects. -
#clamp: For given objects
min
andmax
, or range(min..max)
, returns:-
min
if(self <=> min) < 0
. -
max
if(self <=> max) > 0
. -
self
otherwise.
-
Instance Method Summary collapse
-
#<(other) ⇒ Boolean
Compares two objects based on the receiver’s
<=>
method, returning true if it returns a value less than 0. -
#<=(other) ⇒ Boolean
Compares two objects based on the receiver’s
<=>
method, returning true if it returns a value less than or equal to 0. -
#==(other) ⇒ Boolean
Compares two objects based on the receiver’s
<=>
method, returning true if it returns 0. -
#>(other) ⇒ Boolean
Compares two objects based on the receiver’s
<=>
method, returning true if it returns a value greater than 0. -
#>=(other) ⇒ Boolean
Compares two objects based on the receiver’s
<=>
method, returning true if it returns a value greater than or equal to 0. -
#between?(min, max) ⇒ Boolean
Returns
false
if obj<=>
min is less than zero or if obj<=>
max is greater than zero,true
otherwise. -
#clamp(*args) ⇒ Object
In
(min, max)
form, returns min if obj<=>
min is less than zero, max if obj<=>
max is greater than zero, and obj otherwise.
Instance Method Details
#<(other) ⇒ Boolean
Compares two objects based on the receiver’s <=>
method, returning true if it returns a value less than 0.
132 133 134 135 136 |
# File 'compar.c', line 132
static VALUE
cmp_lt(VALUE x, VALUE y)
{
return RBOOL(cmpint(x, y) < 0);
}
|
#<=(other) ⇒ Boolean
Compares two objects based on the receiver’s <=>
method, returning true if it returns a value less than or equal to 0.
146 147 148 149 150 |
# File 'compar.c', line 146
static VALUE
cmp_le(VALUE x, VALUE y)
{
return RBOOL(cmpint(x, y) <= 0);
}
|
#==(other) ⇒ Boolean
Compares two objects based on the receiver’s <=>
method, returning true if it returns 0. Also returns true if obj and other are the same object.
78 79 80 81 82 83 84 85 86 87 88 |
# File 'compar.c', line 78
static VALUE
cmp_equal(VALUE x, VALUE y)
{
VALUE c;
if (x == y) return Qtrue;
c = rb_exec_recursive_paired_outer(cmp_eq_recursive, x, y, y);
if (NIL_P(c)) return Qfalse;
return RBOOL(rb_cmpint(c, x, y) == 0);
}
|
#>(other) ⇒ Boolean
Compares two objects based on the receiver’s <=>
method, returning true if it returns a value greater than 0.
104 105 106 107 108 |
# File 'compar.c', line 104
static VALUE
cmp_gt(VALUE x, VALUE y)
{
return RBOOL(cmpint(x, y) > 0);
}
|
#>=(other) ⇒ Boolean
Compares two objects based on the receiver’s <=>
method, returning true if it returns a value greater than or equal to 0.
118 119 120 121 122 |
# File 'compar.c', line 118
static VALUE
cmp_ge(VALUE x, VALUE y)
{
return RBOOL(cmpint(x, y) >= 0);
}
|
#between?(min, max) ⇒ Boolean
Returns false
if obj <=>
min is less than zero or if obj <=>
max is greater than zero, true
otherwise.
3.between?(1, 5) #=> true
6.between?(1, 5) #=> false
'cat'.between?('ant', 'dog') #=> true
'gnu'.between?('ant', 'dog') #=> false
167 168 169 170 171 |
# File 'compar.c', line 167
static VALUE
cmp_between(VALUE x, VALUE min, VALUE max)
{
return RBOOL((cmpint(x, min) >= 0 && cmpint(x, max) <= 0));
}
|
#clamp(min, max) ⇒ Object #clamp(range) ⇒ Object
In (min, max)
form, returns min if obj <=>
min is less than zero, max if obj <=>
max is greater than zero, and obj otherwise.
12.clamp(0, 100) #=> 12
523.clamp(0, 100) #=> 100
-3.123.clamp(0, 100) #=> 0
'd'.clamp('a', 'f') #=> 'd'
'z'.clamp('a', 'f') #=> 'f'
If min is nil
, it is considered smaller than obj, and if max is nil
, it is considered greater than obj.
-20.clamp(0, nil) #=> 0
523.clamp(nil, 100) #=> 100
In (range)
form, returns range.begin if obj <=>
range.begin is less than zero, range.end if obj <=>
range.end is greater than zero, and obj otherwise.
12.clamp(0..100) #=> 12
523.clamp(0..100) #=> 100
-3.123.clamp(0..100) #=> 0
'd'.clamp('a'..'f') #=> 'd'
'z'.clamp('a'..'f') #=> 'f'
If range.begin is nil
, it is considered smaller than obj, and if range.end is nil
, it is considered greater than obj.
-20.clamp(0..) #=> 0
523.clamp(..100) #=> 100
When range.end is excluded and not nil
, an exception is raised.
100.clamp(0...100) # ArgumentError
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 |
# File 'compar.c', line 221
static VALUE
cmp_clamp(int argc, VALUE *argv, VALUE x)
{
VALUE min, max;
int c, excl = 0;
if (rb_scan_args(argc, argv, "11", &min, &max) == 1) {
VALUE range = min;
if (!rb_range_values(range, &min, &max, &excl)) {
rb_raise(rb_eTypeError, "wrong argument type %s (expected Range)",
rb_builtin_class_name(range));
}
if (!NIL_P(max)) {
if (excl) rb_raise(rb_eArgError, "cannot clamp with an exclusive range");
}
}
if (!NIL_P(min) && !NIL_P(max) && cmpint(min, max) > 0) {
rb_raise(rb_eArgError, "min argument must be less than or equal to max argument");
}
if (!NIL_P(min)) {
c = cmpint(x, min);
if (c == 0) return x;
if (c < 0) return min;
}
if (!NIL_P(max)) {
c = cmpint(x, max);
if (c > 0) return max;
}
return x;
}
|