www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - New to std.algorithm and generics, no idea how to make simple things

reply "newguy" <no.spam.please sorry.org> writes:
I really can't wrap my head around these. I fought whole day
trying to figure out how to do the simplest thing one can
imagine: remove an element from a doubly linked list. Here's what
I've tried, see if there is a recurring mistake of thought or
something:

import std.stdio;
import std.algorithm;
import std.range;
import std.container;

struct Point {
      int x;
      int y;
}

void main() {
      DList!Point points;
      points.insert(Point(0,0));
      points.insert(Point(10,10));
      points.insert(Point(5,5));
      points.insert(Point(20,20));

      points.remove(takeOne(find!(p => p.x > 7)(points[])));
      // test.d(18): Error: function
std.container.DList!(Point).DList.remove (Range r) is not
callable using argument types (Result)

      points.linearRemove(takeOne(find!(p => p.x > 7)(points[])));
      // test.d(21): Error: template
std.container.DList!(Point).DList.linearRemove cannot deduce
function from argument types !()(Result), candidates are:
      // /usr/include/dmd/phobos/std/container.d(2234):
std.container.DList!(Point).DList.linearRemove(R)(R r) if (is(R
== Range))
      // /usr/include/dmd/phobos/std/container.d(2240):
std.container.DList!(Point).DList.linearRemove(R)(R r) if (is(R
== Range))
      // /usr/include/dmd/phobos/std/container.d(2253):
std.container.DList!(Point).DList.linearRemove(R)(R r) if (is(R
== Take!Range))

      points.remove(find!(p => p.x > 7)(points[]));
      // 0

      points.remove(takeOne(filter!(p => p.x > 7)(points[])));
      // test.d(30): Error: function
std.container.DList!(Point).DList.remove (Range r) is not
callable using argument types (Result)

      points.remove(filter!(p => p.x > 7)(points[]));
      // test.d(33): Error: function
std.container.DList!(Point).DList.remove (Range r) is not
callable using argument types (FilterResult!(__lambda3, Range))

      points.linearRemove(filter!(p => p.x > 7)(points[]));
      // test.d(36): Error: template
std.container.DList!(Point).DList.linearRemove cannot deduce
function from argument types !()(FilterResult!(__lambda1,
Range)), candidates are:
      // /usr/include/dmd/phobos/std/container.d(2234):
std.container.DList!(Point).DList.linearRemove(R)(R r) if (is(R
== Range))
      // /usr/include/dmd/phobos/std/container.d(2240):
std.container.DList!(Point).DList.linearRemove(R)(R r) if (is(R
== Range))
      // /usr/include/dmd/phobos/std/container.d(2253):
std.container.DList!(Point).DList.linearRemove(R)(R r) if (is(R
== Take!Range))

      foreach (Point p; points) {
          if (p.x > 7) {
              //points.remove(/* Somehow get the range */);
              break;
          }
      }

      foreach (Point p; points) {
          writeln(p.x);
      }
}


Purpose is to remove one element that matches predicate, or any
amount really. Now DList.remove is defined as "Range remove(Range
r)" and filter is "auto filter(Range)(Range rs) if
(isInputRange!(Unqual!Range))" with explanation "The call
filter!(predicate)(range) returns a new range only containing
elements x in range for which predicate(x) is true." So if I
understand correctly, filter should return a range that I can
remove from the list. Why isn't this working?
Mar 07 2014
next sibling parent reply "newguy" <no.spam.please sorry.org> writes:
Text went nuts at least for me so here's raw pastebin of it
http://pastebin.com/raw.php?i=JfLFdsNj
Mar 07 2014
parent reply "newguy" <no.spam.please sorry.org> writes:
Ok, I got it working with

points.linearRemove(find!(p => p.x > 7)(points[]).take(1));

I thought takeOne would work and didn't thought of trying 
take(1), but I guess not. I also learned that containers don't 
accept filter results as a range so no problem, I can accept 
that. Still, feels quite complicated. I hope it's worth it in the 
long run :)
Mar 08 2014
parent "bearophile" <bearophileHUGS lycos.com> writes:
newguy:

 Still, feels quite complicated. I hope it's worth it in the 
 long run :)
