On 27.04.2016 21:40, xtreak wrote:
import std.array;
import std.range;
import std.algorithm;
import std.stdio;
T test(alias f, T)(T num) {
return f(num);
}
T test1(T, V)(T num, V f){
return f(num);
}
void main() {
writeln("hello world");
writeln(10000.iota
.map!(a => a * a)
.take(5));
writeln(test!(z => z * z)(10));
writeln(test1(10, ((z) => z *z)));
writeln(test1(10, function int(int z) { return z * z; }));
}
What is the difference between passing as alias and then passing it as
lambda. Does it involve any cost.
As far as I understand, you can imagine `z => z * z` being pasted for
`f` in the alias version. That is, for `test!(z => z * z)(10)` a
function `int test(int num) {return (z => z * z)(num);}` is generated.
It should be easy for the compiler/optimizer to turn that into `return z
* z;`.
When `f` is a function parameter, a function pointer / delegate is
passed at run-time, unless the optimizer manages to inline it. I don't
know how good/aggressive inliners are and if they fail to do this in
practice.
Also note that the alias version generates a new function for every f.
The function parameter version only generates one function per `typeof(f)`.
Also the second form of short notation
throws an error that it returns void.
This line, right?
writeln(test1(10, ((z) => z *z)));
That doesn't work because both the type of test1's V and the type of z
are generic. For example, z could be int or float, and V could be `int
function(int)` or `float function(float)`. The compiler can't decide
that, so it errors out.
Either z or the type of f need to be more explicit. These are ok:
----
writeln(test1(10, (int z) => z * z)); /* now V can be deduced as int
function(int) */
T test2(T)(T num, T function(T) f){ /* building f's type from T */
return f(num);
}
writeln(test2!int(10, z => z * z)); /* giving T explicitly */
----
The alias version doesn't have this problem because `z => z * z` is just
pasted in there. z's type doesn't matter until the call is analyzed. And
then num's type is known which forces z's type.