www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Partial argument specification

reply Lars Kyllingstad <public kyllingen.NOSPAMnet> writes:
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
Oct 17 2008
next sibling parent Lutger <lutger.blijdestijn gmail.com> writes:
I think this is possible using std.bind
Oct 17 2008
prev sibling next sibling parent reply "Denis Koroskin" <2korden gmail.com> writes:
Lars Kyllingstad <public 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?

 -Lars
Oct 17 2008
parent reply "Bill Baxter" <wbaxter gmail.com> writes:
T24gRnJpLCBPY3QgMTcsIDIwMDggYXQgODo1MSBQTSwgRGVuaXMgS29yb3NraW4gPDJrb3JkZW5A
Z21haWwuY29tPiB3cm90ZToKPiBMYXJzIEt5bGxpbmdzdGFkIDxwdWJsaWNAa3lsbGluZ2VuLm5v
c3BhbW5ldD4g0MnTwcwowSkg1yDT18+jzSDQydPYzcUgRnJpLAo+IDE3IE9jdCAyMDA4IDE1OjI3
OjUyICswNDAwOgo+Cj4+IEhlbGxvLAo+Pgo+PiBUaGVyZSBpcyBhIGZlYXR1cmUgSSB3b3VsZCB2
ZXJ5IG11Y2ggbGlrZSB0byBzZWUgaW4gRC4gSSBkb24ndCBrbm93IGlmIGl0Cj4+IGhhcyBiZWVu
IGRpc2N1c3NlZCBiZWZvcmUsIG9yIHdoZXRoZXIgaXMncyBldmVuIHBvc3NpYmxlLCBidXQgSSdt
IGp1c3QgZ29pbmcKPj4gdG8gdGhyb3cgaXQgb3V0IGhlcmUuIFBsZWFzZSB0ZWxsIG1lIHdoYXQg
eW91IHRoaW5rLgo+Pgo+PiBTdXBwb3NlIHlvdSBoYXZlIGEgZnVuY3Rpb24gdGhhdCB0YWtlcyBh
IGNlcnRhaW4gbnVtYmVyIG9mIGFyZ3VtZW50cywgc2F5Cj4+Cj4+ICAgY3JlYWwgZihyZWFsIHgs
IGludCBpKTsKPj4KPj4gVGhlbiBpdCB3b3VsZCBiZSBuZWF0IGlmIG9uZSBjb3VsZCBzcGVjaWZ5
IGp1c3Qgc29tZSBvZiB0aGUgYXJndW1lbnRzLCBhbmQKPj4gaGF2ZSB0aGUgcmVzdWx0IGJlIGEg
cG9pbnRlciB0byBhIGZ1bmN0aW9uIHRoYXQgdGFrZXMgdGhlIHJlbWFpbmluZwo+PiBhcmd1bWVu
dHMuIFRvIGNsYXJpZnksIHRoZSB0eXBlIG9mCj4+Cj4+ICAgZihyZWFsLCAyKQo+Pgo+PiB3b3Vs
ZCB0aGVuIGJlCj4+Cj4+ICAgY3JlYWwgZnVuY3Rpb24ocmVhbCkKPj4KPgo+IFlvdSAqaGF2ZSB0
byogc3RvcmUgYW4gImludCBpIiBwYXJhbWV0ZXIgc29tZXdoZXJlIHVubGVzcyB5b3Ugd2FudCB0
byBiZSBhCj4gY29tcGlsZSB0aW1lIGNvbnN0YW50LiBVc2UgYSB0ZW1wbGF0ZSBpbiB0aGlzIGNh
c2UuIEFsdGVybmF0aXZlbHkgdXNlIGEKPiBzdHJ1Y3Qgb3IgY2xhc3Mgd3JhcHBlci4gU3RydWN0
IHdvbid0IGFsbG9jYXRlIGhlYXAsIGNsYXNzIGdpdmVzIG1vcmUKPiBmbGV4aWJpbGl0eS4gRGVs
ZWdhdGVzIGFsbG93IGNvbnRydWN0aW9uIG9uLWZseSB3aXRob3V0IChldmVuIG1vcmUKPiBmbGV4
aWJpbGl0eSkgYXQgdGhlIGNvc3Qgb2YgYWRkaXRpb25hbCBvdmVyaGVhZC4KPgo+IEknZCBnbyB3
aXRoIGRlbGVnYXRlcyB1bmxlc3MgdGhlIHBlcmZvcm1hbmNlIGRlZ3JhZGUgZHJhc3RpY2FsbHku
Cj4KPiAvLyB1c2Ugb2YgZGVsZWdhdGVzOgo+IGNyZWFsIGRlbGVnYXRlKHJlYWwpIGYyID0gKHJl
YWwgeCl7IHJldHVybiBmKHgsIDIpOyB9Cj4gcmVhbCB4ID0gLi4uOwo+IGNyZWFsIHJlc3VsdCA9
IGYyKHgpOyAvLyBzYW1lIGFzIGYoeCwgMik7Cj4KPiAvLyB1c2Ugb2YgYSBjbGFzcyB3cmFwcGVy
Ogo+IGNsYXNzIEYKPiB7Cj4gICAgdGhpcyhpbnQgaSkgeyB0aGlzLmkgPSBpOyB9Cj4gICAgY3Jl
YWwgb3BDYWxsKHJlYWwgeCkgeyByZXR1cm4gZih4LCBpKTsgfQo+ICAgIHByaXZhdGUgaW50IGk7
Cj4gfQo+Cj4gRiBmMiA9IG5ldyBGKDIpOwo+IHJlYWwgeCA9IC4uLjsKPiBjcmVhbCByZXN1bHQg
PSBmMih4KTsgLy8gc2FtZSBhcyBmKHgsIDIpOwo+Cj4gLy8gc3RydWN0IHdyYXBwZXIKPiBzdHJ1
Y3QgRjIKPiB7Cj4gICAgaW50IGk7Cj4gICAgY3JlYWwgb3BDYWxsKHJlYWwgeCkgeyByZXR1cm4g
Zih4LCBpKTsgfQo+IH0KPgo+IEYyIGYyID0geyAyIH07Cj4gcmVhbCB4ID0gLi4uOwo+IGNyZWFs
IHJlc3VsdCA9IGYyKHgpOwo+Cj4+IFdoeSB3b3VsZCB0aGlzIGJlIG5pY2U/IEFzIGFuIGV4YW1w
bGUsIHNheSB5b3UgaGF2ZSBhIGZ1bmN0aW9uIHRoYXQKPj4gY2FsY3VsYXRlcyB0aGUgZGVyaXZh
dGl2ZSBvZiBhbm90aGVyIGZ1bmN0aW9uIGF0IGEgY2VydGFpbiBwb2ludDoKPj4KPj4gICByZWFs
IGRlcml2YXRpdmUocmVhbCBmdW5jdGlvbihyZWFsKSwgcmVhbCB6KTsKPj4KPj4gV2l0aCB0aGUg
YWJvdmUgbm90YXRpb24gSSBjYW4gdXNlIHRoaXMgZm9yIGZ1bmN0aW9ucyBvZiBzZXZlcmFsIHZh
cmlhYmxlczoKPj4KPj4gICByZWFsIGYocmVhbCB4LCByZWFsIHkpIHsgLi4uIH07Cj4+ICAgYXV0
byBkZmR4ID0gZGVyaXZhdGl2ZSggZihyZWFsLCAxLjIzKSwgNC41NiApOwo+Pgo+PiBBcyBhbiBh
ZGRlZCBib251cywgSSBjYW4gZXZlbiBkaWZmZXJlbnRpYXRlIHdpdGggcmVzcGVjdCB0byB5Ogo+
Pgo+PiAgIGF1dG8gZGZkeSA9IGRlcml2YXRpdmUoIGYoMS4yMywgcmVhbCksIDQuNTYgKTsKPj4K
Pj4gQWxyZWFkeSwgdGhlcmUgYXJlIHNldmVyYWwgd2F5cyB0byBkbyBzaW1pbGFyIHRoaW5ncywg
YnV0IGluIG15IG9waW5pb24KPj4gdGhleSBhcmUgbm90IGFzIGdvb2Q6Cj4+Cj4+IDEuIFVzZSB0
ZW1wbGF0ZXMKPj4gTmljZSwgYnV0IG9ubHkgd29ya3Mgd2hlbiB0aGUgcHJlLXNwZWNpZmllZCBh
cmd1bWVudHMgYXJlIGtub3duIGF0IGNvbXBpbGUKPj4gdGltZS4gKE9yIGlzIHRoZXJlIHNvbWUg
dHJpY2sgSSBkb24ndCBrbm93IGFib3V0PykKPj4KPj4gMi4gVXNlIGZ1bmN0b3JzCj4+IFRoaXMg
d29ya3MsIGJ1dCBsZWFkcyB0byB3b3JzZSBwZXJmb3JtYW5jZSBhbmQgaXMgaW4gbXkgb3Bpbmlv
biBsZXNzCj4+IGVsZWdhbnQuIE9uZSBoYXMgdG8gdHlwZSBhIGxvdCBvZiBjb2RlIGp1c3QgdG8g
ZGVmaW5lIHNpbXBsZSBmdW5jdGlvbnMuCj4+Cj4+IDMuIFVzZSB3cmFwcGVyIGZ1bmN0aW9ucwo+
PiBTYW1lIHByb2JsZW1zIGFzICgyKSwgYW5kIGFsc28gbGVhZHMgdG8gdXNlIG9mIGdsb2JhbCB2
YXJpYWJsZXMuCj4+Cj4+IDQuIFRoZSBHU0wgd2F5OiBQYXNzIHJlbWFpbmluZyBhcmd1bWVudHMg
aW4gYSB2b2lkKiBwb2ludGVyLgo+PiBFeGFtcGxlOgo+Pgo+PiAgIHJlYWwgZGVyaXZhdGl2ZShy
ZWFsIGZ1bmN0aW9uKHJlYWwsIHZvaWQqKSwgcmVhbCB6KTsKPj4KPj4gSU1PLCB0aGlzIGlzIFVH
TFksIG5vdCB0byBtZW50aW9uIHVuLUQtaXNoLgo+Pgo+Pgo+PiBJIG1haW5seSB1c2UgRCBmb3Ig
bnVtZXJpY2FsIGNvbXB1dGF0aW9ucywgaGVuY2UgdGhlIGV4YW1wbGVzIGFib3ZlLiBCdXQKPj4g
SSdtIHN1cmUgdGhlcmUgYXJlIG1hbnkgb3RoZXIgdXNlcyBmb3Igc3VjaCBhIGZlYXR1cmUuIFdo
YXQgZG8geW91IHRoaW5rPwoKU291bmRzIGxpa2Ugd2hhdCB5b3Ugd2FudCBpcyBwYXJ0aWFsIGV2
YWx1YXRpb24KKGh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvUGFydGlhbF9ldmFsdWF0aW9u
KSBidXQgZG9uZSBhdCBydW4KdGltZS4KVGhhdCdzIG9ubHkgZ29pbmcgdG8gYmUgcG9zc2libGUg
aWYgdGhlcmUncyBhIGNvbXBpbGVyIGJ1aWx0IGludG8gdGhlCnJ1bnRpbWUuICBTbyBub3QgcG9z
c2libGUgY3VycmVudGx5LgoKLS1iYgo=
Oct 17 2008
parent reply Robert Fraser <fraserofthenight gmail.com> writes:
Bill Baxter wrote:
 On Fri, Oct 17, 2008 at 8:51 PM, Denis Koroskin <2korden gmail.com> wrote:
 Lars Kyllingstad <public 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.
