After having a short conversation with @bew on Gitter I decided to open this as an issue. Enumerable currently has first
and last
methods which return the first and last elements of an Enumerable respectively. They also take an optional count
parameter which allows you to get the first or last n elements.
I am proposing that Enumerable#take
be added to compliment skip
. It should return every element up to the count index.
An example of how this could be done:
module Enumerable(T)
def take(count : Int)
raise ArgumentError.new("Attempt to take negative size") if count < 0
array = Array(T).new
each_with_index do |e, i|
array << e if i < count
end
array
end
end
I'd be more than happy to PR this
How is it different from first
?
@jhass basically the only difference is that take
requires an argument. Ruby also has first and take methods that you can use in the same way.
Yes, this overload already exists for first
.
@z64 it's more about the naming than anything. When I see first I think first element, it's not until I see the API that I think first _n_ elements. Take however makes sense. I want to take 4 elements from the array. It would be a better named alias really.
That's a fine point for discussion, but we were just confused because the functionality was already there. It wasn't clear if you just didn't know this or wanted something different. You should update the issue description to reflect this.
@z64 how's that?
We have a pretty strict policy of no aliases in the standard library in particular and no two ways to do something in general, mainly to increase code understandabilty and decrease debate in the community about the right way to do something.
So to do this we would need to remove first
with an argument
If take
is more or less like first
, most will agree there is no point to implement it.
But, if we can merge first
and last
in to take
, why not?
My idea is to add support to negative counts, that will be used to return last n elements.
e.g: enumerable.take(-3)
wil take the last 3 elements, and enumerable.take(3)
the first ones.
Enumerable#skip
could also support this.
first(5)
reads fine to me, take
is actually a little confusing since to me the act of taking means to move them, which implies take(5)
is the same as shift(5)
(i.e. it removes them from the array). I vote to close this: it's an unnecessary breaking change for pretty much negative benefit as far as I'm concerned.
@RX14 it wouldn't have to be breaking, just an addition, but whatever works
No, we already explained we don't have aliases in crystal. We have one name for one method. If there's two names for a method then everyone ends up learning that both names exist, and there's inevitably going to be conflicts between collaborators on which one to use (like this one). Closing.
Most helpful comment
first(5)
reads fine to me,take
is actually a little confusing since to me the act of taking means to move them, which impliestake(5)
is the same asshift(5)
(i.e. it removes them from the array). I vote to close this: it's an unnecessary breaking change for pretty much negative benefit as far as I'm concerned.