Skip to content

Commit

Permalink
move clamp from number to comparable (crystal-lang#8522)
Browse files Browse the repository at this point in the history
  • Loading branch information
jkthorne authored and ndbroadbent committed Dec 3, 2019
1 parent 4649a8b commit a66a6f0
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 74 deletions.
48 changes: 48 additions & 0 deletions spec/std/comparable_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,52 @@ describe Comparable do
(obj >= 1).should be_false
(obj > 1).should be_false
end

describe "clamp" do
describe "number" do
it "clamps integers" do
-5.clamp(-10, 100).should eq(-5)
-5.clamp(10, 100).should eq(10)
5.clamp(10, 100).should eq(10)
50.clamp(10, 100).should eq(50)
500.clamp(10, 100).should eq(100)

50.clamp(10..100).should eq(50)

50.clamp(10..nil).should eq(50)
50.clamp(10...nil).should eq(50)
5.clamp(10..nil).should eq(10)
5.clamp(10...nil).should eq(10)

5.clamp(nil..10).should eq(5)
50.clamp(nil..10).should eq(10)
end

it "clamps floats" do
-5.5.clamp(-10.1, 100.1).should eq(-5.5)
-5.5.clamp(10.1, 100.1).should eq(10.1)
5.5.clamp(10.1, 100.1).should eq(10.1)
50.5.clamp(10.1, 100.1).should eq(50.5)
500.5.clamp(10.1, 100.1).should eq(100.1)

50.5.clamp(10.1..100.1).should eq(50.5)
end

it "fails with an exclusive range" do
expect_raises(ArgumentError) do
range = Range.new(1, 2, exclusive: true)
5.clamp(range)
end
end
end

describe "String" do
it "clamps strings" do
"e".clamp("a", "s").should eq "e"
"e".clamp("f", "s").should eq "f"
"e".clamp("a", "c").should eq "c"
"this".clamp("thief", "thin").should eq "thin"
end
end
end
end
37 changes: 0 additions & 37 deletions spec/std/number_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -93,43 +93,6 @@ describe "Number" do
end
end

describe "clamp" do
it "clamps integers" do
-5.clamp(-10, 100).should eq(-5)
-5.clamp(10, 100).should eq(10)
5.clamp(10, 100).should eq(10)
50.clamp(10, 100).should eq(50)
500.clamp(10, 100).should eq(100)

50.clamp(10..100).should eq(50)

50.clamp(10..nil).should eq(50)
50.clamp(10...nil).should eq(50)
5.clamp(10..nil).should eq(10)
5.clamp(10...nil).should eq(10)

5.clamp(nil..10).should eq(5)
50.clamp(nil..10).should eq(10)
end

it "clamps floats" do
-5.5.clamp(-10.1, 100.1).should eq(-5.5)
-5.5.clamp(10.1, 100.1).should eq(10.1)
5.5.clamp(10.1, 100.1).should eq(10.1)
50.5.clamp(10.1, 100.1).should eq(50.5)
500.5.clamp(10.1, 100.1).should eq(100.1)

50.5.clamp(10.1..100.1).should eq(50.5)
end

it "fails with an exclusive range" do
expect_raises(ArgumentError) do
range = Range.new(1, 2, exclusive: true)
5.clamp(range)
end
end
end

it "gives the absolute value" do
123.abs.should eq(123)
-123.abs.should eq(123)
Expand Down
37 changes: 37 additions & 0 deletions src/comparable.cr
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,41 @@ module Comparable(T)
# [3, 1, 2].sort { |x, y| x <=> y } # => [1, 2, 3]
# ```
abstract def <=>(other : T)

# Clamps a value within *range*.
#
# ```
# 5.clamp(10..100) # => 10
# 50.clamp(10..100) # => 50
# 500.clamp(10..100) # => 100
#
# 5.clamp(10..) # => 10
# 50.clamp(10..) # => 50
#
# 5.clamp(..10) # => 5
# 50.clamp(..10) # => 10
# ```
def clamp(range : Range)
raise ArgumentError.new("Can't clamp an exclusive range") if !range.end.nil? && range.exclusive?
clamp range.begin, range.end
end

# Clamps a value between *min* and *max*.
#
# ```
# 5.clamp(10, 100) # => 10
# 50.clamp(10, 100) # => 50
# 500.clamp(10, 100) # => 100
#
# 5.clamp(10, nil) # => 10
# 50.clamp(10, nil) # => 50
#
# 5.clamp(nil, 10) # => 5
# 50.clamp(nil, 10) # => 10
# ```
def clamp(min, max)
return max if !max.nil? && self > max
return min if !min.nil? && self < min
self
end
end
37 changes: 0 additions & 37 deletions src/number.cr
Original file line number Diff line number Diff line change
Expand Up @@ -245,43 +245,6 @@ struct Number
end
end

# Clamps a value within *range*.
#
# ```
# 5.clamp(10..100) # => 10
# 50.clamp(10..100) # => 50
# 500.clamp(10..100) # => 100
#
# 5.clamp(10..) # => 10
# 50.clamp(10..) # => 50
#
# 5.clamp(..10) # => 5
# 50.clamp(..10) # => 10
# ```
def clamp(range : Range)
raise ArgumentError.new("Can't clamp an exclusive range") if !range.end.nil? && range.exclusive?
clamp range.begin, range.end
end

# Clamps a value between *min* and *max*.
#
# ```
# 5.clamp(10, 100) # => 10
# 50.clamp(10, 100) # => 50
# 500.clamp(10, 100) # => 100
#
# 5.clamp(10, nil) # => 10
# 50.clamp(10, nil) # => 50
#
# 5.clamp(nil, 10) # => 5
# 50.clamp(nil, 10) # => 10
# ```
def clamp(min, max)
return max if !max.nil? && self > max
return min if !min.nil? && self < min
self
end

# Returns `true` if value is equal to zero.
#
# ```
Expand Down

0 comments on commit a66a6f0

Please sign in to comment.