Use case for std.bind

Lars Kyllingstad public at kyllingen.NOSPAMnet
Tue Feb 24 06:04:04 PST 2009


Yigal Chripun wrote:
> Lars Kyllingstad wrote:
>> Yigal Chripun wrote:
>>> downs wrote:
>>>> Yigal Chripun wrote:
>>>>> Lars Kyllingstad wrote:
>>>>>> I've always thought currying was the main point of std.bind. If I'm
>>>>>> not
>>>>>> mistaken, currying is commonly a built-in feature of functional
>>>>>> programming languages, so if anything, std.bind could become more
>>>>>> useful/important in D2 than in D1.
>>>>>>
>>>>>> I agree that the std.bind API could and should be improved.
>>>>>>
>>>>>> -Lars
>>>>> you don't need bind for currying, it's even possible to do this in C:
>>>>>
>>>>> int foo(int a, int b) { ... }
>>>>> int bar(int a) { return foo(a, _value); } // curry with some _value
>>>>>
>>>>> Other languages provide useful syntax sugar for currying:
>>>>> auto bar2 = foo(_, 500);
>>>>>
>>>>> bar2 here will be a delegate that will do the the same as the above
>>>>> bar.
>>>>
>>>> Just for comparison' sake:
>>>>
>>>> auto dg =&foo /rfix/ somevar; // 1.0, tools
>>>> auto dg = _bind(&foo, _1, somevar); // 1.0, std.bind
>>>> auto dg = (int a) { return foo(a, somevar); }; // 2.0, literal
>>> auto dg = foo(_, somevar);
>>>
>>> So does that mean you like the above suggestion?
>>> after all, it's shorter and clearer than all the other alternatives.. ;)
>>
>> I for one like it, and would very much like to see such a syntax in D2.
>> Also, I'd have it work with either of a function's arguments, not only
>> the leading or trailing ones:
> 
>>
>> int foo(int a, int b, int c, int d) {...}
>> auto bar1 = foo(_, b, c, d);
>> auto bar2 = foo(a, b, c, _);
>> auto bar3 = foo(_, b, _, d);
>>
>> assert (is (typeof(bar3) == int delegate(int, int)));
> 
> no such restriction was intended. but that's good that you made this 
> clear. the only restriction here is re-ordering:
> bar3(A, C) will always call foo(A, b, C, d) but since it's just syntax 
> sugar and will be expanded by the language to the delegate literal this 
> is not a big deal - the user can always re-order arguments by using the 
> delegate literal syntax directly:
> 
> auto reordered_bar3 = (int C, int A) { return foo(A, b, C, d); };
> 
>>
>> In its simplest form, it would just be syntactic sugar for the delegate
>> literal. But I'm curious: If foo is a pure function, couldn't the
>> compiler perform some extra optimization here?
>>
>> -Lars
> 
> what kind of optimizations you had in mind?
> b & d in bar3 above can be specified at run-time so you can't avoid the 
> intermidiate delegate, I think.

I'm on thin ice here, I know, but consider the following simple example:

   pure real foo(real a, real b, real c)
   {
     auto tmp = sqrt(b + c);
     return tmp + a;
   }

   auto bar = foo(_, x, y);

Since bar now carries with it the last two arguments, it should in 
principle only have to calculate the square root once, i.e. the last 
line above would be equivalent to something like

   struct Bar
   {
     auto tmp;

     pure real bar(real a) { return tmp + a; }
   }

   auto bar = &Bar(sqrt(x+y)).bar;


-Lars



More information about the Digitalmars-d mailing list