www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - First experience with std.algorithm: I had to resort to writing a

reply Bernard Helyer <b.helyer gmail.com> writes:
So I'm writing a compiler, and I wanted to create a list of TokenTypes 
(an enum) and check to see if the current token is among them. 'A-ha!', 
says I, 'I'll use std.algorithm!' (as I hadn't tried it really, yet, 
except for playing around)
So I look it up, and find 'find'. It returns an iterated range, or an 
empty range on failure. A little funky, but that's okay, I can swing it!

immutable TokenType[] someList = [TokenType.Foo, TokenType.Bar];

...

while (find(someList, tokenStream.peek.type) != []) {
    doStuff();
}

If I have unittests on, this assert is triggered:

static assert(is(typeof(s) == Tuple!(string, float)));

I didn't at first, so I got another error. So I looked closer at the 
documentation, and it turns out it needs an input range, and that needs 
popFront! Well, it can't popFront an immutable range, so I dropped 
immutable, and decided to let convention and TLS sort the rest out!

This worked. Until I turned unittests on, and the assert I showed above 
tripped. At this point my language turned rather unpleasant and I wrote 
this:

bool contains(T)(const(T)[] l, T a)
{
      foreach(e; l) {
          if (a == e) {
             return true;
          }
      }
      return false;
}

And my problems went away. I assume what I experienced is a bug, but I'm 
not sure, so I thought I'd share my experience.
Jun 08 2010
next sibling parent "Lars T. Kyllingstad" <public kyllingen.NOSPAMnet> writes:
On Tue, 08 Jun 2010 23:23:39 +1200, Bernard Helyer wrote:

 [...]
 
 If I have unittests on, this assert is triggered:
 
 static assert(is(typeof(s) == Tuple!(string, float)));
 
 [...]
 
 And my problems went away. I assume what I experienced is a bug, but I'm
 not sure, so I thought I'd share my experience.

Would it be this bug, perhaps? http://d.puremagic.com/issues/show_bug.cgi?id=4294 It was just reported, following the discussion in the "Tuple to tuple conversion" thread on D.learn. It's a really annoying bug which I've come across a few times, and I'm glad Simen has been able to narrow it down so much. -Lars
Jun 08 2010
prev sibling next sibling parent reply Alex Makhotin <alex bitprox.com> writes:
Bernard Helyer wrote:
 
 This worked. Until I turned unittests on, and the assert I showed above 
 tripped. At this point my language turned rather unpleasant and I wrote 
 this:
 
 bool contains(T)(const(T)[] l, T a)
 {
      foreach(e; l) {
          if (a == e) {
             return true;
          }
      }
      return false;
 }
 
 And my problems went away. I assume what I experienced is a bug, but I'm 
 not sure, so I thought I'd share my experience.

I want you to know that you are not the only one who makes such decisions. I have almost the same method, except it returns an index value. That is not the only one reason I wanted a std library with clear and documented interfaces. Generally I use std library to make writeln, thread wrapper around OS, and string conversions. I do not want to use std.algorithm. -- Alex Makhotin, the founder of BITPROX, http://bitprox.com
Jun 08 2010
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 06/08/2010 08:31 AM, Alex Makhotin wrote:
 Bernard Helyer wrote:
 This worked. Until I turned unittests on, and the assert I showed
 above tripped. At this point my language turned rather unpleasant and
 I wrote this:

 bool contains(T)(const(T)[] l, T a)
 {
 foreach(e; l) {
 if (a == e) {
 return true;
 }
 }
 return false;
 }

 And my problems went away. I assume what I experienced is a bug, but
 I'm not sure, so I thought I'd share my experience.

I want you to know that you are not the only one who makes such decisions. I have almost the same method, except it returns an index value. That is not the only one reason I wanted a std library with clear and documented interfaces. Generally I use std library to make writeln, thread wrapper around OS, and string conversions. I do not want to use std.algorithm.

If you could frame that as a requirement, I'd be glad to look into improving std.algorithm. (BTW. std.algorithm has had indexOf for a while, I haven't checked in that yet.) Andrei
Jun 08 2010
prev sibling next sibling parent "Lars T. Kyllingstad" <public kyllingen.NOSPAMnet> writes:
On Tue, 08 Jun 2010 23:23:39 +1200, Bernard Helyer wrote:

 [...]
 
 immutable TokenType[] someList = [TokenType.Foo, TokenType.Bar];
 
 ...
 
 while (find(someList, tokenStream.peek.type) != []) {
     doStuff();
 }
 
 If I have unittests on, this assert is triggered:
 
 static assert(is(typeof(s) == Tuple!(string, float)));
 
 I didn't at first, so I got another error. So I looked closer at the
 documentation, and it turns out it needs an input range, and that needs
 popFront! Well, it can't popFront an immutable range, so I dropped
 immutable, and decided to let convention and TLS sort the rest out!