Oct 17 2008
parent reply "Bill Baxter" <wbaxter gmail.com> writes:
T24gU2F0LCBPY3QgMTgsIDIwMDggYXQgNzowNSBBTSwgUm9iZXJ0IEZyYXNlcgo8ZnJhc2Vyb2Z0
aGVuaWdodEBnbWFpbC5jb20+IHdyb3RlOgo+IEJpbGwgQmF4dGVyIHdyb3RlOgo+Pgo+PiBPbiBG
cmksIE9jdCAxNywgMjAwOCBhdCA4OjUxIFBNLCBEZW5pcyBLb3Jvc2tpbiA8MmtvcmRlbkBnbWFp
bC5jb20+IHdyb3RlOgo+Pj4KPj4+IExhcnMgS3lsbGluZ3N0YWQgPHB1YmxpY0BreWxsaW5nZW4u
bm9zcGFtbmV0PiDQydPBzCjBKSDXINPXz6PNINDJ09jNxQo+Pj4gRnJpLAo+Pj4gMTcgT2N0IDIw
MDggMTU6Mjc6NTIgKzA0MDA6Cj4+Pgo+Pj4+IEhlbGxvLAo+Pj4+Cj4+Pj4gVGhlcmUgaXMgYSBm
ZWF0dXJlIEkgd291bGQgdmVyeSBtdWNoIGxpa2UgdG8gc2VlIGluIEQuIEkgZG9uJ3Qga25vdyBp
Zgo+Pj4+IGl0Cj4+Pj4gaGFzIGJlZW4gZGlzY3Vzc2VkIGJlZm9yZSwgb3Igd2hldGhlciBpcydz
IGV2ZW4gcG9zc2libGUsIGJ1dCBJJ20ganVzdAo+Pj4+IGdvaW5nCj4+Pj4gdG8gdGhyb3cgaXQg
b3V0IGhlcmUuIFBsZWFzZSB0ZWxsIG1lIHdoYXQgeW91IHRoaW5rLgo+Pj4+Cj4+Pj4gU3VwcG9z
ZSB5b3UgaGF2ZSBhIGZ1bmN0aW9uIHRoYXQgdGFrZXMgYSBjZXJ0YWluIG51bWJlciBvZiBhcmd1
bWVudHMsCj4+Pj4gc2F5Cj4+Pj4KPj4+PiAgY3JlYWwgZihyZWFsIHgsIGludCBpKTsKPj4+Pgo+
Pj4+IFRoZW4gaXQgd291bGQgYmUgbmVhdCBpZiBvbmUgY291bGQgc3BlY2lmeSBqdXN0IHNvbWUg
b2YgdGhlIGFyZ3VtZW50cywKPj4+PiBhbmQKPj4+PiBoYXZlIHRoZSByZXN1bHQgYmUgYSBwb2lu
dGVyIHRvIGEgZnVuY3Rpb24gdGhhdCB0YWtlcyB0aGUgcmVtYWluaW5nCj4+Pj4gYXJndW1lbnRz
LiBUbyBjbGFyaWZ5LCB0aGUgdHlwZSBvZgo+Pj4+Cj4+Pj4gIGYocmVhbCwgMikKPj4+Pgo+Pj4+
IHdvdWxkIHRoZW4gYmUKPj4+Pgo+Pj4+ICBjcmVhbCBmdW5jdGlvbihyZWFsKQo+Pj4+Cj4+PiBZ
b3UgKmhhdmUgdG8qIHN0b3JlIGFuICJpbnQgaSIgcGFyYW1ldGVyIHNvbWV3aGVyZSB1bmxlc3Mg
eW91IHdhbnQgdG8gYmUKPj4+IGEKPj4+IGNvbXBpbGUgdGltZSBjb25zdGFudC4gVXNlIGEgdGVt
cGxhdGUgaW4gdGhpcyBjYXNlLiBBbHRlcm5hdGl2ZWx5IHVzZSBhCj4+PiBzdHJ1Y3Qgb3IgY2xh
c3Mgd3JhcHBlci4gU3RydWN0IHdvbid0IGFsbG9jYXRlIGhlYXAsIGNsYXNzIGdpdmVzIG1vcmUK
Pj4+IGZsZXhpYmlsaXR5LiBEZWxlZ2F0ZXMgYWxsb3cgY29udHJ1Y3Rpb24gb24tZmx5IHdpdGhv
dXQgKGV2ZW4gbW9yZQo+Pj4gZmxleGliaWxpdHkpIGF0IHRoZSBjb3N0IG9mIGFkZGl0aW9uYWwg
b3ZlcmhlYWQuCj4+Pgo+Pj4gSSdkIGdvIHdpdGggZGVsZWdhdGVzIHVubGVzcyB0aGUgcGVyZm9y
bWFuY2UgZGVncmFkZSBkcmFzdGljYWxseS4KPj4+Cj4+PiAvLyB1c2Ugb2YgZGVsZWdhdGVzOgo+
Pj4gY3JlYWwgZGVsZWdhdGUocmVhbCkgZjIgPSAocmVhbCB4KXsgcmV0dXJuIGYoeCwgMik7IH0K
Pj4+IHJlYWwgeCA9IC4uLjsKPj4+IGNyZWFsIHJlc3VsdCA9IGYyKHgpOyAvLyBzYW1lIGFzIGYo
eCwgMik7Cj4+Pgo+Pj4gLy8gdXNlIG9mIGEgY2xhc3Mgd3JhcHBlcjoKPj4+IGNsYXNzIEYKPj4+
IHsKPj4+ICAgdGhpcyhpbnQgaSkgeyB0aGlzLmkgPSBpOyB9Cj4+PiAgIGNyZWFsIG9wQ2FsbChy
ZWFsIHgpIHsgcmV0dXJuIGYoeCwgaSk7IH0KPj4+ICAgcHJpdmF0ZSBpbnQgaTsKPj4+IH0KPj4+
Cj4+PiBGIGYyID0gbmV3IEYoMik7Cj4+PiByZWFsIHggPSAuLi47Cj4+PiBjcmVhbCByZXN1bHQg
PSBmMih4KTsgLy8gc2FtZSBhcyBmKHgsIDIpOwo+Pj4KPj4+IC8vIHN0cnVjdCB3cmFwcGVyCj4+
PiBzdHJ1Y3QgRjIKPj4+IHsKPj4+ICAgaW50IGk7Cj4+PiAgIGNyZWFsIG9wQ2FsbChyZWFsIHgp
IHsgcmV0dXJuIGYoeCwgaSk7IH0KPj4+IH0KPj4+Cj4+PiBGMiBmMiA9IHsgMiB9Owo+Pj4gcmVh
bCB4ID0gLi4uOwo+Pj4gY3JlYWwgcmVzdWx0ID0gZjIoeCk7Cj4+Pgo+Pj4+IFdoeSB3b3VsZCB0
aGlzIGJlIG5pY2U/IEFzIGFuIGV4YW1wbGUsIHNheSB5b3UgaGF2ZSBhIGZ1bmN0aW9uIHRoYXQK
Pj4+PiBjYWxjdWxhdGVzIHRoZSBkZXJpdmF0aXZlIG9mIGFub3RoZXIgZnVuY3Rpb24gYXQgYSBj
ZXJ0YWluIHBvaW50Ogo+Pj4+Cj4+Pj4gIHJlYWwgZGVyaXZhdGl2ZShyZWFsIGZ1bmN0aW9uKHJl
YWwpLCByZWFsIHopOwo+Pj4+Cj4+Pj4gV2l0aCB0aGUgYWJvdmUgbm90YXRpb24gSSBjYW4gdXNl
IHRoaXMgZm9yIGZ1bmN0aW9ucyBvZiBzZXZlcmFsCj4+Pj4gdmFyaWFibGVzOgo+Pj4+Cj4+Pj4g
IHJlYWwgZihyZWFsIHgsIHJlYWwgeSkgeyAuLi4gfTsKPj4+PiAgYXV0byBkZmR4ID0gZGVyaXZh
dGl2ZSggZihyZWFsLCAxLjIzKSwgNC41NiApOwo+Pj4+Cj4+Pj4gQXMgYW4gYWRkZWQgYm9udXMs
IEkgY2FuIGV2ZW4gZGlmZmVyZW50aWF0ZSB3aXRoIHJlc3BlY3QgdG8geToKPj4+Pgo+Pj4+ICBh
dXRvIGRmZHkgPSBkZXJpdmF0aXZlKCBmKDEuMjMsIHJlYWwpLCA0LjU2ICk7Cj4+Pj4KPj4+PiBB
bHJlYWR5LCB0aGVyZSBhcmUgc2V2ZXJhbCB3YXlzIHRvIGRvIHNpbWlsYXIgdGhpbmdzLCBidXQg
aW4gbXkgb3Bpbmlvbgo+Pj4+IHRoZXkgYXJlIG5vdCBhcyBnb29kOgo+Pj4+Cj4+Pj4gMS4gVXNl
IHRlbXBsYXRlcwo+Pj4+IE5pY2UsIGJ1dCBvbmx5IHdvcmtzIHdoZW4gdGhlIHByZS1zcGVjaWZp
ZWQgYXJndW1lbnRzIGFyZSBrbm93biBhdAo+Pj4+IGNvbXBpbGUKPj4+PiB0aW1lLiAoT3IgaXMg
dGhlcmUgc29tZSB0cmljayBJIGRvbid0IGtub3cgYWJvdXQ/KQo+Pj4+Cj4+Pj4gMi4gVXNlIGZ1
bmN0b3JzCj4+Pj4gVGhpcyB3b3JrcywgYnV0IGxlYWRzIHRvIHdvcnNlIHBlcmZvcm1hbmNlIGFu
ZCBpcyBpbiBteSBvcGluaW9uIGxlc3MKPj4+PiBlbGVnYW50LiBPbmUgaGFzIHRvIHR5cGUgYSBs
b3Qgb2YgY29kZSBqdXN0IHRvIGRlZmluZSBzaW1wbGUgZnVuY3Rpb25zLgo+Pj4+Cj4+Pj4gMy4g
VXNlIHdyYXBwZXIgZnVuY3Rpb25zCj4+Pj4gU2FtZSBwcm9ibGVtcyBhcyAoMiksIGFuZCBhbHNv
IGxlYWRzIHRvIHVzZSBvZiBnbG9iYWwgdmFyaWFibGVzLgo+Pj4+Cj4+Pj4gNC4gVGhlIEdTTCB3
YXk6IFBhc3MgcmVtYWluaW5nIGFyZ3VtZW50cyBpbiBhIHZvaWQqIHBvaW50ZXIuCj4+Pj4gRXhh
bXBsZToKPj4+Pgo+Pj4+ICByZWFsIGRlcml2YXRpdmUocmVhbCBmdW5jdGlvbihyZWFsLCB2b2lk
KiksIHJlYWwgeik7Cj4+Pj4KPj4+PiBJTU8sIHRoaXMgaXMgVUdMWSwgbm90IHRvIG1lbnRpb24g
dW4tRC1pc2guCj4+Pj4KPj4+Pgo+Pj4+IEkgbWFpbmx5IHVzZSBEIGZvciBudW1lcmljYWwgY29t
cHV0YXRpb25zLCBoZW5jZSB0aGUgZXhhbXBsZXMgYWJvdmUuIEJ1dAo+Pj4+IEknbSBzdXJlIHRo
ZXJlIGFyZSBtYW55IG90aGVyIHVzZXMgZm9yIHN1Y2ggYSBmZWF0dXJlLiBXaGF0IGRvIHlvdQo+
Pj4+IHRoaW5rPwo+Pgo+PiBTb3VuZHMgbGlrZSB3aGF0IHlvdSB3YW50IGlzIHBhcnRpYWwgZXZh
bHVhdGlvbgo+PiAoaHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9QYXJ0aWFsX2V2YWx1YXRp
b24pIGJ1dCBkb25lIGF0IHJ1bgo+PiB0aW1lLgo+PiBUaGF0J3Mgb25seSBnb2luZyB0byBiZSBw
b3NzaWJsZSBpZiB0aGVyZSdzIGEgY29tcGlsZXIgYnVpbHQgaW50byB0aGUKPj4gcnVudGltZS4g
IFNvIG5vdCBwb3NzaWJsZSBjdXJyZW50bHkuCj4+Cj4+IC0tYmIKPgo+IEkgdGhpbmsgYWxsIGhl
IHdhcyBhc2tpbmcgZm9yIGlzIGN1cnJ5aW5nLCB3aGljaCBpcyBpbmRlZWQgcG9zc2libGUuCgpZ
b3UgbWVhbiB0aGlzIGtpbmQgb2Ygc29sdXRpb24gOgpodHRwOi8vd2ViLm1pdC5lZHUvZF92MS4w
MjAvaHRtbC9kL3RlbXBsYXRlLmh0bWwgIChzZWFyY2ggZm9yICJDdXJyeSIKb24gdGhlIHBhZ2Up
ID8KCk5vLCBoZSBzcGVjaWZpY2FsbHkgc2FpZCBoZSBkaWRuJ3Qgd2FudCB0aGUgb3ZlcmhlYWQg
b2YgY2FycnlpbmcKYXJvdW5kIHRoZSBhcmd1bWVudHMuICBUaGF0J3MgYmFzaWNhbGx5IHRoZSAi
ZnVuY3RvciIgc29sdXRpb24gaGUKbWVudGlvbnMuICBPbmx5IGl0IHJldHVybnMgYSBkZWxlZ2F0
ZSB0byB0aGUgZnVuY3RvcidzIG1ldGhvZCByYXRoZXIKdGhhbiByZXR1cm5pbmcgdGhlIGZ1bmN0
b3IgaXRzZWxmLgoKQnV0IHRoYXQgaXMgdGhlIGNsb3Nlc3QgeW91IGNhbiBnZXQuCgotLWJiCg==
Oct 17 2008
parent Lars Kyllingstad <public kyllingen.NOSPAMnet> writes:
Bill Baxter wrote:
 On Sat, Oct 18, 2008 at 7:05 AM, Robert Fraser
 <fraserofthenight gmail.com> wrote:
 Bill Baxter wrote:
 On Fri, Oct 17, 2008 at 8:51 PM, Denis Koroskin <2korden gmail.com> wrote:
 Lars Kyllingstad <public 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
Oct 18 2008
prev sibling parent reply downs <default_357-line yahoo.de> writes:
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 :)
Oct 17 2008
parent reply Lars Kyllingstad <public kyllingen.NOSPAMnet> writes:
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
Oct 18 2008
parent reply downs <default_357-line yahoo.de> writes:
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!
Oct 20 2008
parent Lars Kyllingstad <public kyllingen.NOSPAMnet> writes:
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 this: 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. -Lars
Oct 20 2008