www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Partial function application (Currying)

reply atzensepp <webwicht web.de> writes:
Hello,

D-Language allows for anonymous functions.
Is there a way of elegant partial function application such as in 
other (functional) languages?
A function "doemar" accepts a function with one parameter,
Another function g defined within mail accepts two parameters and 
should be applied partially. I found a way but it requires a 
temporary lambda expression in the invocation.
Is there a better way to do this?

```d
     void doemar( int delegate(int y) f)
     {
        for(int i=0;i<3;i++) writeln( f(i));
     }


     void main()
     {

        int delegate(int x,int y) g;
        for (int i=0;i<3;i++)
        {
           g = (a,b) => i*10+ a*3+b;

           writeln("---------");
           doemar( (x) => g(x,i));
        }
     }
```
Thanks
Jan 20
next sibling parent reply Christian =?UTF-8?B?S8O2c3RsaW4=?= <christian.koestlin gmail.com> writes:
Would
https://dlang.org/library/std/functional/curry.html
help you?

kind regards,
Christian
Jan 20
parent atzensepp <webwicht web.de> writes:
On Saturday, 20 January 2024 at 17:45:36 UTC, Christian Köstlin 
wrote:
 Would
 https://dlang.org/library/std/functional/curry.html
 help you?

 kind regards,
 Christian
Hello Christian, thank for the link. I looks good however in my installation (gdc 8.4.0) it says: ```d curry.d:1:8: error: module std.functional import 'curry' not found ``` Do I need to switch do another compiler?
Jan 20
prev sibling parent reply "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
Not really any other way to do it, create context (i.e. struct, or 
stack) and have a delegate point to both it and a patch function.

It'll be how partial is implemented.

https://dlang.org/phobos/std_functional.html#.partial
Jan 20
parent reply atzensepp <webwicht web.de> writes:
On Saturday, 20 January 2024 at 17:47:29 UTC, Richard (Rikki) 
Andrew Cattermole wrote:
 Not really any other way to do it, create context (i.e. struct, 
 or stack) and have a delegate point to both it and a patch 
 function.

 It'll be how partial is implemented.

 https://dlang.org/phobos/std_functional.html#.partial
Hi Rikki, thanks for the link to partial. I tried this: ```d import std.stdio; // Overloads are resolved when the partially applied function is called // with the remaining arguments. struct S { static char fun(int i, string s) { return s[i]; } static int fun(int a, int b) { return a * b; } } void main() { alias fun3 = partial!(S.fun, 3); writeln(fun3("hello")); // 'l' writeln(fun3(10)); // 30 } ``` But getting: ``` partial.d:12:14: error: template instance partial!(S.fun, 3) partial is not a template declaration, it is a module alias fun3 = partial!(S.fun, 3); ```
Jan 20
parent reply "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
On 21/01/2024 9:55 AM, atzensepp wrote:
 import std.stdio; // Overloads are resolved when the partially applied 
 function is called // with the remaining arguments. struct S { static 
 char fun(int i, string s) { return s[i]; } static int fun(int a, int b) 
 { return a * b; } } void main() { alias fun3 = partial!(S.fun, 3); 
 writeln(fun3("hello")); // 'l' writeln(fun3(10)); // 30 }
This worked: ```d import std.functional; import std.stdio; // Overloads are resolved when the partially applied function is called // with the remaining arguments. struct S { static char fun(int i, string s) { return s[i]; } static int fun(int a, int b) { return a * b; } } void main() { alias fun3 = partial!(S.fun, 3); writeln(fun3("hello")); // 'l' writeln(fun3(10)); // 30 } ```
Jan 20
parent atzensepp <webwicht web.de> writes:
On Saturday, 20 January 2024 at 20:58:49 UTC, Richard (Rikki) 
Andrew Cattermole wrote:
 On 21/01/2024 9:55 AM, atzensepp wrote:
 import std.stdio; // Overloads are resolved when the partially 
 applied function is called // with the remaining arguments. 
 struct S { static char fun(int i, string s) { return s[i]; } 
 static int fun(int a, int b) { return a * b; } } void main() { 
 alias fun3 = partial!(S.fun, 3); writeln(fun3("hello")); // 
 'l' writeln(fun3(10)); // 30 }
This worked: ```d import std.functional; import std.stdio; // Overloads are resolved when the partially applied function is called // with the remaining arguments. struct S { static char fun(int i, string s) { return s[i]; } static int fun(int a, int b) { return a * b; } } void main() { alias fun3 = partial!(S.fun, 3); writeln(fun3("hello")); // 'l' writeln(fun3(10)); // 30 } ```
Hello Rikki, thank you, this helps a lot although the polymorphism does not work in my environment. ``` partial2.d:23:17: error: function std.functional.partial!(fun, 3).partial (string _param_0) is not callable using argument types (int) writeln(fun3(10)); // 30 ``` But when I rename the functions for each case currying works well.
Jan 20