What does alias do?

ag0aep6g via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Wed Apr 27 14:03:38 PDT 2016


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.


More information about the Digitalmars-d-learn mailing list