Thread overview
[Issue 5645] New: std.range.drop(), std.range.slice()
Aug 25, 2011
Jonathan M Davis
Aug 25, 2011
Jonathan M Davis
February 23, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=5645

           Summary: std.range.drop(), std.range.slice()
           Product: D
           Version: D2
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: enhancement
          Priority: P2
         Component: Phobos
        AssignedTo: nobody@puremagic.com
        ReportedBy: bearophile_hugs@eml.cc


--- Comment #0 from bearophile_hugs@eml.cc 2011-02-23 04:30:40 PST ---
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]

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
February 23, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=5645



--- Comment #1 from bearophile_hugs@eml.cc 2011-02-23 05:19:35 PST ---
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());
}

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
August 25, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=5645


Jonathan M Davis <jmdavisProg@gmx.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
                 CC|                            |jmdavisProg@gmx.com
         Resolution|                            |FIXED


--- Comment #2 from Jonathan M Davis <jmdavisProg@gmx.com> 2011-08-24 21:22:04 PDT ---
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.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
August 25, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=5645



--- Comment #3 from bearophile_hugs@eml.cc 2011-08-25 00:44:25 PDT ---
(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.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
August 25, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=5645



--- Comment #4 from bearophile_hugs@eml.cc 2011-08-25 00:46:14 PDT ---
(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.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
August 25, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=5645



--- Comment #5 from Jonathan M Davis <jmdavisProg@gmx.com> 2011-08-25 08:26:01 PDT ---
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.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------