Thread overview
[Issue 4535] New: std.range could have a takeWhile!pred(range) function
Jul 30, 2010
Philippe Sigaud
Aug 15, 2010
David Simcha
Aug 15, 2010
Jonathan M Davis
Aug 19, 2010
Philippe Sigaud
Jun 04, 2011
timon.gehr@gmx.ch
July 30, 2010
http://d.puremagic.com/issues/show_bug.cgi?id=4535

           Summary: std.range could have a takeWhile!pred(range) function
           Product: D
           Version: D2
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: enhancement
          Priority: P2
         Component: Phobos
        AssignedTo: nobody@puremagic.com
        ReportedBy: philippe.sigaud@gmail.com


--- Comment #0 from Philippe Sigaud <philippe.sigaud@gmail.com> 2010-07-30 11:49:25 CEST ---
takeWhile!predicate(range) is a very useful function, that lazily produces elements of a range, as long as a predicate holds for the produced elements.

Usage example:
----
auto small = takeWhile!"a<5"([0,1,2,3,4,5,6,7,6,5,4,3,2,1,0]);
assert(equal(small, [0,1,2,3,4,5]);
----

That's different from filter!predicate(range) that would return _all_ elements in the range that satisfy the predicate.

Possible code for this follow:


import std.functional: unaryFun;
import std.range;


struct TakeWhile(alias pred, R)
if (isInputRange!R && is(typeof(!unaryFun!pred(ElementType!R.init)) == bool))
{
    R _range;

    bool empty() @property
    {
        return _range.empty || !(unaryFun!pred(_range.front));
    }

    ElementType!R front() @property
    {
        return _range.front;
    }

    TakeWhile save() @property
    {
        return this;
    }

    void popFront()
    {
        _range.popFront;
    }
}

TakeWhile!(pred, R) takeWhile(alias pred, R)(R range) if (isInputRange!R)
{
    return TakeWhile!(pred,R)(range);
}

unittest
{
    auto arr = [0,1,2,3,4,3,2,1,0];

    // With 'string functions'
    assert(equal( takeWhile!"a<3"(arr), [0,1,2])); // standard case
    assert(equal( takeWhile!"a<10"(arr), arr));    // predicate true for all
elements
    assert(takeWhile!"a<0"(arr).empty);            // predicate false from the
beginning
    assert(takeWhile!"a!=0"(arr).empty);           // predicate false for the
first element

    // With a standard function
    bool foo(int i) { return i != 4;}
    assert(equal( takeWhile!foo(arr), [0,1,2,3]));
}

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


David Simcha <dsimcha@yahoo.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |dsimcha@yahoo.com


--- Comment #1 from David Simcha <dsimcha@yahoo.com> 2010-08-14 18:32:44 PDT ---
Doesn't std.algorithm.until pretty much do what you want?

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


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

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |jmdavisProg@gmail.com


--- Comment #2 from Jonathan M Davis <jmdavisProg@gmail.com> 2010-08-14 18:45:43 PDT ---
I'd say that it mostly does, but it's not generic enough. until() has the
concept of a sentinel, while takeWhile() is based entirely on a predicate. I'm
not quite sure how their implementations would be different, but I'd expect
takeWhile() to be at least slightly more efficient (though perhaps negligably
so) than until(). I think that it would be beneficial to have the more generic
takeWhile(); if nothing else, the intent is clearer.

Of course, truth be told, I'm not a huge fan of until() anyway. I really think
that it should be more like find() except return what's before what you're
looking for rather than starting with it like find() does.

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



--- Comment #3 from Philippe Sigaud <philippe.sigaud@gmail.com> 2010-08-20 00:46:32 CEST ---
(In reply to comment #1)
> Doesn't std.algorithm.until pretty much do what you want?

Hmm.
I see until() is templated on the predicate. I guess most of the time, I can
rewrite my predicates to use until.

auto t = takeWhile!"a*a>10"(someValues);
auto u = until!"a*a>b"(10, someValues); // hey, b is 10, a will be elements
from someValues. Is that clear?

I personally find takeWhile to be more readable. Maybe I'm biased due to my using it in other languages?


Also, it's cumbersome for no-arg functions:

// takes lines as long as they are not empty
auto t = takeWhile!"!a.empty"(file.byLine);
auto u = until!"!a.empty"(dummy, file.byLine);

auto t = takeWile!externalUnaryPredicate(someValues);
auto u = until!externalUnaryPredicate(??, someValues); // How do I do that?


Philippe

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


Andrei Alexandrescu <andrei@metalanguage.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |ASSIGNED
                 CC|                            |andrei@metalanguage.com
         AssignedTo|nobody@puremagic.com        |andrei@metalanguage.com


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


timon.gehr@gmx.ch changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |timon.gehr@gmx.ch


--- Comment #4 from timon.gehr@gmx.ch 2011-06-04 13:36:46 PDT ---
*** Issue 6104 has been marked as a duplicate of this issue. ***

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