Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: crystal-lang/crystal
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: a8e556780914
Choose a base ref
...
head repository: crystal-lang/crystal
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 5370fafdd874
Choose a head ref
  • 2 commits
  • 2 files changed
  • 1 contributor

Commits on Jun 12, 2017

  1. Copy the full SHA
    c8ec408 View commit details
  2. Copy the full SHA
    5370faf View commit details
Showing with 55 additions and 0 deletions.
  1. +24 −0 spec/std/range_spec.cr
  2. +31 −0 src/range.cr
24 changes: 24 additions & 0 deletions spec/std/range_spec.cr
Original file line number Diff line number Diff line change
@@ -356,6 +356,30 @@ describe "Range" do
end
end

describe "map" do
it "optimizes for int range" do
(5..12).map(&.itself).should eq([5, 6, 7, 8, 9, 10, 11, 12])
(5...12).map(&.itself).should eq([5, 6, 7, 8, 9, 10, 11])
(5..4).map(&.itself).size.should eq(0)
end

it "works for other types" do
('a'..'c').map(&.itself).should eq(['a', 'b', 'c'])
end
end

describe "size" do
it "optimizes for int range" do
(5..12).size.should eq(8)
(5...12).size.should eq(7)
(5..4).size.should eq(0)
end

it "works for other types" do
('a'..'c').size.should eq(3)
end
end

it "clones" do
range = [1]..[2]
clone = range.clone
31 changes: 31 additions & 0 deletions src/range.cr
Original file line number Diff line number Diff line change
@@ -276,6 +276,37 @@ struct Range(B, E)
Range.new(@begin.clone, @end.clone, @exclusive)
end

# :nodoc:
def map(&block : B -> U) forall U
b = self.begin
e = self.end

# Optimized implementation for int range
if b.is_a?(Int) && e.is_a?(Int)
e -= 1 if @exclusive
n = e - b + 1
n = 0 if n < 0
Array(U).new(n) { |i| yield b + i }
else
super { |i| yield i }
end
end

# :nodoc:
def size
b = self.begin
e = self.end

# Optimized implementation for int range
if b.is_a?(Int) && e.is_a?(Int)
e -= 1 if @exclusive
n = e - b + 1
n < 0 ? 0 : n
else
super
end
end

private class ItemIterator(B, E)
include Iterator(B)