Partial argument specification

Lars Kyllingstad public at kyllingen.NOSPAMnet
Sat Oct 18 12:16:17 PDT 2008


Bill Baxter wrote:
> 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.

I didn't know what currying was, so I checked out the Wikipedia article. 
  I quote:

     Intuitively, currying says "if you fix some arguments,
     you get a function of the remaining arguments".

This is exactly what I was looking for. There seems to be agreement here 
that this can't be done without at least a little overhead, but I still 
think it would be nice with a simple, intuitive syntax like the one I 
described. Also, I think it would fit in nicely with D2's focus on 
functional programming.


-Lars



More information about the Digitalmars-d mailing list