Should aliasing a lambda expression be allowed?

Steven Schveighoffer schveiguy at yahoo.com
Wed Nov 15 15:25:06 UTC 2017


On 11/15/17 9:07 AM, Jonathan M Davis wrote:
> On Wednesday, November 15, 2017 07:28:02 Steven Schveighoffer via
> Digitalmars-d wrote:
>> On 11/14/17 8:56 PM, Michael V. Franklin wrote:
>>> On Tuesday, 14 November 2017 at 23:41:39 UTC, Steven Schveighoffer
> wrote:
>>>> In fact, I'm surprised you can alias to an expression like that.
>>>> Usually you need a symbol. It's probably due to how this is lowered.
>>>
>>> Boy did I "step in it" with my original post:  Started out with one
>>> issue and ended up with 3.
>>>
>>> I looked at what the compiler is doing, and it is generated a new symbol
>>> (e.g. `__lambda4`).  I suspect this is not intended.
>>>
>>> My question now is, should the compiler actually be treating the lambda
>>> as an expression instead of a new symbol, thus disallowing it
>>> altogether? (sigh! more breakage)?
>>
>> I don't think we can prevent the aliasing in the first place, because if
>> this is possible, I guarantee people use it, and it looks quite handy
>> actually. Much less verbose than templates:
>>
>> alias mul = (a, b) => a * b;
>>
>> vs.
>>
>> auto mul(A, B)(A a, B b) { return a * b; }
> 
> In general, alias aliases symbols, whereas a lambda isn't a symbol. They're
> essentially the rvalue equivalent of functions. So, in that sense, it's
> pretty weird that it works. However, we _do_ use it all the time with alias
> template parameters. So, regardless of what would make sense for other
> aliases, if we just made it so that alias in general didn't work with
> lambdas, we'd be in big trouble. It wouldn't surprise me if the fact that
> aliases like this works with lambdas is related to the fact that it works
> with alias template parameters, but I don't know. It may simply be that
> because of how the compiler generates lambdas, it ends up with a name for
> them (even if you don't see it), and it just naturally came out that those
> were aliasable.
> 
>> However, it would be good to prevent the second alias which effectively
>> does nothing.
> 
> As far as I'm concerned, in principal, it's identical to declaring a
> variable with the same name in the same scope, and I'm very surprised that
> it
> works. Interestingly, this code
> 
> alias foo = int;
> alias foo = float;

alias statements and alias parameters have differences, so I don't know 
if there is any real relation here. For example, int cannot bind to a 
template alias.

Some really weird stuff is going on with aliasing and function overloads 
in general.

If we change them from anonymous lambdas to actual functions:

auto lambda1(char c) { return 1; }
auto lambda2(int i) { return 4; }

alias foo = lambda1;
alias foo = lambda2;

void main()
{
    assert(foo('a') == 1);
    assert(foo(1) == 4);
}

Hey look, it all works!

Even if lambda1 and lambda2 are turned into templates, it works.

I seriously did not expect this to work.

-Steve


More information about the Digitalmars-d mailing list