-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add enumerable#chunk #2821
add enumerable#chunk #2821
Conversation
Interestingly since In any case if we decide to accept this, docs a crucial for such a complex method. |
Enumerable#slice_before, Enumerable#slice_when or Enumerable#slice_after not so obvious to use (strange name, strange behavior), chunk is clear for me. |
Note that while we don't have |
iterator need to implement |
i trying to implement iterator, but have error with code: class A(T)
def initialize(@collection : Enumerable(T))
@iterator = @collection.each
end
end
a = A(Int32).new([1,2,3])
|
We can probably have module Iterator
def chunk
Chunk(typeof(self), T).new(self)
end
class Chunk(I, T)
@iterator : I
def initialize(@iterator : Iterator(T))
end
end
end |
iterator added |
@kostya Cool! Do you still have the non-iterator version? We could have both. Not all |
|
||
it "works with block" do | ||
res = [] of Tuple(Bool, Array(Int32)) | ||
[1, 2, 3].chunk { |x| x < 3 }.each { |k, v| res << {k, v} } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you use |(k, v)|
for now? Auto-unpacking is only available in the next version, with this the current specs can't be compiled anymore with 0.17.4.
what classes without each? may be implement for them each on channels? |
@kostya The standard library provides In the future I'd like to have something like |
how add two methods chunk for each with block and without? different names? |
added chunks method |
when :_alone | ||
return {tail_key.not_nil!, [tail_val]} | ||
else | ||
raise "symbols beginning with an underscore are reserved" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ArgumentError
end | ||
|
||
it "raises a RuntimeError if the block returns a Symbol starting with an underscore other than :_alone or :_separator" do | ||
expect_raises do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
expect_raises ArgumentError
@kostya I'll review the code and we'll eventually add this to the standard library :-) One thing: instead of using module Enumerable
module Chunk
record Drop
record Alone
end
end So one can do: enumerable.chunk { Enumerable::Chunk::Alone } It's a bit more verbose, but this way |
else | ||
raise ArgumentError.new("symbols beginning with an underscore are reserved") | ||
end | ||
return {tail_key.not_nil!, [tail_val]} if tail_key == Enumerable::Chunk::Alone |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this not_nil!
needed now? Could you maybe add a spec with nil
values? :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nil is hard here because, if i try to setup previous = uninitialized U
, it gives error:
can't use Object as a Proc argument type yet, use a more specific type
previous = uninitialized U
|
||
pending "work with class" do | ||
[1, 1, 2, 3, 3].each_chunk(&.class).to_a.should eq [{Int32, [1, 1, 2, 3, 3]}] | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nil is fixed, but now this not compiled because try to create uninitialized Int32.class
@kostya don't worry about the |
funny that this code give error: ./bin/crystal eval 'p [1,2,3].chunk { Enumerable::Chunk::Drop }.to_a'
but this not: ./bin/crystal eval 'p [1,2,3].chunk { rand >= 0 ? Enumerable::Chunk::Drop : 1 }.to_a'
[] |
a391af1
to
2776afd
Compare
This is done. Code is much readable now. |
@kostya Thank you for this! And sorry for the long delay. I'll merge this and add a few more comments and do some small changes. |
this version return array, but ruby returns enumerator class(implemented on fibers), which missing in crystal. at least this is 10 times faster than ruby