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

Reply via email to