digitalmars.D.learn - Higher-order functions?
- Jonas H. (10/10) Apr 10 2012 Hi everyone,
- Timon Gehr (42/52) Apr 10 2012 D has full runtime support for higher-order functions and closures.
- Nick Sabalausky (11/16) Apr 10 2012 And keep in mind, too, even though those high-order functions take the
- Xan (16/77) Apr 11 2012 Good answer.
- Jacob Carlborg (14/26) Apr 11 2012 If I understand the above code correctly:
- Xan (8/42) Apr 11 2012 Yes, you undertood correcty.
- Timon Gehr (8/52) Apr 11 2012 AFAIK GDC does not yet support the new lambda literal syntax.
- Xan (25/91) Apr 11 2012 Better but with error ;-)
- Mirko Pilger (2/3) Apr 11 2012 e.g. try this:
- Xan (2/5) Apr 11 2012 I receive the same error
- Timon Gehr (9/93) Apr 11 2012 Apparently your compiler does not support parameter type deduction yet.
- Xan (2/11) Apr 11 2012 Yes, now it works!
- Nick Sabalausky (43/51) Apr 10 2012 Yes. Fully. Many are already in the std lib:
Hi everyone, does D have any runtime higher-order function facilities? (I'm not talking about templates.) More specifically, is something like this possible? (That's how I'd do it in Python) car_prices = map(Car.get_price, list_of_cars) car = new Car foobar(car.get_price) Thanks Jonas
Apr 10 2012
On 04/11/2012 01:13 AM, Jonas H. wrote:Hi everyone, does D have any runtime higher-order function facilities?D has full runtime support for higher-order functions and closures. import std.stdio; int[] map(scope int delegate(int) f, int[] a){ auto b = new int[a.length]; foreach(i,x;a) b[i] = f(x); return b; } void main(){ int a = 2; writeln(map(x=>a*x, [1,2,3])); }(I'm not talking about templates.)You will often use templates together with runtime higher order functions. Eg: import std.stdio; T[] map(T,S)(scope T delegate(S) f, S[] a){ auto b = new T[a.length]; foreach(i,x;a) b[i] = f(x); return b; } void main(){ int a = 2; writeln(map((int x)=>a*x, [1,2,3])); writeln(map((double x)=>a*x, [1.6,2.7,3.8])); } For function literals that contain more than one statement, there is an alternate syntax: auto dg = (int a, double b){a*=b; return a+b;} You can explicitly specify 'function' or 'delegate': auto fp = function (int x) => 2*x; // not a closure, simple function pointer (uses less space, but is less powerful) int a = 2; auto dg = delegate (int x) => a*x; // closure, can refer to a You can leave out argument types when they can be directly deduced from the context. Finally, if the literal has an explicit 'function' or 'delegate' it is possible to explicitly specify the return type: auto dg = delegate int(int x) => x;More specifically, is something like this possible? (That's how I'd do it in Python) car_prices = map(Car.get_price, list_of_cars) car = new Car foobar(car.get_price) Thanks Jonas(Well, the standard way to do what that python code does is using templates. auto car_prices = map!(car => car.get_price)(list_of_cars);// lazy range auto car_prices = array(map!(car => car.get_price(list_of_cars)); // eager array)
Apr 10 2012
"Timon Gehr" <timon.gehr gmx.ch> wrote in message news:jm2hnp$s0s$1 digitalmars.com...(Well, the standard way to do what that python code does is using templates. auto car_prices = map!(car => car.get_price)(list_of_cars);// lazy range auto car_prices = array(map!(car => car.get_price(list_of_cars)); // eager array)And keep in mind, too, even though those high-order functions take the delegate/closure as a template paramater, you CAN still rig it up for the delegate/closure to be changed at runtime (as long as the delegate's signature is the same): auto myDelegate = (Car c) => c.getPrice; // Change it at runtime: if(foo) myDelegate = (Car c) => c.getPrice + 7; auto carPrices = map!myDelegate(list_of_cars);
Apr 10 2012
Good answer. For the other hand, what is the simplest method for implementing this (in pseucode) in D: Sure: FUNC someprocedure(int a, int b, func<int, int: int> f) int RETURN f(a, b) } And call it with: IO.writeLine("add: " .. someprocedure(2, 3, { a, b => a + b })) IO.writeLine("multiply: " .. someprocedure(2, 3, { a, b => a * b })) (Read the => as "gives") Is it possible to have this? Thanks, Xan On Wednesday, 11 April 2012 at 00:03:05 UTC, Timon Gehr wrote:On 04/11/2012 01:13 AM, Jonas H. wrote:Hi everyone, does D have any runtime higher-order function facilities?D has full runtime support for higher-order functions and closures. import std.stdio; int[] map(scope int delegate(int) f, int[] a){ auto b = new int[a.length]; foreach(i,x;a) b[i] = f(x); return b; } void main(){ int a = 2; writeln(map(x=>a*x, [1,2,3])); }(I'm not talking about templates.)You will often use templates together with runtime higher order functions. Eg: import std.stdio; T[] map(T,S)(scope T delegate(S) f, S[] a){ auto b = new T[a.length]; foreach(i,x;a) b[i] = f(x); return b; } void main(){ int a = 2; writeln(map((int x)=>a*x, [1,2,3])); writeln(map((double x)=>a*x, [1.6,2.7,3.8])); } For function literals that contain more than one statement, there is an alternate syntax: auto dg = (int a, double b){a*=b; return a+b;} You can explicitly specify 'function' or 'delegate': auto fp = function (int x) => 2*x; // not a closure, simple function pointer (uses less space, but is less powerful) int a = 2; auto dg = delegate (int x) => a*x; // closure, can refer to a You can leave out argument types when they can be directly deduced from the context. Finally, if the literal has an explicit 'function' or 'delegate' it is possible to explicitly specify the return type: auto dg = delegate int(int x) => x;More specifically, is something like this possible? (That's how I'd do it in Python) car_prices = map(Car.get_price, list_of_cars) car = new Car foobar(car.get_price) Thanks Jonas(Well, the standard way to do what that python code does is using templates. auto car_prices = map!(car => car.get_price)(list_of_cars);// lazy range auto car_prices = array(map!(car => car.get_price(list_of_cars)); // eager array)
Apr 11 2012
On 2012-04-11 10:45, Xan wrote:Good answer. For the other hand, what is the simplest method for implementing this (in pseucode) in D: Sure: FUNC someprocedure(int a, int b, func<int, int: int> f) int RETURN f(a, b) } And call it with: IO.writeLine("add: " .. someprocedure(2, 3, { a, b => a + b })) IO.writeLine("multiply: " .. someprocedure(2, 3, { a, b => a * b })) (Read the => as "gives") Is it possible to have this?If I understand the above code correctly: import std.stdio; int someprocedure (int a, int b, int delegate (int, int) f) { return f(a, b); } void main () { writeln("add: ", someprocedure(2, 3, (a, b) => a + b)); writeln("multiply: ", someprocedure(2, 3, (a, b) => a * b)); } -- /Jacob Carlborg
Apr 11 2012
On Wednesday, 11 April 2012 at 09:17:12 UTC, Jacob Carlborg wrote:On 2012-04-11 10:45, Xan wrote:Yes, you undertood correcty. Your code gives me an error: $ gdmd-4.6 funcions.d funcions.d:10: expression expected, not '>' funcions.d:10: found 'a' when expecting ',' funcions.d:11: expression expected, not '>' funcions.d:11: found 'a' when expecting ','Good answer. For the other hand, what is the simplest method for implementing this (in pseucode) in D: Sure: FUNC someprocedure(int a, int b, func<int, int: int> f) int RETURN f(a, b) } And call it with: IO.writeLine("add: " .. someprocedure(2, 3, { a, b => a + b })) IO.writeLine("multiply: " .. someprocedure(2, 3, { a, b => a * b })) (Read the => as "gives") Is it possible to have this?If I understand the above code correctly: import std.stdio; int someprocedure (int a, int b, int delegate (int, int) f) { return f(a, b); }void main () { writeln("add: ", someprocedure(2, 3, (a, b) => a + b)); writeln("multiply: ", someprocedure(2, 3, (a, b) => a * b)); }
Apr 11 2012
On 04/11/2012 11:37 AM, Xan wrote:On Wednesday, 11 April 2012 at 09:17:12 UTC, Jacob Carlborg wrote:AFAIK GDC does not yet support the new lambda literal syntax. You can use void main () { writeln("add: ", someprocedure(2, 3, (a, b) { return a + b; })); writeln("multiply: ", someprocedure(2, 3, (a, b) { return a * b; })); }On 2012-04-11 10:45, Xan wrote:Yes, you undertood correcty. Your code gives me an error: $ gdmd-4.6 funcions.d funcions.d:10: expression expected, not '>' funcions.d:10: found 'a' when expecting ',' funcions.d:11: expression expected, not '>' funcions.d:11: found 'a' when expecting ','Good answer. For the other hand, what is the simplest method for implementing this (in pseucode) in D: Sure: FUNC someprocedure(int a, int b, func<int, int: int> f) int RETURN f(a, b) } And call it with: IO.writeLine("add: " .. someprocedure(2, 3, { a, b => a + b })) IO.writeLine("multiply: " .. someprocedure(2, 3, { a, b => a * b })) (Read the => as "gives") Is it possible to have this?If I understand the above code correctly: import std.stdio; int someprocedure (int a, int b, int delegate (int, int) f) { return f(a, b); }void main () { writeln("add: ", someprocedure(2, 3, (a, b) => a + b)); writeln("multiply: ", someprocedure(2, 3, (a, b) => a * b)); }
Apr 11 2012
On Wednesday, 11 April 2012 at 09:43:27 UTC, Timon Gehr wrote:On 04/11/2012 11:37 AM, Xan wrote:Better but with error ;-) $ gdmd-4.6 func2.d func2.d:10: Error: undefined identifier a func2.d:10: Error: undefined identifier b func2.d:10: Error: function func2.someprocedure (int a, int b, int delegate(int, int) f) is not callable using argument types (int,int,_error_ delegate(_error_, _error_)) func2.d:10: Error: cannot implicitly convert expression (__dgliteral1) of type _error_ delegate(_error_, _error_) to int delegate(int, int) With: import std.stdio; int someprocedure (int a, int b, int delegate (int, int) f) { return f(a, b); } void main () { writeln("add: ", someprocedure(2, 3, (a, b) { return a + b; } )); writeln("multiply: ", someprocedure(2, 3, (a, b) { return a * b; } )); } What is the error?On Wednesday, 11 April 2012 at 09:17:12 UTC, Jacob Carlborg wrote:AFAIK GDC does not yet support the new lambda literal syntax. You can use void main () { writeln("add: ", someprocedure(2, 3, (a, b) { return a + b; })); writeln("multiply: ", someprocedure(2, 3, (a, b) { return a * b; })); }On 2012-04-11 10:45, Xan wrote:Yes, you undertood correcty. Your code gives me an error: $ gdmd-4.6 funcions.d funcions.d:10: expression expected, not '>' funcions.d:10: found 'a' when expecting ',' funcions.d:11: expression expected, not '>' funcions.d:11: found 'a' when expecting ','Good answer. For the other hand, what is the simplest method for implementing this (in pseucode) in D: Sure: FUNC someprocedure(int a, int b, func<int, int: int> f) int RETURN f(a, b) } And call it with: IO.writeLine("add: " .. someprocedure(2, 3, { a, b => a + b })) IO.writeLine("multiply: " .. someprocedure(2, 3, { a, b => a * b })) (Read the => as "gives") Is it possible to have this?If I understand the above code correctly: import std.stdio; int someprocedure (int a, int b, int delegate (int, int) f) { return f(a, b); }void main () { writeln("add: ", someprocedure(2, 3, (a, b) => a + b)); writeln("multiply: ", someprocedure(2, 3, (a, b) => a * b)); }
Apr 11 2012
What is the error?e.g. try this: auto someprocedure (int a, int b, int delegate (int, int) f)
Apr 11 2012
On Wednesday, 11 April 2012 at 10:14:21 UTC, Mirko Pilger wrote:I receive the same errorWhat is the error?e.g. try this: auto someprocedure (int a, int b, int delegate (int, int) f)
Apr 11 2012
On 04/11/2012 11:51 AM, Xan wrote:On Wednesday, 11 April 2012 at 09:43:27 UTC, Timon Gehr wrote:Apparently your compiler does not support parameter type deduction yet. void main () { writeln("add: ", someprocedure(2, 3, (int a, int b) { return a + b; })); writeln("multiply: ", someprocedure(2, 3, (int a, int b) { return a * b; })); }On 04/11/2012 11:37 AM, Xan wrote:Better but with error ;-) $ gdmd-4.6 func2.d func2.d:10: Error: undefined identifier a func2.d:10: Error: undefined identifier b func2.d:10: Error: function func2.someprocedure (int a, int b, int delegate(int, int) f) is not callable using argument types (int,int,_error_ delegate(_error_, _error_)) func2.d:10: Error: cannot implicitly convert expression (__dgliteral1) of type _error_ delegate(_error_, _error_) to int delegate(int, int) With: import std.stdio; int someprocedure (int a, int b, int delegate (int, int) f) { return f(a, b); } void main () { writeln("add: ", someprocedure(2, 3, (a, b) { return a + b; } )); writeln("multiply: ", someprocedure(2, 3, (a, b) { return a * b; } )); } What is the error?On Wednesday, 11 April 2012 at 09:17:12 UTC, Jacob Carlborg wrote:AFAIK GDC does not yet support the new lambda literal syntax. You can use void main () { writeln("add: ", someprocedure(2, 3, (a, b) { return a + b; })); writeln("multiply: ", someprocedure(2, 3, (a, b) { return a * b; })); }On 2012-04-11 10:45, Xan wrote:Yes, you undertood correcty. Your code gives me an error: $ gdmd-4.6 funcions.d funcions.d:10: expression expected, not '>' funcions.d:10: found 'a' when expecting ',' funcions.d:11: expression expected, not '>' funcions.d:11: found 'a' when expecting ','Good answer. For the other hand, what is the simplest method for implementing this (in pseucode) in D: Sure: FUNC someprocedure(int a, int b, func<int, int: int> f) int RETURN f(a, b) } And call it with: IO.writeLine("add: " .. someprocedure(2, 3, { a, b => a + b })) IO.writeLine("multiply: " .. someprocedure(2, 3, { a, b => a * b })) (Read the => as "gives") Is it possible to have this?If I understand the above code correctly: import std.stdio; int someprocedure (int a, int b, int delegate (int, int) f) { return f(a, b); }void main () { writeln("add: ", someprocedure(2, 3, (a, b) => a + b)); writeln("multiply: ", someprocedure(2, 3, (a, b) => a * b)); }
Apr 11 2012
Apparently your compiler does not support parameter type deduction yet. void main () { writeln("add: ", someprocedure(2, 3, (int a, int b) { return a + b; })); writeln("multiply: ", someprocedure(2, 3, (int a, int b) { return a * b; })); }Yes, now it works! Thanks,
Apr 11 2012
"Jonas H." <jonas lophus.org> wrote in message news:mailman.1600.1334099651.4860.digitalmars-d-learn puremagic.com...Hi everyone, does D have any runtime higher-order function facilities? (I'm not talking about templates.)Yes. Fully. Many are already in the std lib: http://dlang.org/phobos/std_algorithm.htmlMore specifically, is something like this possible? (That's how I'd do it in Python) car_prices = map(Car.get_price, list_of_cars)Just as one example (These all work as of DMD 2.058): import std.algorithm; // For 'map' class Car {...blah...} int getPrice(Car c) {return ...blah...;} void main() { auto listOfCars = [new Car()]; auto carPrices = listOfCars.map!getPrice(); } Or: import std.algorithm; // For 'map' class Car { ...blah... property int price() {return ...blah...;} } void main() { auto listOfCars = [new Car()]; auto carPrices = listOfCars.map!( (Car c) => (c.price) )(); //or auto getPrice = (Car c) => (c.price); // getPrice can be reassigned at runtime auto carPrices = listOfCars.map!getPrice(); }car = new Car foobar(car.get_price)class Car { ...blah... int getPrice() {return ...blah...;} } void foobar(int delegate() dg) { auto x = dg(); } void main() { auto car = new Car(); foobar(&car.getPrice); }
Apr 10 2012