View mode: basic / threaded / horizontal-split · Log in · Help
October 20, 2008
Re: Partial argument specification
downs wrote:
> Lars Kyllingstad wrote:
>> downs wrote:
>>> Lars Kyllingstad wrote:
>>>> Hello,
>>>> There is a feature I would very much like to see in D. I don't know if
>>>> it has been discussed before, or whether is's even possible, but I'm
>>>> just going to throw it out here. Please tell me what you think.
>>>> Suppose you have a function that takes a certain number of arguments,
>>>> say
>>>>   creal f(real x, int i);
>>>> Then it would be neat if one could specify just some of the arguments,
>>>> and have the result be a pointer to a function that takes the remaining
>>>> arguments. To clarify, the type of
>>>>   f(real, 2)
>>>> would then be
>>>>   creal function(real)
>>>> Why would this be nice? As an example, say you have a function that
>>>> calculates the derivative of another function at a certain point:
>>>>   real derivative(real function(real), real z);
>>>> With the above notation I can use this for functions of several
>>>> variables:
>>>>   real f(real x, real y) { ... };
>>>>   auto dfdx = derivative( f(real, 1.23), 4.56 );
>>>> As an added bonus, I can even differentiate with respect to y:
>>>>   auto dfdy = derivative( f(1.23, real), 4.56 );
>>>> Already, there are several ways to do similar things, but in my opinion
>>>> they are not as good:
>>>> 1. Use templates
>>>> Nice, but only works when the pre-specified arguments are known at
>>>> compile time. (Or is there some trick I don't know about?)
>>>> 2. Use functors
>>>> This works, but leads to worse performance and is in my opinion less
>>>> elegant. One has to type a lot of code just to define simple functions.
>>>> 3. Use wrapper functions
>>>> Same problems as (2), and also leads to use of global variables.
>>>> 4. The GSL way: Pass remaining arguments in a void* pointer.
>>>> Example:
>>>>   real derivative(real function(real, void*), real z);
>>>> IMO, this is UGLY, not to mention un-D-ish.
>>>> I mainly use D for numerical computations, hence the examples above. But
>>>> I'm sure there are many other uses for such a feature. What do you
>>>> think?
>>>> -Lars
>>> How about an implicit functor?
>>> creal f(real x, int i);
>>> auto f2 = bind(&f, _0, 2); // I think
>>> auto f2 = &f /rfix/ 2; // tools version
>>> This creates a functor on the heap, and is indeed slower, but it's
>>> more elegant than you make it sound :)
>> Ok, but say I want to do this several times:
>>   for (real y=yStart; y<=yEnd; y+=yStep)
>>       derivative(&f /rfix/ y, 1.23);
>> Would it be any faster if your /rfix/ (or a similar function) created
>> the functor on the stack instead?
>> -Lars
> Yes, but how could it possibly do that?
> After all, then the data would become invalid on scope exit, which is exactly what we're trying to avoid!

I'm not sure I understand. Wouldn't it be possible to do something like 

  struct FunctionWrapper
    SomeType opCall(...) { ... }

and then have /rfix/ (or bind) return a FunctionWrapper? Of course it 
would have to return by value instead of returning a pointer, since 
whatever is pointed to will be lost on scope exit. If there are no 
pointers to stack data inside the struct there shouldn't be a problem. 
Don't know if it's possible to avoid this, though.

But perhaps the cost of returning a (possibly large) struct by value 
would outweigh the cost of calling functors on the heap? I guess it 
depends on how many times a single functor is called, compared to how 
often a new one is created.

Next ›   Last »
1 2
Top | Discussion index | About this forum | D home