Partial argument specification

Bill Baxter wbaxter at gmail.com
Fri Oct 17 15:20:21 PDT 2008


On Sat, Oct 18, 2008 at 7:05 AM, Robert Fraser
<fraserofthenight at gmail.com> wrote:
> Bill Baxter wrote:
>>
>> On Fri, Oct 17, 2008 at 8:51 PM, Denis Koroskin <2korden at gmail.com> wrote:
>>>
>>> Lars Kyllingstad <public at kyllingen.nospamnet> писал(а) в своём письме
>>> Fri,
>>> 17 Oct 2008 15:27:52 +0400:
>>>
>>>> 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)
>>>>
>>> You *have to* store an "int i" parameter somewhere unless you want to be
>>> a
>>> compile time constant. Use a template in this case. Alternatively use a
>>> struct or class wrapper. Struct won't allocate heap, class gives more
>>> flexibility. Delegates allow contruction on-fly without (even more
>>> flexibility) at the cost of additional overhead.
>>>
>>> I'd go with delegates unless the performance degrade drastically.
>>>
>>> // use of delegates:
>>> creal delegate(real) f2 = (real x){ return f(x, 2); }
>>> real x = ...;
>>> creal result = f2(x); // same as f(x, 2);
>>>
>>> // use of a class wrapper:
>>> class F
>>> {
>>>   this(int i) { this.i = i; }
>>>   creal opCall(real x) { return f(x, i); }
>>>   private int i;
>>> }
>>>
>>> F f2 = new F(2);
>>> real x = ...;
>>> creal result = f2(x); // same as f(x, 2);
>>>
>>> // struct wrapper
>>> struct F2
>>> {
>>>   int i;
>>>   creal opCall(real x) { return f(x, i); }
>>> }
>>>
>>> F2 f2 = { 2 };
>>> real x = ...;
>>> creal result = f2(x);
>>>
>>>> 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?
>>
>> Sounds like what you want is partial evaluation
>> (http://en.wikipedia.org/wiki/Partial_evaluation) but done at run
>> time.
>> That's only going to be possible if there's a compiler built into the
>> runtime.  So not possible currently.
>>
>> --bb
>
> I think all he was asking for is currying, which is indeed possible.

You mean this kind of solution :
http://web.mit.edu/d_v1.020/html/d/template.html  (search for "Curry"
on the page) ?

No, he specifically said he didn't want the overhead of carrying
around the arguments.  That's basically the "functor" solution he
mentions.  Only it returns a delegate to the functor's method rather
than returning the functor itself.

But that is the closest you can get.

--bb


More information about the Digitalmars-d mailing list