Project

General

Profile

Actions

Feature #6240

closed

Enumerable#drop with negative argument

Added by marcandre (Marc-Andre Lafortune) about 12 years ago. Updated over 5 years ago.

Status:
Closed
Target version:
-
[ruby-core:44028]

Description

Currently, Enumerable#drop works only for non-negative arguments.

It could be extended so that negative arguments means dropping from the end:

[:hello, :world].drop(-1) # => [:hello]

This could especially be interesting for Lazy#drop, which would keep a circular buffer of elements before yielding them.

(1..6).lazy.drop(-3).each{|x| puts x} # -> prints 1, 2 and 3

Thoughts?

Updated by shugo (Shugo Maeda) about 12 years ago

marcandre (Marc-Andre Lafortune) wrote:

Currently, Enumerable#drop works only for non-negative arguments.

It could be extended so that negative arguments means dropping from the end:

[:hello, :world].drop(-1) # => [:hello]

This could especially be interesting for Lazy#drop, which would keep a circular buffer of elements before yielding them.

(1..6).lazy.drop(-3).each{|x| puts x} # -> prints 1, 2 and 3

Thoughts?

How Enumerable#drop can know the total number of elements?
The source of elements might be IO. Besides that, the total number of elements might be infinite.

Updated by marcandre (Marc-Andre Lafortune) about 12 years ago

Hi,

shugo (Shugo Maeda) wrote:

How Enumerable#drop can know the total number of elements?
The source of elements might be IO. Besides that, the total number of elements might be infinite.

drop would have to consume the whole iteration, indeed, which is why I was talking about a buffer. The buffer holds elements until we know they are not in the last (-n) elements. Here's a Ruby implementation:

class Lazy
def drop(n)
return to_enum :drop, n unless block_given?
if n < 0
buffer = []
each do |e|
buffer << e
yield buffer.shift if buffer.size > -n
end
else
# ...
end
end
end

For infinite sequences, drop with negative argument would not be very useful, but it would still yield all elements.

Updated by shugo (Shugo Maeda) about 12 years ago

marcandre (Marc-Andre Lafortune) wrote:

How Enumerable#drop can know the total number of elements?
The source of elements might be IO. Besides that, the total number of elements might be infinite.

drop would have to consume the whole iteration, indeed, which is why I was talking about a buffer. The buffer holds elements until we know they are not in the last (-n) elements. Here's a Ruby implementation:

Ah, I see. It's interesting.

Do you have any use case in mind?

Updated by mame (Yusuke Endoh) about 12 years ago

  • Status changed from Open to Assigned
  • Assignee set to matz (Yukihiro Matsumoto)

Updated by yhara (Yutaka HARA) over 11 years ago

  • Target version changed from 2.0.0 to 2.6
Actions #6

Updated by naruse (Yui NARUSE) over 6 years ago

  • Target version deleted (2.6)
Actions #7

Updated by usa (Usaku NAKAMURA) over 5 years ago

  • Status changed from Assigned to Feedback

Updated by knu (Akinori MUSHA) over 5 years ago

Using an existing feature, [1,2,3,4,5].lazy.drop(-n) could be written as [1,2,3,4,5].each_cons(n+1).lazy.map(&:first).
Enumerable#each_cons does not use a circular buffer, though. (It currently uses push & shift)

Updated by marcandre (Marc-Andre Lafortune) over 5 years ago

  • Status changed from Feedback to Closed

knu (Akinori MUSHA) wrote:

Using an existing feature, [1,2,3,4,5].lazy.drop(-n) could be written as [1,2,3,4,5].each_cons(n+1).lazy.map(&:first).
Enumerable#each_cons does not use a circular buffer, though. (It currently uses push & shift)

That is clever.
I'll close this request, since it's not clear how frequent this could be needed and there's already an easy way of doing it (even though it might not be obvious).

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0Like0Like0