www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - setIntersection of struct range

reply Jesse Phillips <jessekphillips+d gmail.com> writes:
I am trying to obtain a rang that is the intersection of two other ranges. To
do this I am using the _setIntersection()_ function.

    import std.algorithm;
    import std.stdio;

    struct S {
	string label;
    }

    void main() {
        auto s1 = new S[2];
        auto s2 = new S[2];

        s1[0].label = "fish";
        s1[1].label = "bar";
        s2[0].label = "foo";
        s2[1].label = "fish";

        foreach(str; setIntersection(s1,s2))
            writeln(str);
    }

The code above generates this error:

     C:\opt\dmd\windows\bin\..\..\src\phobos\std\functional.d(191):
          Error: static assert  "Bad binary function q{a < b}. 
             You need to use a valid D expression using symbols a of type S and
b of type S."

So I attempted an intersection of string arrays, and received a different
error. I'm not sure if I am at fault or the compiler. Shouldn't these work?

    import std.algorithm;
    import std.stdio;
    import std.array;

    struct S {
        string label;
    }

    void main() {
        auto s1 = ["fish", "bar"];
        auto s2 = ["foo", "fish"];

        foreach(str; setIntersection(s1,s2))
            writeln(str);
    }

Which ended up with:

    test.d(13): Error: template std.algorithm.setIntersection(alias less = "a <
b",Rs...)
        if (allSatisfy!(isInputRange,Rs)) does not match any function template
declaration
    test.d(13): Error: template std.algorithm.setIntersection(alias less = "a <
b",Rs...)
        if (allSatisfy!(isInputRange,Rs)) cannot deduce template function from
        argument types !()(immutable(char)[][2u],immutable(char)[][2u])
    test.d(13): Error: foreach: int is not an aggregate type
Aug 11 2009
next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 11 Aug 2009 19:35:40 -0400, Jesse Phillips  
<jessekphillips+d gmail.com> wrote:

 I am trying to obtain a rang that is the intersection of two other  
 ranges. To do this I am using the _setIntersection()_ function.

     import std.algorithm;
     import std.stdio;

     struct S {
 	string label;
     }

     void main() {
         auto s1 = new S[2];
         auto s2 = new S[2];

         s1[0].label = "fish";
         s1[1].label = "bar";
         s2[0].label = "foo";
         s2[1].label = "fish";

         foreach(str; setIntersection(s1,s2))
             writeln(str);
     }

 The code above generates this error:

      C:\opt\dmd\windows\bin\..\..\src\phobos\std\functional.d(191):
           Error: static assert  "Bad binary function q{a < b}.
              You need to use a valid D expression using symbols a of  
 type S and b of type S."
You did not define a way to compare two S structs. Try redefining S like this: struct S { string label; int opCmp(ref const S s2) const { if(label < s2.label) return -1; if(label > s2.label) return 1; return 0; } }
 So I attempted an intersection of string arrays, and received a  
 different error. I'm not sure if I am at fault or the compiler.  
 Shouldn't these work?

     import std.algorithm;
     import std.stdio;
     import std.array;

     struct S {
         string label;
     }

     void main() {
         auto s1 = ["fish", "bar"];
         auto s2 = ["foo", "fish"];

         foreach(str; setIntersection(s1,s2))
             writeln(str);
     }

 Which ended up with:

     test.d(13): Error: template std.algorithm.setIntersection(alias less  
 = "a < b",Rs...)
         if (allSatisfy!(isInputRange,Rs)) does not match any function  
 template declaration
     test.d(13): Error: template std.algorithm.setIntersection(alias less  
 = "a < b",Rs...)
         if (allSatisfy!(isInputRange,Rs)) cannot deduce template  
 function from
         argument types !()(immutable(char)[][2u],immutable(char)[][2u])
I think it's expecting dynamc arrays, not static ones. Auto is making them static. Try explicitly defining s1 and s2 as string[] or slice the literal, typing them as dynamic arrays like this: auto s1 = ["fish", "bar"][]; auto s2 = ["foo", "fish"][];
     test.d(13): Error: foreach: int is not an aggregate type
This is a dummy error because it couldn't figure out the type of setIntersection, so it just assumes int (a quirk of dmd). -Steve
Aug 12 2009
next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Wed, 12 Aug 2009 11:25:10 -0400, Steven Schveighoffer  
<schveiguy yahoo.com> wrote:

 I think it's expecting dynamc arrays, not static ones.  Auto is making  
 them static.
BTW, this probably should not be true, I would guess that static arrays should be intersectable, of course the return type would have to be a dynamic array. When will static arrays be first class? *sigh* -Steve
Aug 12 2009
prev sibling parent reply Jesse Phillips <jessekphillips+d gmail.com> writes:
Steven Schveighoffer Wrote:

 You did not define a way to compare two S structs.  Try redefining S like  
 this:
 
 struct S {
    string label;
    int opCmp(ref const S s2) const {
       if(label < s2.label)
         return -1;
       if(label > s2.label)
         return 1;
       return 0;
    }
 }
You know, I didn't think about this because struct arrays are sorted by the first element if you do array.sort. But this does make the error a little more clear.
Aug 12 2009
parent Jesse Phillips <jessekphillips+d gmail.com> writes:
Jesse Phillips Wrote:

 Steven Schveighoffer Wrote:
 
 You did not define a way to compare two S structs.  Try redefining S like  
 this:
 
 struct S {
    string label;
    int opCmp(ref const S s2) const {
       if(label < s2.label)
         return -1;
       if(label > s2.label)
         return 1;
       return 0;
    }
 }
You know, I didn't think about this because struct arrays are sorted by the first element if you do array.sort. But this does make the error a little more clear.
Got around to trying this, but it didn't fix the problem.
Aug 12 2009
prev sibling parent Sergey Gromov <snake.scaly gmail.com> writes:
Tue, 11 Aug 2009 19:35:40 -0400, Jesse Phillips wrote:

 I am trying to obtain a rang that is the intersection of two other ranges. To
do this I am using the _setIntersection()_ function.
 
     import std.algorithm;
     import std.stdio;
 
     struct S {
 	string label;
     }
 
     void main() {
         auto s1 = new S[2];
         auto s2 = new S[2];
 
         s1[0].label = "fish";
         s1[1].label = "bar";
         s2[0].label = "foo";
         s2[1].label = "fish";
 
         foreach(str; setIntersection(s1,s2))
             writeln(str);
     }
 
 The code above generates this error:
 
      C:\opt\dmd\windows\bin\..\..\src\phobos\std\functional.d(191):
           Error: static assert  "Bad binary function q{a < b}. 
              You need to use a valid D expression using symbols a of type S
and b of type S."
Looks like a compiler bug/feature to me. The following is a reduced test case: import std.functional; struct S { string label; } void main() { auto f1 = &binaryFunImpl!("a < b", "a", "b").result!(int, int); auto f2 = &binaryFunImpl!("a.label < b.label", "a", "b").result!(S, S); } Compiled with dmd2 test.d: C:\opt\dmd.2.031\windows\bin\..\..\src\phobos\std\functional.d(191): Error: static assert "Bad binary function q{a.label < b.label}. You need to use a valid D expression using symbols a of ty pe S and b of type S." Note that int,int passes while S,S fails.
Aug 12 2009