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