It is complicated. Other parts of Phobos are both less complex and more useful. This means you have chosen a bad part of Phobos :-) Bye, bearophile
Mar 08 2014
prev sibling parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Friday, 7 March 2014 at 19:53:04 UTC, newguy wrote:
 I really can't wrap my head around these. I fought whole day
 trying to figure out how to do the simplest thing one can
 imagine: remove an element from a doubly linked list. Here's 
 what
 I've tried, see if there is a recurring mistake of thought or
 something:

 import std.stdio;
 import std.algorithm;
 import std.range;
 import std.container;

 struct Point {
      int x;
      int y;
 }

 void main() {
      DList!Point points;
      points.insert(Point(0,0));
      points.insert(Point(10,10));
      points.insert(Point(5,5));
      points.insert(Point(20,20));

      points.remove(takeOne(find!(p => p.x > 7)(points[])));
      // test.d(18): Error: function
 std.container.DList!(Point).DList.remove (Range r) is not
 callable using argument types (Result)

      points.linearRemove(takeOne(find!(p => p.x > 
 7)(points[])));
      // test.d(21): Error: template
 std.container.DList!(Point).DList.linearRemove cannot deduce
 function from argument types !()(Result), candidates are:
      // /usr/include/dmd/phobos/std/container.d(2234):
 std.container.DList!(Point).DList.linearRemove(R)(R r) if (is(R
 == Range))
      // /usr/include/dmd/phobos/std/container.d(2240):
 std.container.DList!(Point).DList.linearRemove(R)(R r) if (is(R
 == Range))
      // /usr/include/dmd/phobos/std/container.d(2253):
 std.container.DList!(Point).DList.linearRemove(R)(R r) if (is(R
 == Take!Range))

      points.remove(find!(p => p.x > 7)(points[]));
      // 0

      points.remove(takeOne(filter!(p => p.x > 7)(points[])));
      // test.d(30): Error: function
 std.container.DList!(Point).DList.remove (Range r) is not
 callable using argument types (Result)

      points.remove(filter!(p => p.x > 7)(points[]));
      // test.d(33): Error: function
 std.container.DList!(Point).DList.remove (Range r) is not
 callable using argument types (FilterResult!(__lambda3, Range))

      points.linearRemove(filter!(p => p.x > 7)(points[]));
      // test.d(36): Error: template
 std.container.DList!(Point).DList.linearRemove cannot deduce
 function from argument types !()(FilterResult!(__lambda1,
 Range)), candidates are:
      // /usr/include/dmd/phobos/std/container.d(2234):
 std.container.DList!(Point).DList.linearRemove(R)(R r) if (is(R
 == Range))
      // /usr/include/dmd/phobos/std/container.d(2240):
 std.container.DList!(Point).DList.linearRemove(R)(R r) if (is(R
 == Range))
      // /usr/include/dmd/phobos/std/container.d(2253):
 std.container.DList!(Point).DList.linearRemove(R)(R r) if (is(R
 == Take!Range))

      foreach (Point p; points) {
          if (p.x > 7) {
              //points.remove(/* Somehow get the range */);
              break;
          }
      }

      foreach (Point p; points) {
          writeln(p.x);
      }
 }


 Purpose is to remove one element that matches predicate, or any
 amount really. Now DList.remove is defined as "Range 
 remove(Range
 r)" and filter is "auto filter(Range)(Range rs) if
 (isInputRange!(Unqual!Range))" with explanation "The call
 filter!(predicate)(range) returns a new range only containing
 elements x in range for which predicate(x) is true." So if I
 understand correctly, filter should return a range that I can
 remove from the list. Why isn't this working?
std.container isn't great and hasn't received enough attention. There are plans to improve it, but I believe we're waiting on std.allocator and possibly a higher level layer on top of it before any significant revamp is made. It is perfectly usable in its current state however, just not always totally pleasant. Don't let this put you off std.algorithm and std.range, which are both very high quality.
Mar 09 2014
parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Sunday, 9 March 2014 at 09:06:51 UTC, John Colvin wrote:
 std.container isn't great and hasn't received enough attention. 
 There are plans to improve it, but I believe we're waiting on 
 std.allocator and possibly a higher level layer on top of it 
 before any significant revamp is made. It is perfectly usable 
 in its current state however, just not always totally pleasant.
 Don't let this put you off std.algorithm and std.range, which 
 are both very high quality.
Actually, DList is very hard to use.
Mar 11 2014