Thread overview
Delegate parameter name shadows type name
Jan 09, 2017
Ali Çehreli
Jan 09, 2017
H. S. Teoh
Jan 09, 2017
Ali Çehreli
Jan 10, 2017
Jacob Carlborg
Jan 09, 2017
Jonathan M Davis
Jan 09, 2017
Jacob Carlborg
January 09, 2017
This is something that surprised me in a friend's code.

(A "friend", hmmm? No, really, it wasn't me! :) )

// Some type of the API
struct MyType {
    int i;
}

// Some function of the API that takes a delegate
void call(void delegate(MyType) dlg) {
    dlg(MyType(42));
}

void main() {
    /* The programmer simply copied the delegate definition from
     * the function and used it as-is when passing a lambda: */
    call(delegate void(MyType) {
            /* WAT? Does the following really compile? After all,
             * MyType.i is NOT a static member! */
            if (MyType.i == 42) {
                // ...
            }
        });
}

I was surprised to see it compiled and worked but of course MyType at the lambda definition inside main() is not a type name, rather the parameter name. Surprising, but I think this is according to spec.

Ali
January 09, 2017
On Mon, Jan 09, 2017 at 11:18:02AM -0800, Ali Çehreli via Digitalmars-d-learn wrote: [...]
> // Some type of the API
> struct MyType {
>     int i;
> }
> 
> // Some function of the API that takes a delegate
> void call(void delegate(MyType) dlg) {
>     dlg(MyType(42));
> }
> 
> void main() {
>     /* The programmer simply copied the delegate definition from
>      * the function and used it as-is when passing a lambda: */
>     call(delegate void(MyType) {

Are you sure this isn't spelt `void delegate(MyType)`?


>             /* WAT? Does the following really compile? After all,
>              * MyType.i is NOT a static member! */
>             if (MyType.i == 42) {
>                 // ...
>             }
>         });
> }
> 
> I was surprised to see it compiled and worked but of course MyType at the lambda definition inside main() is not a type name, rather the parameter name. Surprising, but I think this is according to spec.
[...]

I think it makes sense relative to your rationalization of it per the spec, but from an objective POV, I think it rightly deserves a WAT?. I can't see anything useful such a construction would allow, besides leading to buggy code caused by unexpected shadowing.

I'd say file an enhancement request to make such code a compile error.


T

-- 
Ph.D. = Permanent head Damage
January 09, 2017
On Monday, January 09, 2017 11:18:02 Ali Çehreli via Digitalmars-d-learn wrote:
> This is something that surprised me in a friend's code.
>
> (A "friend", hmmm? No, really, it wasn't me! :) )
>
> // Some type of the API
> struct MyType {
>      int i;
> }
>
> // Some function of the API that takes a delegate
> void call(void delegate(MyType) dlg) {
>      dlg(MyType(42));
> }
>
> void main() {
>      /* The programmer simply copied the delegate definition from
>       * the function and used it as-is when passing a lambda: */
>      call(delegate void(MyType) {
>              /* WAT? Does the following really compile? After all,
>               * MyType.i is NOT a static member! */
>              if (MyType.i == 42) {
>                  // ...
>              }
>          });
> }
>
> I was surprised to see it compiled and worked but of course MyType at the lambda definition inside main() is not a type name, rather the parameter name. Surprising, but I think this is according to spec.

Well, stuff inside a function is quite free to shadow stuff from outside of it. AFAIK, the only shadowing that's prevented is declarations in a function shadowing other declarations in a function.

- Jonathan M Davis


January 09, 2017
On 01/09/2017 11:23 AM, H. S. Teoh via Digitalmars-d-learn wrote:
> On Mon, Jan 09, 2017 at 11:18:02AM -0800, Ali Çehreli via Digitalmars-d-learn wrote:

>> // Some function of the API that takes a delegate
>> void call(void delegate(MyType) dlg) {

That's a delegate type.

>>     call(delegate void(MyType) {
>
> Are you sure this isn't spelt `void delegate(MyType)`?

Those two syntaxes always confuse me and I'm never sure without trying which one to use when. :) However, the code is correct in this case because that's a delegate instance.

Ali

January 09, 2017
On 2017-01-09 20:18, Ali Çehreli wrote:
> This is something that surprised me in a friend's code.
>
> (A "friend", hmmm? No, really, it wasn't me! :) )
>
> // Some type of the API
> struct MyType {
>     int i;
> }
>
> // Some function of the API that takes a delegate
> void call(void delegate(MyType) dlg) {
>     dlg(MyType(42));
> }
>
> void main() {
>     /* The programmer simply copied the delegate definition from
>      * the function and used it as-is when passing a lambda: */
>     call(delegate void(MyType) {
>             /* WAT? Does the following really compile? After all,
>              * MyType.i is NOT a static member! */
>             if (MyType.i == 42) {
>                 // ...
>             }
>         });
> }
>
> I was surprised to see it compiled and worked but of course MyType at
> the lambda definition inside main() is not a type name, rather the
> parameter name. Surprising, but I think this is according to spec.

I know this has come up before, and reported as a bug, at least once. Might have been me :). What's confusing is that using a type that has a keyword will make the parameter unnamed of the specified type, just as a regular function:

auto a = (int) => 3; // works, a lambda taking an int, no parameter name
auto b = (Foo) => 3; // error, cannot infer type of template lambda
alias b = (Foo) => 3; // works, since this is an alias, Foo is the parameter name of an unknown type

-- 
/Jacob Carlborg
January 10, 2017
On 2017-01-09 20:51, Ali Çehreli wrote:

> Those two syntaxes always confuse me and I'm never sure without trying
> which one to use when. :) However, the code is correct in this case
> because that's a delegate instance.

I agree. When it comes to declaring a delegate type, i.e. a variable or function parameter I always think that the syntax is the same as the declaring a regular function, but replacing the function name with "delegate".

-- 
/Jacob Carlborg