Actually, there is no reason this shouldn't be possible. This works: import std.array: popFront; immutable(int)[] tail(immutable(int)[] list) { list.popFront(); return list; } void main() { immutable a = [0, 1, 2, 3]; assert (tail(a) == [1, 2, 3]); } The problem is that find()'s parameters are templated, so when you give it an immutable(int[]), it doesn't know it's safe to treat it as an immutable(int)[]. find() should probably be improved to allow this. I'm sure this won't be the last time someone tries to search an immutable array. -Lars
Jun 08 2010
prev sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 08 Jun 2010 07:23:39 -0400, Bernard Helyer <b.helyer gmail.com>  
wrote:

 So I'm writing a compiler, and I wanted to create a list of TokenTypes  
 (an enum) and check to see if the current token is among them. 'A-ha!',  
 says I, 'I'll use std.algorithm!' (as I hadn't tried it really, yet,  
 except for playing around)
 So I look it up, and find 'find'. It returns an iterated range, or an  
 empty range on failure. A little funky, but that's okay, I can swing it!

 immutable TokenType[] someList = [TokenType.Foo, TokenType.Bar];

 ...

 while (find(someList, tokenStream.peek.type) != []) {
     doStuff();
 }

 If I have unittests on, this assert is triggered:

 static assert(is(typeof(s) == Tuple!(string, float)));

 I didn't at first, so I got another error. So I looked closer at the  
 documentation, and it turns out it needs an input range, and that needs  
 popFront! Well, it can't popFront an immutable range, so I dropped  
 immutable, and decided to let convention and TLS sort the rest out!

This should be filed as a bug. find should be able to strip the immutable part from the array length itself since immutable T[] implicitly casts to immutable(T)[]. I think this should be special cased. For custom ranges, it's not as easy, but array should be supported as well as is possible.
 This worked. Until I turned unittests on, and the assert I showed above  
 tripped. At this point my language turned rather unpleasant and I wrote  
 this:

 bool contains(T)(const(T)[] l, T a)
 {
       foreach(e; l) {
           if (a == e) {
              return true;
           }
       }
       return false;
 }

 And my problems went away. I assume what I experienced is a bug, but I'm  
 not sure, so I thought I'd share my experience.

As D2 nears release, and is used more and more, I'm sure we will find many problems. It's sort of a chicken-and-egg thing, people don't want to use D2 because it's changing so much, but when nobody uses it, nobody finds any bugs until it's finalized! I suspect at least one more change to const is necessary to take away the pain :) -Steve
Jun 08 2010
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 06/08/2010 08:45 AM, Steven Schveighoffer wrote:
 On Tue, 08 Jun 2010 07:23:39 -0400, Bernard Helyer <b.helyer gmail.com>
 wrote:

 So I'm writing a compiler, and I wanted to create a list of TokenTypes
 (an enum) and check to see if the current token is among them.
 'A-ha!', says I, 'I'll use std.algorithm!' (as I hadn't tried it
 really, yet, except for playing around)
 So I look it up, and find 'find'. It returns an iterated range, or an
 empty range on failure. A little funky, but that's okay, I can swing it!

 immutable TokenType[] someList = [TokenType.Foo, TokenType.Bar];

 ...

 while (find(someList, tokenStream.peek.type) != []) {
 doStuff();
 }

 If I have unittests on, this assert is triggered:

 static assert(is(typeof(s) == Tuple!(string, float)));

 I didn't at first, so I got another error. So I looked closer at the
 documentation, and it turns out it needs an input range, and that
 needs popFront! Well, it can't popFront an immutable range, so I
 dropped immutable, and decided to let convention and TLS sort the rest
 out!

This should be filed as a bug. find should be able to strip the immutable part from the array length itself since immutable T[] implicitly casts to immutable(T)[]. I think this should be special cased. For custom ranges, it's not as easy, but array should be supported as well as is possible.

I agree. Someone please file this so it doesn't fall through the cracks. Andrei
Jun 08 2010