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: ac92a361cd52
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: b52aeb03c359
Choose a head ref
  • 3 commits
  • 8 files changed
  • 1 contributor

Commits on Oct 25, 2016

  1. Make the Iterable module generic

    Ary Borenszweig committed Oct 25, 2016

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    7b67552 View commit details
  2. Copy Ruby docs for Iterator#chunk.

    Ary Borenszweig committed Oct 25, 2016
    Copy the full SHA
    d3acc93 View commit details
  3. Added Iterator#with_index(&block)

    Ary Borenszweig committed Oct 25, 2016
    4
    Copy the full SHA
    b52aeb0 View commit details
Showing with 68 additions and 21 deletions.
  1. +8 −0 spec/std/iterator_spec.cr
  2. +1 −1 src/dir.cr
  3. +14 −10 src/enumerable.cr
  4. +1 −1 src/indexable.cr
  5. +10 −1 src/iterable.cr
  6. +32 −6 src/iterator.cr
  7. +1 −1 src/range.cr
  8. +1 −1 src/set.cr
8 changes: 8 additions & 0 deletions spec/std/iterator_spec.cr
Original file line number Diff line number Diff line change
@@ -442,6 +442,14 @@ describe Iterator do
iter.rewind
iter.next.should eq({1, 10})
end

it "does with_index from range, with block" do
tuples = [] of {Int32, Int32}
(1..3).each.with_index do |value, index|
tuples << {value, index}
end
tuples.should eq([{1, 0}, {2, 1}, {3, 2}])
end
end

describe "with object" do
2 changes: 1 addition & 1 deletion src/dir.cr
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@ require "c/sys/stat"
# the parent directory (..), and the directory itself (.).
class Dir
include Enumerable(String)
include Iterable
include Iterable(String)

getter path : String

24 changes: 14 additions & 10 deletions src/enumerable.cr
Original file line number Diff line number Diff line change
@@ -74,18 +74,23 @@ module Enumerable(T)
any? &.itself
end

# Returns an iterator with chunks
# Enumerates over the items, chunking them together based on the return value of the block.
#
# (0..7).chunk(&./(3)).to_a => [{0, [0, 1, 2]}, {1, [3, 4, 5]}, {2, [6, 7]}]
# Consecutive elements which return the same block value are chunked together.
#
def chunk(&block : T -> U)
self.each.chunk &block
end

# Returns an array of chunks (TODO: rewrite to use enumerator)
# For example, consecutive even numbers and odd numbers can be chunked as follows.
#
# ```
# ary = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5].chunks { |n| n.even? }
# ary # => [{false, [3, 1]}, {true, [4]}, {false, [1, 5, 9]}, {true, [2, 6]}, {false, [5, 3, 5]}]
# ```
#
# (0..7).chunks(&./(3)) => [{0, [0, 1, 2]}, {1, [3, 4, 5]}, {2, [6, 7]}]
# The following key values have special meaning:
#
# * `Enumerable::Chunk::Drop` specifies that the elements should be dropped
# * `Enumerable::Chunk::Alone` specifies that the element should be chunked by itself
#
# See also: `Iterator#chunk`
def chunks(&block : T -> U)
res = [] of Tuple(U, Array(T))
chunks_internal(block) { |k, v| res << {k, v} }
@@ -98,7 +103,7 @@ module Enumerable(T)
record Alone

# :nodoc:
class Accumulator(T, U)
struct Accumulator(T, U)
def initialize
@key = uninitialized U
@initialized = false
@@ -130,7 +135,6 @@ module Enumerable(T)
end
end

# :nodoc:
private def chunks_internal(original_block : T -> U)
acc = Chunk::Accumulator(T, U).new
each do |val|
2 changes: 1 addition & 1 deletion src/indexable.cr
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@
#
# Types including this module are typically `Array`-like types.
module Indexable(T)
include Iterable
include Iterable(T)

# TODO: the compiler doesn't realize that if X includes Indexable then X is Enumerable
# This is fixed in 0.19.0
11 changes: 10 additions & 1 deletion src/iterable.cr
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# The Iterable mixin provides convenience methods to collection classes
# that provide an `each` method that returns an `Iterator` over the collection.
module Iterable
module Iterable(T)
# Must return an `Iterator` over the elements in this collection.
abstract def each

@@ -14,6 +14,15 @@ module Iterable
each.cycle(n)
end

# Returns an Iterator that enumerates over the items, chunking them together based on the return value of the block.
#
# (0..7).chunk(&./(3)).to_a => [{0, [0, 1, 2]}, {1, [3, 4, 5]}, {2, [6, 7]}]
#
# See `Iterator#chunks`
def chunk(&block : T -> U) forall U
each.chunk &block
end

# Same as `each.slice(count)`.
def each_slice(count : Int)
each.slice(count)
38 changes: 32 additions & 6 deletions src/iterator.cr
Original file line number Diff line number Diff line change
@@ -893,6 +893,13 @@ module Iterator(T)
WithIndex(typeof(self), T, typeof(offset)).new(self, offset)
end

# Yields each element in this iterator together with its index.
def with_index(offset : Int = 0)
with_index.each do |value, index|
yield value, index
end
end

private class WithIndex(I, T, O)
include Iterator({T, Int32})
include IteratorWrapper
@@ -976,14 +983,33 @@ module Iterator(T)
end
end

# Returns an iterator that returns a chunks.
# Returns an Iterator that enumerates over the items, chunking them together based on the return value of the block.
#
# iter = (1..3).chunk(&./(2))
# iter.next # => {0, [1]}
# iter.next # => {1, [2, 3]}
# iter.next # => Iterator::Stop::INSTANCE
# Consecutive elements which return the same block value are chunked together.
#
# For example, consecutive even numbers and odd numbers can be chunked as follows.
#
# ```
# [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5].chunk { |n|
# n.even?
# }.each { |even, ary|
# p [even, ary]
# }
#
# # => [false, [3, 1]]
# # [true, [4]]
# # [false, [1, 5, 9]]
# # [true, [2, 6]]
# # [false, [5, 3, 5]]
# ```
#
# The following key values have special meaning:
#
# * `Enumerable::Chunk::Drop` specifies that the elements should be dropped
# * `Enumerable::Chunk::Alone` specifies that the element should be chunked by itself
#
def chunk(&block : T -> U)
# See also: `Enumerable#chunks`
def chunk(&block : T -> U) forall T, U
Chunk(typeof(self), T, U).new(self, &block)
end

2 changes: 1 addition & 1 deletion src/range.cr
Original file line number Diff line number Diff line change
@@ -51,7 +51,7 @@
# ```
struct Range(B, E)
include Enumerable(B)
include Iterable
include Iterable(B)

# Returns the object that defines the beginning of this range.
#
2 changes: 1 addition & 1 deletion src/set.cr
Original file line number Diff line number Diff line change
@@ -23,7 +23,7 @@
# s2.subset? s1 # => true
struct Set(T)
include Enumerable(T)
include Iterable
include Iterable(T)

# Creates a new, empty `Set`
#