digitalmars.D.bugs - [Issue 3217] New: std.functional.binaryFunImpl doesn't support UDT with string functions , therefore neither does many std.algorithm functions
- d-bugmail puremagic.com (147/147) Jul 30 2009 http://d.puremagic.com/issues/show_bug.cgi?id=3217
- d-bugmail puremagic.com (10/10) Jul 30 2009 http://d.puremagic.com/issues/show_bug.cgi?id=3217
- d-bugmail puremagic.com (12/12) Aug 28 2009 http://d.puremagic.com/issues/show_bug.cgi?id=3217
http://d.puremagic.com/issues/show_bug.cgi?id=3217 Summary: std.functional.binaryFunImpl doesn't support UDT with string functions , therefore neither does many std.algorithm functions Product: D Version: 2.031 Platform: x86 OS/Version: Windows Status: NEW Keywords: patch Severity: major Priority: P2 Component: Phobos AssignedTo: nobody puremagic.com ReportedBy: sandford jhu.edu std.functional.binaryFunImpl doesn't support user defined data types. As this is used by many functions in std.algorithm, it represents a major loss of function. import std.functional; import std.algorithm; struct foo{ foo opAdd(foo f) { return this; } } void main(char[][] args) { foo[] foos = new foo[5]; // binaryFunImpl!("a + b","a","b").Body!(foo,foo); // writeln( reduce!"a + b"(foos) ); // C:\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 foo and b of type foo."| // This is the failed static if // static if (__traits(compiles, mixin(testAsExpression))) // and testAsExpression equals // {foo a; foo b; return (a + b);}() static assert(__traits(compiles, mixin("{foo a; foo b; return (a + b);}()")) == true ); static if (__traits(compiles, mixin("{foo a; foo b; return (a + b);}()"))) // okay static assert(true); else static assert(false); return; } I tried replacing ElementType1.stringof with "ElementType1", ElementType2.stringof with , "ElementType2" which seemed to work: The patch in brief: enum testAsExpression = "{ ElementType1 " ~parm1Name~"; ElementType2 " ~parm2Name~"; return ("~fun~");}()"; The patch in full: template binaryFunImpl(alias fun, string parm1Name, string parm2Name) { static if (is(typeof(fun) : string)) { template Body(ElementType1, ElementType2) { enum testAsExpression = "{ ElementType1 " ~parm1Name~"; ElementType2 " ~parm2Name~"; return ("~fun~");}()"; enum testAsStmts = "{ "~ElementType1.stringof~" " ~parm1Name~"; "~ElementType2.stringof~" " ~parm2Name~"; "~fun~"}()"; static if (__traits(compiles, mixin(testAsExpression))) { enum string code = "return (" ~ fun ~ ");"; alias typeof(mixin(testAsExpression)) ReturnType; } // else static if (__traits(compiles, mixin(testAsStmts))) // { // enum string code = fun; // alias typeof(mixin(testAsStmts)) ReturnType; // } else { // Credit for this idea goes to Don Clugston enum string msg = "Bad binary function q{" ~ fun ~ "}." ~" You need to use a valid D expression using symbols " ~parm1Name~" of type "~ElementType1.stringof~" and " ~parm2Name~" of type "~ElementType2.stringof~"." ~(fun.length && fun[$ - 1] == ';' ? " The trailing semicolon is _not_ needed." : "") ~(fun.length && fun[$ - 1] == '}' ? " The trailing bracket is mistaken." : ""); static assert(false, msg); } } Body!(ElementType1, ElementType2).ReturnType result(ElementType1, ElementType2) (ElementType1 __a, ElementType2 __b) { mixin("alias __a "~parm1Name~";"); mixin("alias __b "~parm2Name~";"); mixin(Body!(ElementType1, ElementType2).code); } } else { alias fun result; } // static if (is(typeof(comp) : string)) // { // // BUG1816 : typeof(mixin(comp)) should work // typeof({ // static ElementType1 a; // static ElementType2 b; // return mixin(comp); // }()) // binaryFun(ElementType1, ElementType2) // (ElementType1 a, ElementType2 b) // { // return mixin(comp); // } // } // else // { // alias comp binaryFun; // } } The patch passes the unittests in functional.d. i.e. unittest { alias binaryFun!(q{a < b}) less; assert(less(1, 2) && !less(2, 1)); assert(less("1", "2") && !less("2", "1")); static int f1(int a, string b) { return a + 1; } static assert(is(typeof(binaryFun!(f1)(1, "2")) == int)); assert(binaryFun!(f1)(41, "a") == 42); string f2(int a, string b) { return b ~ "2"; } static assert(is(typeof(binaryFun!(f2)(1, "1")) == string)); assert(binaryFun!(f2)(1, "4") == "42"); assert(binaryFun!("a + b")(41, 1) == 42); // BUG //assert(binaryFun!("return a + b;")(41, 1) == 42); } As a note, unaryFunImpl uses "{ ElementType " as well, and it looks like testAsStmts is dead code in each (grepping the source tree only turned up he definition in functional.d). As testAsStmts also uses .stringof, which seems to be wrong, I'd recommend either fixing or removing it in both templates. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jul 30 2009
http://d.puremagic.com/issues/show_bug.cgi?id=3217 Andrei Alexandrescu <andrei metalanguage.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|NEW |ASSIGNED CC| |andrei metalanguage.com AssignedTo|nobody puremagic.com |andrei metalanguage.com -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jul 30 2009
http://d.puremagic.com/issues/show_bug.cgi?id=3217 Andrei Alexandrescu <andrei metalanguage.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|ASSIGNED |RESOLVED Resolution| |FIXED 09:21:34 PDT --- Ok, thanks. I've integrated the patch. As for testAsStmts, it used to crash the compiler so I'm leaving it commented (albeit corrected) for now. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Aug 28 2009