digitalmars.D - One case of careless opDispatch :)
- Dmitry Olshansky (54/54) Jul 15 2010 As a practical habit, once I stumble upon a very tricky error, I usually...
- Robert Jacques (5/57) Jul 15 2010 :) I've run into this before, with other compile-time tests such as
- =?iso-8859-2?B?VG9tZWsgU293afFza2k=?= (7/10) Jul 23 2010 o =
- Nick Sabalausky (3/10) Jul 15 2010 Duck typing == TROUBLE
As a practical habit, once I stumble upon a very tricky error, I usually share the valuable knowledge of "when you do this ... and get that ... it's probably because ... " Damn, sometimes they can even become cool quizzes... So to warn those oblivious to the dangers of opDispatch, here is my the yesterday nightmare, the striped down code below. import std.algorithm; import std.array; class Widget { string _name; Widget[] _children; this(in string name){ _name = name.idup; } Widget opDispatch(string nm)(){ auto r = find!((Widget c){ return c._name == nm; })(_children); return r.front(); } } void main(){ Widget g = new Widget("G"); Widget warr[] = [new Widget("W"),g]; find(warr,g); } produces: Error 1 Error: template std.algorithm.startsWith(alias pred = "a == b",Range,Ranges...) if (isInputRange!(Range) && Ranges.length > 0 && is(typeof(binaryFun!(pred)(doesThisStart.front,withOneOfThese[0].front)))) startsWith(alias pred = "a == b",Range,Ranges...) if (isInputRange!(Range) && Ranges.length > 0 && is(typeof(binaryFun!(pred)(doesThisStart.front,withOneOfThese[0].front)))) matches more than one template declaration, C:\dmd2\windows\bin\..\..\src\phobos\std\algorithm.d(1892):startsWith(alias pred = "a == b",Range,Ranges...) if (isInputRange!(Range) && Ranges.length > 0 && is(typeof(binaryFun!(pred)(doesThisStart.front,withOneOfThese[0].front)))) and C:\dmd2\windows\bin\..\..\src\phobos\std\algorithm.d(1980):startsWith(alias pred = "a == b",Range,Elements...) if (isInputRange!(Range) && Elements.length > 0 && is(typeof(binaryFun!(pred)(doesThisStart.front,withOneOfThese[0])))) C:\dmd2\windows\bin\..\..\src\phobos\std\algorithm.d 1488 The tricky part is that *any* class with unconstrained (or loosely constrained) opDispatch is also a Range, and at least a bidirectional one, since it "provides" all the primitives: front, popFront etc. In fact such classes could penetrate almost any attempts at C++ trait-like stuff and should be avoided. The moral: unconstrainted opDispatch == TROUBLE. Hope that helps! P.S. Strangely enough, that problem haven't showed up until update to 2.047 release, so it's probably detonated by some changes to Phobos. I guess better sooner than later. -- Dmitry Olshansky
Jul 15 2010
On Thu, 15 Jul 2010 15:34:23 -0400, Dmitry Olshansky <dmitry.olsh gmail.com> wrote:As a practical habit, once I stumble upon a very tricky error, I usually share the valuable knowledge of "when you do this ... and get that ... it's probably because ... " Damn, sometimes they can even become cool quizzes... So to warn those oblivious to the dangers of opDispatch, here is my the yesterday nightmare, the striped down code below. import std.algorithm; import std.array; class Widget { string _name; Widget[] _children; this(in string name){ _name = name.idup; } Widget opDispatch(string nm)(){ auto r = find!((Widget c){ return c._name == nm; })(_children); return r.front(); } } void main(){ Widget g = new Widget("G"); Widget warr[] = [new Widget("W"),g]; find(warr,g); } produces: Error 1 Error: template std.algorithm.startsWith(alias pred = "a == b",Range,Ranges...) if (isInputRange!(Range) && Ranges.length > 0 && is(typeof(binaryFun!(pred)(doesThisStart.front,withOneOfThese[0].front)))) startsWith(alias pred = "a == b",Range,Ranges...) if (isInputRange!(Range) && Ranges.length > 0 && is(typeof(binaryFun!(pred)(doesThisStart.front,withOneOfThese[0].front)))) matches more than one template declaration, C:\dmd2\windows\bin\..\..\src\phobos\std\algorithm.d(1892):startsWith(alias pred = "a == b",Range,Ranges...) if (isInputRange!(Range) && Ranges.length > 0 && is(typeof(binaryFun!(pred)(doesThisStart.front,withOneOfThese[0].front)))) and C:\dmd2\windows\bin\..\..\src\phobos\std\algorithm.d(1980):startsWith(alias pred = "a == b",Range,Elements...) if (isInputRange!(Range) && Elements.length > 0 && is(typeof(binaryFun!(pred)(doesThisStart.front,withOneOfThese[0])))) C:\dmd2\windows\bin\..\..\src\phobos\std\algorithm.d 1488 The tricky part is that *any* class with unconstrained (or loosely constrained) opDispatch is also a Range, and at least a bidirectional one, since it "provides" all the primitives: front, popFront etc. In fact such classes could penetrate almost any attempts at C++ trait-like stuff and should be avoided. The moral: unconstrainted opDispatch == TROUBLE. Hope that helps! P.S. Strangely enough, that problem haven't showed up until update to 2.047 release, so it's probably detonated by some changes to Phobos. I guess better sooner than later.:) I've run into this before, with other compile-time tests such as isAssociativeArray. Often, the real bug is the tests themselves are too permissive.
Jul 15 2010
Dnia 15-07-2010 o 21:52:56 Robert Jacques <sandford jhu.edu> napisa=B3(a= ):I've run into this before, with other compile-time tests such as =isAssociativeArray. Often, the real bug is the tests themselves are to=o =permissive.Yes. I think isSomeRange should check that pop(Front|Back) returns void.= = opDispatch couldn't stand for a range interface just by mistake. Tomek
Jul 23 2010
"Dmitry Olshansky" <dmitry.olsh gmail.com> wrote in message news:i1nns8$d4g$1 digitalmars.com...The tricky part is that *any* class with unconstrained (or loosely constrained) opDispatch is also a Range, and at least a bidirectional one, since it "provides" all the primitives: front, popFront etc. In fact such classes could penetrate almost any attempts at C++ trait-like stuff and should be avoided. The moral: unconstrainted opDispatch == TROUBLE. Hope that helps!Duck typing == TROUBLE
Jul 15 2010