We need to have a way to say "convert this nested function into a struct"

Atila Neves via Digitalmars-d digitalmars-d at puremagic.com
Sat Jun 6 05:49:35 PDT 2015


On Saturday, 6 June 2015 at 06:59:26 UTC, Jonathan M Davis wrote:
> On Saturday, 6 June 2015 at 06:16:17 UTC, Andrei Alexandrescu 
> wrote:
>> Nested functions that allocate their environment dynamically 
>> can be quite useful. However, oftentimes the need is to 
>> convert the code plus the data needed into an anonymous struct 
>> that copies the state inside, similar to C++ lambdas that 
>> capture by value.
>>
>> I wonder how to integrate that within the language nicely.
>
> Some of us were discussing this at dconf. Essentially, we need 
> a way to create a functor similar to how C++ lambdas do. The 
> most straightforward way would involve string mixins, and you'd 
> do something like
>
> auto f = makeFunctor!"function code here"(arguments);
> auto result = range.algorithm!f();
>
> but that's not terribly pretty. Atila seemed to have figured 
> out how we could do it with std.functional.partial, but I was 
> too tired at the time to quite understand what his proposal 
> was. So, we may have something better there. Ideally, we'd be 
> able to just give a lambda, but that would put us right back in 
> the problem of a delegate being allocated unnecessarily (though 
> IIRC, Atila's suggestion somehow worked with lambdas and 
> partial without allocating; I wish that I could remember what 
> he proposed). But while it may or not be as pretty as we'd 
> like, I think that it's at last _possible_ for us to have a 
> shorthand for creating a functor by just providing the 
> function's body and arguments that hold the values for its 
> members. I'm certainly not against finding a language way to 
> make it prettier though, since I'm not sure how clean we can 
> really do it without language help.
>
> That being said, we really should find a way to make it so that 
> lambda's don't turn into delegates unless they really need to. 
> In many, many cases, they should be plenty efficient without 
> having to force the issue with functors, but they aren't, 
> because we allocate for them unnecessarily. I don't know how 
> easy it'll be though for the compiler devs to figure out how to 
> optimize that, since sometimes you _do_ need to allocate a 
> closure.
>
> But having a shorthand way to create functors would definitely 
> allow us to force the issue where necessary. And from what 
> Liran was saying at dconf, that alone would make it possible 
> for them to use a lot of Phobos that they can't right now. I 
> suspect that unnecessary closures are actually the main reason 
> that we have GC allocation problems with Phobos, since most 
> algorithms just don't explicitly involve allocation unless 
> they're doing array-specific stuff.
>
> - Jonathan M Davis

I remember the conversation but not really what I said. However, 
I just wrote this:


import std.stdio;
import std.algorithm;
import std.range;
import std.conv;
import std.traits;
import std.exception;


auto functorPartial(alias F, T)(T arg) {
     struct Functor {

         T arg;

         this(T args) { //because of opCall
             this.arg = arg;
         }

         auto opCall(U...)(U rest) {
             return F(arg, rest);
         }
     }

     return Functor(arg);
}

int adder(int i, int j) {
     return i + j;
}

void main(string[] args) {

     enforce(args.length > 1, "An argument must be passed in");

     auto arg = args[1].to!int; //to prove it's at runtime
     auto adderPartial = functorPartial!adder(arg); //runtime value
     writeln("adder result: ", adderPartial(4));

     //"subtracter"? "subtractor"? who cares
     auto subtracterPartial = functorPartial!((a, b) => a - 
b)(arg);
     writeln("subtracter partial: ", subtracterPartial(4));

}




More information about the Digitalmars-d mailing list