digitalmars.D.learn - Function Composition
- atzensepp (26/26) Jan 24 How is it possible to compose functions?
- atzensepp (45/45) Jan 24 Some progress: compose function needs to know type but templates
- user1234 (3/5) Jan 24 Have you tried
- user1234 (4/11) Jan 24 I just realize, as this requires template specialization with
- atzensepp (28/40) Jan 25 Hello,
- Paul Backus (5/14) Jan 25 Try using the address operator:
- atzensepp (13/29) Jan 25 Hello,
- Inkrementator (6/11) Jan 29 While not a real function pointer, this might already fit your
- atzensepp (5/17) Jan 31 Dear Inkrementator,
How is it possible to compose functions? I came up with following solution that is not satisfactory for two reasons: 1. the compose function should be argument agnostic here it is explicitly coded for (int) -> (int) 2. the composition itself requires additional lambda expressions I would like to write compose(f,g) ```dimport std.stdio; // Function composition: int f(int x) { return x*2;} ; int g(int x) { return x+2;} ; int delegate (int) compose( int delegate(int)second, int delegate(int)first) { return ((int i) => second(first(i))); } void main() { writeln( compose((x) => f(x),(x) => g(x))(2)); writeln( compose((x) => g(x),(x) => f(x))(2)); } ~ ~ ~ ```
Jan 24
Some progress: compose function needs to know type but templates help to create for different types. ```d import std.stdio; import std.container.array; // Function composition: int f(int x) { return x*2;} ; int g(int x) { return x+2;} ; double ff(double x) { return x*x;} ; double gg(double x) { return 2+x;} ; template Delegate(T) { T delegate(T) compose( T function(T)second, T function(T )first) { return ((T i) => second(first(i))); } } void main() { alias c = Delegate!(int); writeln( c.compose(&f,&g)(2)); writeln( c.compose(&g,&f)(2)); alias d = Delegate!(double); writeln( d.compose(&ff,&gg)(2)); writeln( d.compose(&gg,&ff)(2)); } ``` Compose function gets 2 pointers to functions and yield a delegate. The created delegate can be invoked. However it cannot be passed to the composition function. This: ```d int delegate (int) fg = c.compose(&f,&g); int delegate (int) fgf = c.compose(fg,&f); writeln( fgf(2)); ``` leads to: ``` lambda2.d:41:37: error: function lambda2.Delegate!int.compose (int function(int) second, int function(int) first) is not callable using argument types (int delegate(int), int function(int x)) int delegate (int) fgf = c.compose(fg,&f); ``` what a bummer!
Jan 24
On Wednesday, 24 January 2024 at 21:12:20 UTC, atzensepp wrote:[...] what a bummer!Have you tried https://dlang.org/phobos/std_functional.html#compose ?
Jan 24
On Wednesday, 24 January 2024 at 21:30:23 UTC, user1234 wrote:On Wednesday, 24 January 2024 at 21:12:20 UTC, atzensepp wrote:Well this violates the second requirement:[...] what a bummer!Have you tried https://dlang.org/phobos/std_functional.html#compose ?the composition itself requires additional lambda expressions I would like to write compose(f,g)I just realize, as this requires template specialization with `!`. But this is how D works with these kind of things.
Jan 24
On Wednesday, 24 January 2024 at 21:34:26 UTC, user1234 wrote:On Wednesday, 24 January 2024 at 21:30:23 UTC, user1234 wrote:Hello, thank you for pointing me to compose! I think i can live with intermediate lambda expression as it is hidden in the template. Obviously functions and delegates are different kinds. And compose from std.functional is excellent as it has varargs and is also very generic. The only rest issue is that I do not know how to get a pointer to composed function. ```d int main() { writeln(compose!(map!(to!(int)), split)("1 2 3").equal([1, 2, 3])); writeln( compose!(f,g,g,f,g,g,f,g,g,f)(8)); int function(int) t = compose!(f,g,g,f,g,g,f,g,g,f); writeln(t(3)); // auto cf = curry!f; // auto cf1 = cf(1); // auto cf2 = cf(2); return(0); } ``` This leads to: ``` gdc lambda4.d lambda4.d:28:25: error: template compose(E)(E a) has no value int function(int) t = compose!(f,g,g,f,g,g,f,g,g,f); ```On Wednesday, 24 January 2024 at 21:12:20 UTC, atzensepp wrote:Well this violates the second requirement:[...] what a bummer!Have you tried https://dlang.org/phobos/std_functional.html#compose ?the composition itself requires additional lambda expressions I would like to write compose(f,g)I just realize, as this requires template specialization with `!`. But this is how D works with these kind of things.
Jan 25
On Thursday, 25 January 2024 at 08:25:02 UTC, atzensepp wrote:```d int function(int) t = compose!(f,g,g,f,g,g,f,g,g,f); ``` This leads to: ``` gdc lambda4.d lambda4.d:28:25: error: template compose(E)(E a) has no value int function(int) t = compose!(f,g,g,f,g,g,f,g,g,f); ```Try using the address operator: // Here // ▼ int function(int) t = &compose!(f,g,g,f,g,g,f,g,g,f);
Jan 25
On Thursday, 25 January 2024 at 12:19:47 UTC, Paul Backus wrote:On Thursday, 25 January 2024 at 08:25:02 UTC, atzensepp wrote:Hello, thanks for the hint. But in my environment I am getting the same error: ``` gdc lambda4.d lambda4.d:29:26: error: compose(E)(E a) is not an lvalue int function(int) t = &compose!(f,g,g,f,g,g,f,g,g,f); ``` However this works: ```d int delegate (int) td = (x) => compose!(f,g,g,f,g,g,f,g,g,f)(x); ``````d int function(int) t = compose!(f,g,g,f,g,g,f,g,g,f); ``` This leads to: ``` gdc lambda4.d lambda4.d:28:25: error: template compose(E)(E a) has no value int function(int) t = compose!(f,g,g,f,g,g,f,g,g,f); ```Try using the address operator: // Here // ▼ int function(int) t = &compose!(f,g,g,f,g,g,f,g,g,f);
Jan 25
On Thursday, 25 January 2024 at 18:44:26 UTC, atzensepp wrote:However this works: ```d int delegate (int) td = (x) => compose!(f,g,g,f,g,g,f,g,g,f)(x); ```While not a real function pointer, this might already fit your needs. ```d alias td = compose!(f,g); ```
Jan 29
On Monday, 29 January 2024 at 19:24:51 UTC, Inkrementator wrote:On Thursday, 25 January 2024 at 18:44:26 UTC, atzensepp wrote:Dear Inkrementator, thank you very much for this recommendation! This is an effective way to make functions and delegates compatible.However this works: ```d int delegate (int) td = (x) => compose!(f,g,g,f,g,g,f,g,g,f)(x); ```While not a real function pointer, this might already fit your needs. ```d alias td = compose!(f,g); ```
Jan 31