digitalmars.D.learn - Delegate parameter name shadows type name
- =?UTF-8?Q?Ali_=c3=87ehreli?= (25/25) Jan 09 2017 This is something that surprised me in a friend's code.
- H. S. Teoh via Digitalmars-d-learn (12/37) Jan 09 2017 Are you sure this isn't spelt `void delegate(MyType)`?
- =?UTF-8?Q?Ali_=c3=87ehreli?= (7/12) Jan 09 2017 That's a delegate type.
- Jacob Carlborg (7/10) Jan 09 2017 I agree. When it comes to declaring a delegate type, i.e. a variable or
- Jonathan M Davis via Digitalmars-d-learn (6/30) Jan 09 2017 Well, stuff inside a function is quite free to shadow stuff from outside...
- Jacob Carlborg (11/35) Jan 09 2017 I know this has come up before, and reported as a bug, at least once.
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
Jan 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
Jan 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 viaDigitalmars-d-learn wrote:That's a delegate type.// Some function of the API that takes a delegate void call(void delegate(MyType) dlg) {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. Alicall(delegate void(MyType) {Are you sure this isn't spelt `void delegate(MyType)`?
Jan 09 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
Jan 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
Jan 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
Jan 09 2017