digitalmars.D - about lambdas
- Michael (38/38) Jan 02 2013 R With(I, R)(I o, R function (I) fun)
- Maxim Fomin (3/41) Jan 02 2013 The first one is a lambda function, the second one is a lambda
- Timon Gehr (26/59) Jan 02 2013 Actually the 'void' is just a diagnostics bug. (lambda templates
- Michael (7/19) Jan 03 2013 Now if I want add a somewhat task into expression "x =>
- Timon Gehr (13/35) Jan 03 2013 You understand this correctly, but it is a somewhat roundabout way to
- Michael (5/5) Jan 03 2013 I just doing a chained null checks.
R With(I, R)(I o, R function (I) fun) { static if(isAssignable!(I, typeof(null))) return o is null ? null : fun(o); else return fun(o); } class Person { private { string _name; Address _address; } property { string name() { return _name; } void name(string v) { _name = v; } Address address() { return _address; } void address(Address v) { _address = v; } } } in main function ---------------- foreach(p; persons) p.With((Person x) => x.address); // works but ---------------- foreach(p; persons) p.With(x => x.address); // error nullcheck.d(89): Error: template maybe.With does not match any function template declaration. Candidates are: maybe.d(20): maybe.With(I, R)(I o, R function(I) fun) nullcheck.d(89): Error: template maybe.With(I, R)(I o, R function(I) fun) cannot deduce template function from argument types !()(Person,void) Why?
Jan 02 2013
On Wednesday, 2 January 2013 at 21:00:10 UTC, Michael wrote:R With(I, R)(I o, R function (I) fun) { static if(isAssignable!(I, typeof(null))) return o is null ? null : fun(o); else return fun(o); } class Person { private { string _name; Address _address; } property { string name() { return _name; } void name(string v) { _name = v; } Address address() { return _address; } void address(Address v) { _address = v; } } } in main function ---------------- foreach(p; persons) p.With((Person x) => x.address); // works but ---------------- foreach(p; persons) p.With(x => x.address); // error nullcheck.d(89): Error: template maybe.With does not match any function template declaration. Candidates are: maybe.d(20): maybe.With(I, R)(I o, R function(I) fun) nullcheck.d(89): Error: template maybe.With(I, R)(I o, R function(I) fun) cannot deduce template function from argument types !()(Person,void) Why?The first one is a lambda function, the second one is a lambda template. Templates have type void.
Jan 02 2013
On Wednesday, 2 January 2013 at 21:12:33 UTC, Maxim Fomin wrote:On Wednesday, 2 January 2013 at 21:00:10 UTC, Michael wrote:Actually the 'void' is just a diagnostics bug. (lambda templates only exist in template parameter lists.) The reason the matching fails is that IFTI is not smart enough to devise a type for the parameter 'x', and therefore no type for 'R' is obtained, what makes the matching fail. Currently other parameters are not taken into account during IFTI matching. I believe that the reason is that otherwise the compiler needs to be clever about the order in which it analyzes the parameters. I consider this one of the more annoying limitations. A workaround that should work in this case is to use a template parameter: auto With(alias fun, I)(I o) // maybe add a template constraint here { static if(isAssignable!(I, typeof(null))) return o is null ? null : fun(o); else return fun(o); } --- foreach(p; persons) p.With!(x => x.address); This creates a template from the lambda, and instantiates it once inside 'With'. This way the return type does not have to be part of the template parameters.R With(I, R)(I o, R function (I) fun) { static if(isAssignable!(I, typeof(null))) return o is null ? null : fun(o); else return fun(o); } ... in main function ---------------- foreach(p; persons) p.With((Person x) => x.address); // works but ---------------- foreach(p; persons) p.With(x => x.address); // error nullcheck.d(89): Error: template maybe.With does not match any function template declaration. Candidates are: maybe.d(20): maybe.With(I, R)(I o, R function(I) fun) nullcheck.d(89): Error: template maybe.With(I, R)(I o, R function(I) fun) cannot deduce template function from argument types !()(Person,void) Why?The first one is a lambda function, the second one is a lambda template. Templates have type void.
Jan 02 2013
Thanks guys)auto With(alias fun, I)(I o) // maybe add a template constraint here { static if(isAssignable!(I, typeof(null))) return o is null ? null : fun(o); else return fun(o); } foreach(p; persons) p.With!(x => x.address);Now if I want add a somewhat task into expression "x => x.address", for example "writeln(x.address)", a code should be rewritten likeforeach(p; persons) p.With!(x => {writeln(x.address); return x.address;}());As I understand, right part of expression above - "{ ... }()" is anonymous function (or delegate, or closure) that immediately called in lambda expression. Right? Is right behaviour?
Jan 03 2013
On 01/03/2013 10:54 PM, Michael wrote:Thanks guys)You understand this correctly, but it is a somewhat roundabout way to achieve what you want to do. This should work as well: foreach(p; persons) p.With!((x){writeln(x.address); return x.address;}); The reason is that there are two different ways for forming function literals. The lambda literal a=>exp is immediately rewritten to (a){ return exp; } Historically, the lambda syntax has not been available, turning function literal heavy code into something that looked like {return{return(){return((){return}())}. The introduction of '=>' was a backwards-compatible addition.auto With(alias fun, I)(I o) // maybe add a template constraint here { static if(isAssignable!(I, typeof(null))) return o is null ? null : fun(o); else return fun(o); } foreach(p; persons) p.With!(x => x.address);Now if I want add a somewhat task into expression "x => x.address", for example "writeln(x.address)", a code should be rewritten likeforeach(p; persons) p.With!(x => {writeln(x.address); return x.address;}());As I understand, right part of expression above - "{ ... }()" is anonymous function (or delegate, or closure) that immediately called in lambda expression. Right? Is right behaviour?
Jan 03 2013
I just doing a chained null checks. And I prefer when code looks like "a => ...". In any case we have two ways to do same thing: "a => {...}()" and "(a){...}". Thanks Timon)
Jan 03 2013