Bug 5645 – std.range.drop(), std.range.slice()

Status
RESOLVED
Resolution
FIXED
Severity
enhancement
Priority
P2
Component
phobos
Product
D
Version
D2
Platform
All
OS
All
Creation time
2011-02-23T04:30:00Z
Last change time
2011-08-25T08:26:01Z
Assigned to
nobody
Creator
bearophile_hugs

Comments

Comment #0 by bearophile_hugs — 2011-02-23T04:30:40Z
std.range may find useful a function named "drop", to skip the first n items of a lazy iterable (it may call popFrontN if present, or empty/popFront otherwise). Example: it allows to take the nth item of a lazy iterable: import std.stdio, std.array, std.range; void main() { auto fib = recurrence!("a[n-1] + a[n-2]")(1, 1); writeln(drop(fib, 9).front); } Instead of using something worse like: import std.stdio, std.array, std.range; void main() { auto fib = recurrence!("a[n-1] + a[n-2]")(1, 1); writeln(array(take(fib, 10)).back); } "drop" is present in Haskell too: http://www.cse.unsw.edu.au/~en1000/haskell/inbuilt.html#take (Haskell also has this syntax: list !! n to take exactly the n-th item of a lazy list.) In Python, module itertools, there is also a quite useful lazy slicing function named islice(), that's more general than drop(): http://docs.python.org/library/itertools.html#itertools.islice >>> from itertools import islice >>> r = (x*x for x in xrange(10)) # lazy >>> list(islice(r, 5, 8)) [25, 36, 49]
Comment #1 by bearophile_hugs — 2011-02-23T05:19:35Z
Currently you are able to write drop(fib, 9).front like this, in two lines: import std.stdio, std.array, std.range; void main() { auto fib = recurrence!("a[n-1] + a[n-2]")(1, 1); popFrontN(fib, 9); writeln(fib.front()); }
Comment #2 by issues.dlang — 2011-08-24T21:22:04Z
The drop function has been added https://github.com/D-Programming- Language/phobos/commit/6b6c604bbeb66ca1811a3a02b4f807d27621580f You can get the islice functionality by combining take with drop. e.g. take(drop(range, 5), 3); Personally, I'm not all that thrilled with idea of adding a function such as islice, since it's not efficient the way that slices normally are, and I'm afraid that it would give the impression that it is - that and the fact that you end up with a new type unless the range actually _is_ sliceable. If you still want such a function though, please create a new enhancement request for it.
Comment #3 by bearophile_hugs — 2011-08-25T00:44:25Z
(In reply to comment #2) > The drop function has been added Thank you. > take(drop(range, 5), 3); > > Personally, I'm not all that thrilled with idea of adding a function such as > islice, since it's not efficient the way that slices normally are, islice() is a lazy range implemented essentially as take(drop()), so I don't understand why it's not efficient.
Comment #4 by bearophile_hugs — 2011-08-25T00:46:14Z
(In reply to comment #3) Now I understand what you meant: "the way that slices normally are". You are right. It contains drop(), so you generally have to iterate the first items to drop. This is slower than array slicing, that's an O(1) operation.
Comment #5 by issues.dlang — 2011-08-25T08:26:01Z
Exactly. Slicing is an O(1) operation, but take(drop(range, 5), 3) is O(n) unless the original range isSliceable. It's perfectly fine to do it, but creating a function such as islice at least implies that it's efficient like slicing is, which isn't generally true. I do have to say though, that it's operations like that that make me wish that take's arguments had never been flipped, so that you could do take(3, drop(5, range)), but I guess that we're stuck at this point, and it made no sense for drop not to match take in regards to the order of its arguments.