Preview Ruby 4.1 is a preview. It can change before the final release. Switch to Ruby 4.0 →
Range#clamp
static VALUE
range_clamp(int argc, VALUE *argv, VALUE self)
{
VALUE self_beg = RANGE_BEG(self);
VALUE self_end = RANGE_END(self);
int self_excl = EXCL(self);
VALUE min, max;
int clamp_beg = 0, clamp_end = 0, excl = 0;
argc = rb_scan_args(argc, argv, "11", &min, &max);
if (argc == 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(min) && !NIL_P(max) && r_cmp(min, max) > 0) {
rb_raise(rb_eArgError, "min argument must be less than or equal to max argument");
}
if (!NIL_P(min)) {
if (NIL_P(self_beg) || r_cmp(self_beg, min) < 0) {
clamp_beg = -1;
self_beg = min;
}
if (!NIL_P(self_end) && r_cmp(self_end, min) < 0) {
clamp_end = -1;
self_end = min;
}
}
if (!NIL_P(max)) {
if (clamp_beg == 0) {
if (!NIL_P(self_beg) && r_cmp(self_beg, max) > 0) {
clamp_beg = +1;
self_beg = max;
}
}
if (clamp_end == 0) {
int cmp = NIL_P(self_end) ? +1 : r_cmp(self_end, max);
if (cmp > 0) {
clamp_end = +1;
self_end = max;
self_excl = excl;
}
else if (cmp == 0) {
self_excl |= excl;
}
}
}
if (clamp_beg && clamp_beg == clamp_end) {
/* self is entirely outside the clamping bounds. */
self_excl = TRUE;
}
return rb_range_new(self_beg, self_end, self_excl);
}
Returns a new Range instance whose begin and end values are clamped to min and max, or to range.begin and range.end.
The returned range excludes its end if any of the following is true:
-
The returned end value is an excluded end value of
selfor range. -
Both begin and end values are clamped to the lower bound, or both are clamped to the upper bound. Since
selfis entirely outside the clamping bounds, the returned range is made empty by excluding its end.
Otherwise, the returned range includes its end.
Examples:
(1..10).clamp(3, 7) # => 3..7 (1...10).clamp(3, 7) # => 3..7 (1...10).clamp(3, 10) # => 3...10 (0...).clamp(0, 10) # => 0..10 (1..10).clamp(3..7) # => 3..7 (1..10).clamp(3...7) # => 3...7 (1..5).clamp(3...7) # => 3..5 (..10).clamp(3, 7) # => 3..7 (...10).clamp(3, 7) # => 3..7 (..10).clamp(3...7) # => 3...7 (..5).clamp(3...7) # => 3..5 (1..10).clamp(20..30) # => 20...20 (1..10).clamp(-10..0) # => 0...0 (..10).clamp(20..30) # => 20...20 (1..10).clamp(..7) # => 1..7 (1..10).clamp(...7) # => 1...7 (1..5).clamp(...7) # => 1..5 (1..10).clamp(3..) # => 3..10 (1..10).clamp(3...) # => 3..10 (1..).clamp(3..) # => 3.. (1...).clamp(3...) # => 3...
Ruby version changes
-
4.1
-
Range#clampis added. It returns a newRangeinstance whose begin and end values are clamped to the given bounds. [Feature #22175]
-