digitalmars.D - about lambdas
- "Michael" <pr m1xa.com> Jan 02 2013
- "Maxim Fomin" <maxim maxim-fomin.ru> Jan 02 2013
- Timon Gehr <timon.gehr gmx.ch> Jan 03 2013
- "Timon Gehr" <timon.gehr gmx.ch> Jan 02 2013
- "Michael" <pr m1xa.com> Jan 03 2013
- "Michael" <pr m1xa.com> Jan 03 2013
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 01/03/2013 10:54 PM, Michael wrote: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?
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.
Jan 03 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: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.
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.
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
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









Timon Gehr <timon.gehr gmx.ch> 