digitalmars.D - Partial argument specification
- Lars Kyllingstad <public kyllingen.NOSPAMnet> Oct 17 2008
- Lutger <lutger.blijdestijn gmail.com> Oct 17 2008
- "Denis Koroskin" <2korden gmail.com> Oct 17 2008
- "Bill Baxter" <wbaxter gmail.com> Oct 17 2008
- Robert Fraser <fraserofthenight gmail.com> Oct 17 2008
- Lars Kyllingstad <public kyllingen.NOSPAMnet> Oct 18 2008
- "Bill Baxter" <wbaxter gmail.com> Oct 17 2008
- downs <default_357-line yahoo.de> Oct 17 2008
- Lars Kyllingstad <public kyllingen.NOSPAMnet> Oct 18 2008
- downs <default_357-line yahoo.de> Oct 20 2008
- Lars Kyllingstad <public kyllingen.NOSPAMnet> Oct 20 2008
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
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
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
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)
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
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)
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?
(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
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
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
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
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
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
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
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 :)
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









Lutger <lutger.blijdestijn gmail.com> 