Thread overview | ||||||||
---|---|---|---|---|---|---|---|---|
|
August 11, 2009 setIntersection of struct range | ||||
---|---|---|---|---|
| ||||
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 |
August 12, 2009 Re: setIntersection of struct range | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jesse Phillips | 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 |
August 12, 2009 Re: setIntersection of struct range | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | 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
|
August 12, 2009 Re: setIntersection of struct range | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | 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.
|
August 12, 2009 Re: setIntersection of struct range | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jesse Phillips | 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.
|
August 12, 2009 Re: setIntersection of struct range | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jesse Phillips | 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. |
Copyright © 1999-2021 by the D Language Foundation