"Stephan Soller" <stephan.sol...@helionweb.de> wrote in message news:ieg4c3$2o4...@digitalmars.com... > On 16.12.2010 20:01, Jacob Carlborg wrote: >> On 2010-12-15 17:06, Stephan Soller wrote: >>> On 14.12.2010 20:03, Jacob Carlborg wrote: > >> . > >> >>>What's more important >>> (at least for me) is the chaining ability and how performant such >>> delegates actually are. From what I understood from std.functional it >>> wraps string expressions in delegates anyway so using >>> >>> ary.map!("a*a"); >>> >>> is not more efficient. Please correct me if I'm wrong! The >>> std.functional code is definitely above my understanding. >> >> I would though it just mixed in the string with some other code to make >> a complete expression. >> > > It does that (would there be another way?). The question is if it creates > an delegate with the expression or does it not built a delegate? The code > in question starts at line 78 of std/functional.d[1] (that is the code > related to unaryFun!()). > > I'm really not sure what this code does. > > [1]: > http://www.dsource.org/projects/phobos/browser/trunk/phobos/std/functional.d#L78 >
I checked into this. The short answer is: It seems to generate an ordinary free-standing function (that gets passed around as various aliases), but not a delegate. Overview: 1. In std.functional: The string gets mixed into a function named "result" that's inside the "unaryFunImpl" template, ie the code gets mixed into the free-standing function "unaryFunImpl.result()". 2. Then, "unaryFun" is an alias to "unaryFunImpl.result()". 3. In std.algorithm: "map()" is a function that simply calls the ctor of the "Map" struct, passing in the "unaryFunImpl.result" function as a template alias param that "Map" calls "fun". 4. Inside the "Map" struct, "fun" gets aliased to "_fun" for some reason, and then gets called at various points. Some Details: I took DMD 2.050, modified std/functional.d by changing this: static if (byRef) { Body!(ElementType).ReturnType result(ElementType)(ref ElementType a) { mixin(Body!(ElementType).code); } } else { Body!(ElementType).ReturnType result(ElementType)(ElementType __a) { mixin("alias __a "~parmName~";"); mixin(Body!(ElementType).code); } // string mixme = "Body!(ElementType).ReturnType" // " result(ElementType)(ElementType a) // { " ~ Body!(ElementType).code ~ " }"; // mixin(mixme); } ...To this: static if (byRef) { Body!(ElementType).ReturnType result(ElementType)(ref ElementType a) { pragma(msg, "generated inside unaryFunImpl:"); pragma(msg, Body!(ElementType).code); mixin(Body!(ElementType).code); } } else { Body!(ElementType).ReturnType result(ElementType)(ElementType __a) { pragma(msg, "generated inside unaryFunImpl:"); pragma(msg, "alias __a "~parmName~";"); pragma(msg, Body!(ElementType).code); mixin("alias __a "~parmName~";"); mixin(Body!(ElementType).code); } // string mixme = "Body!(ElementType).ReturnType" // " result(ElementType)(ElementType a) // { " ~ Body!(ElementType).code ~ " }"; // mixin(mixme); } All I changed was added the pragmas. Then I used it to compile this: import std.algorithm; void main() { auto x = map!"a + 10"([1, 2, 3, 4]); } And the compiler's output was: generated inside unaryFunImpl: alias __a a; return (a + 10); So the result() function inside the unaryFunImpl template ends up looking like this: Body!(ElementType).ReturnType result(ElementType)(ElementType __a) { alias __a a; return (a + 10); } And then, as I described above, that function gets passed around via various aliases and then called directly.