Why Ruby?
Nick Sabalausky
a at a.a
Fri Dec 17 10:00:27 PST 2010
"Stephan Soller" <stephan.soller at helionweb.de> wrote in message
news:ieg4c3$2o4q$1 at 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.
More information about the Digitalmars-d
mailing list