digitalmars.D.learn - UCFS does not work for nested functions?
- Steffen Wenz (15/15) May 18 2014 Hi,
- bearophile (11/14) May 18 2014 Currently it's intended. Because doing otherwise causes other
- Bastiaan Veelo (14/18) Jun 18 2018 I just had the same question.
- Steven Schveighoffer (5/27) Jun 18 2018 It's never been supported, and likely will not be. I think the idea is
- aliak (8/36) Jun 18 2018 Wondering how this is different than with non-nested functions?
- bauss (2/40) Jun 18 2018 I second this.
- Steven Schveighoffer (7/46) Jun 18 2018 What then can happen is that your local calls can get hijacked from
- Bastiaan Veelo (23/72) Jun 18 2018 I don't understand. What local symbol would be overwritten by
- Steven Schveighoffer (16/87) Jun 18 2018 In other words, if UFCS meant that module-level symbols took precedent
- Bastiaan Veelo (6/20) Jun 18 2018 Ah, you mean it would have to be that way to prevent breakage. No
- aliak (21/28) Jun 18 2018 I thought that happens already with non-nested functions:
- Steven Schveighoffer (25/56) Jun 18 2018 It's the same in the fact that your call is silently switched to a
- aliak (6/16) Jun 18 2018 Ah I see. So it's basically that locals take priority, but if you
Hi, Just noticed that using UFCS does not work for nested functions, and was wondering whether that's intended, and what the rationale behind it is: class X { void foo() {} } void main() { // moving bar to module scope solves the error below void bar(X x) {} X x; x.foo(); // ok bar(x); // ok x.bar(); // Error: no property 'bar' for type 'nested.X' }
May 18 2014
Steffen Wenz:Just noticed that using UFCS does not work for nested functions,Right.and was wondering whether that's intended, and what the rationale behind it is:Currently it's intended. Because doing otherwise causes other problems with struct/class member functions. Perhaps there are ways to design around this problem, but so far no one has suggested a good way to design it (and the good Kenji has worked on this problem, so probably there are no simple solutions). Once you understand this problem space well, if you find a good design solution you can submit it to Bugzilla. Bye, bearophile
May 18 2014
On Sunday, 18 May 2014 at 08:15:08 UTC, Steffen Wenz wrote:Hi, Just noticed that using UFCS does not work for nested functions, and was wondering whether that's intended, and what the rationale behind it is:I just had the same question. I can imagine that the context pointer of nested functions complicates things, but making `bar` `static` does not help. Has anything changed in recent years regarding the difficulty of implementing UFCS for nested functions? Would it be easier to only support static nested functions? ``` void main() { static void bar(int x) {} int x; x.bar(); // Error: no property 'bar' for type 'int' } ```
Jun 18 2018
On 6/18/18 7:16 AM, Bastiaan Veelo wrote:On Sunday, 18 May 2014 at 08:15:08 UTC, Steffen Wenz wrote:It's never been supported, and likely will not be. I think the idea is that you can override expected behavior inside by accidentally defining some function locally with the same name. -SteveHi, Just noticed that using UFCS does not work for nested functions, and was wondering whether that's intended, and what the rationale behind it is:I just had the same question. I can imagine that the context pointer of nested functions complicates things, but making `bar` `static` does not help. Has anything changed in recent years regarding the difficulty of implementing UFCS for nested functions? Would it be easier to only support static nested functions? ``` void main() { static void bar(int x) {} int x; x.bar(); // Error: no property 'bar' for type 'int' } ```
Jun 18 2018
On Monday, 18 June 2018 at 14:19:30 UTC, Steven Schveighoffer wrote:On 6/18/18 7:16 AM, Bastiaan Veelo wrote:Wondering how this is different than with non-nested functions? If a global function has the same name as a member function then the member function takes precedence. So wouldn't the same thing just apply here if it were supported? Cheers, - AliOn Sunday, 18 May 2014 at 08:15:08 UTC, Steffen Wenz wrote:It's never been supported, and likely will not be. I think the idea is that you can override expected behavior inside by accidentally defining some function locally with the same name. -SteveHi, Just noticed that using UFCS does not work for nested functions, and was wondering whether that's intended, and what the rationale behind it is:I just had the same question. I can imagine that the context pointer of nested functions complicates things, but making `bar` `static` does not help. Has anything changed in recent years regarding the difficulty of implementing UFCS for nested functions? Would it be easier to only support static nested functions? ``` void main() { static void bar(int x) {} int x; x.bar(); // Error: no property 'bar' for type 'int' } ```
Jun 18 2018
On Monday, 18 June 2018 at 17:16:29 UTC, aliak wrote:On Monday, 18 June 2018 at 14:19:30 UTC, Steven Schveighoffer wrote:I second this.On 6/18/18 7:16 AM, Bastiaan Veelo wrote:Wondering how this is different than with non-nested functions? If a global function has the same name as a member function then the member function takes precedence. So wouldn't the same thing just apply here if it were supported? Cheers, - AliOn Sunday, 18 May 2014 at 08:15:08 UTC, Steffen Wenz wrote:It's never been supported, and likely will not be. I think the idea is that you can override expected behavior inside by accidentally defining some function locally with the same name. -SteveHi, Just noticed that using UFCS does not work for nested functions, and was wondering whether that's intended, and what the rationale behind it is:I just had the same question. I can imagine that the context pointer of nested functions complicates things, but making `bar` `static` does not help. Has anything changed in recent years regarding the difficulty of implementing UFCS for nested functions? Would it be easier to only support static nested functions? ``` void main() { static void bar(int x) {} int x; x.bar(); // Error: no property 'bar' for type 'int' } ```
Jun 18 2018
On 6/18/18 1:25 PM, bauss wrote:On Monday, 18 June 2018 at 17:16:29 UTC, aliak wrote:What then can happen is that your local calls can get hijacked from outside the module, if someone happens to define something later that you happened to import. D tries to avoid such possibilities. There's not much precedent for local symbols being overridden by module-level symbols. -SteveOn Monday, 18 June 2018 at 14:19:30 UTC, Steven Schveighoffer wrote:I second this.On 6/18/18 7:16 AM, Bastiaan Veelo wrote:Wondering how this is different than with non-nested functions? If a global function has the same name as a member function then the member function takes precedence. So wouldn't the same thing just apply here if it were supported?On Sunday, 18 May 2014 at 08:15:08 UTC, Steffen Wenz wrote:It's never been supported, and likely will not be. I think the idea is that you can override expected behavior inside by accidentally defining some function locally with the same name.Hi, Just noticed that using UFCS does not work for nested functions, and was wondering whether that's intended, and what the rationale behind it is:I just had the same question. I can imagine that the context pointer of nested functions complicates things, but making `bar` `static` does not help. Has anything changed in recent years regarding the difficulty of implementing UFCS for nested functions? Would it be easier to only support static nested functions? ``` void main() { static void bar(int x) {} int x; x.bar(); // Error: no property 'bar' for type 'int' } ```
Jun 18 2018
On Monday, 18 June 2018 at 17:58:11 UTC, Steven Schveighoffer wrote:On 6/18/18 1:25 PM, bauss wrote:I don't understand. What local symbol would be overwritten by which module-level symbol? Whatever the concerns, what is the difference regarding these concerns between this: ``` // Valid today void bar(int) {} void main() { int x; b.bar; } ``` and this: ``` \\ Invalid today void main() { static void bar(int) {} int x; x.bar; } ```On Monday, 18 June 2018 at 17:16:29 UTC, aliak wrote:What then can happen is that your local calls can get hijacked from outside the module, if someone happens to define something later that you happened to import. D tries to avoid such possibilities. There's not much precedent for local symbols being overridden by module-level symbols. -SteveOn Monday, 18 June 2018 at 14:19:30 UTC, Steven Schveighoffer wrote:I second this.On 6/18/18 7:16 AM, Bastiaan Veelo wrote:Wondering how this is different than with non-nested functions? If a global function has the same name as a member function then the member function takes precedence. So wouldn't the same thing just apply here if it were supported?On Sunday, 18 May 2014 at 08:15:08 UTC, Steffen Wenz wrote:It's never been supported, and likely will not be. I think the idea is that you can override expected behavior inside by accidentally defining some function locally with the same name.Hi, Just noticed that using UFCS does not work for nested functions, and was wondering whether that's intended, and what the rationale behind it is:I just had the same question. I can imagine that the context pointer of nested functions complicates things, but making `bar` `static` does not help. Has anything changed in recent years regarding the difficulty of implementing UFCS for nested functions? Would it be easier to only support static nested functions? ``` void main() { static void bar(int x) {} int x; x.bar(); // Error: no property 'bar' for type 'int' } ```
Jun 18 2018
On 6/18/18 2:57 PM, Bastiaan Veelo wrote:On Monday, 18 June 2018 at 17:58:11 UTC, Steven Schveighoffer wrote:In other words, if UFCS meant that module-level symbols took precedent over local symbols, then it's backwards in terms of which place usually wins. Generally it's the local symbols.On 6/18/18 1:25 PM, bauss wrote:I don't understand. What local symbol would be overwritten by which module-level symbol?On Monday, 18 June 2018 at 17:16:29 UTC, aliak wrote:What then can happen is that your local calls can get hijacked from outside the module, if someone happens to define something later that you happened to import. D tries to avoid such possibilities. There's not much precedent for local symbols being overridden by module-level symbols.On Monday, 18 June 2018 at 14:19:30 UTC, Steven Schveighoffer wrote:I second this.On 6/18/18 7:16 AM, Bastiaan Veelo wrote:Wondering how this is different than with non-nested functions? If a global function has the same name as a member function then the member function takes precedence. So wouldn't the same thing just apply here if it were supported?On Sunday, 18 May 2014 at 08:15:08 UTC, Steffen Wenz wrote:It's never been supported, and likely will not be. I think the idea is that you can override expected behavior inside by accidentally defining some function locally with the same name.Hi, Just noticed that using UFCS does not work for nested functions, and was wondering whether that's intended, and what the rationale behind it is:I just had the same question. I can imagine that the context pointer of nested functions complicates things, but making `bar` `static` does not help. Has anything changed in recent years regarding the difficulty of implementing UFCS for nested functions? Would it be easier to only support static nested functions? ``` void main() { static void bar(int x) {} int x; x.bar(); // Error: no property 'bar' for type 'int' } ```Whatever the concerns, what is the difference regarding these concerns between this: ``` // Valid today void bar(int) {} void main() { int x; b.bar; } ``` and this: ``` \\ Invalid today void main() { static void bar(int) {} int x; x.bar; } ```It's a good question, I don't think it has a particularly satisfying answer. But one thing I will note, is that this is valid today: void bar(int) {writeln("module");} void main() { static void bar(int) {writeln("local");} int x; x.bar; // "module" } Adding UFCS support to locals, which one would be the expected call? It's difficult to imagine the local being the lower priority, but it would have to be that way to avoid code breakage. -Steve
Jun 18 2018
On Monday, 18 June 2018 at 19:31:39 UTC, Steven Schveighoffer wrote:In other words, if UFCS meant that module-level symbols took precedent over local symbols, then it's backwards in terms of which place usually wins. Generally it's the local symbols.Ah, you mean it would have to be that way to prevent breakage. No I would not want it that way. [...]But one thing I will note, is that this is valid today: void bar(int) {writeln("module");} void main() { static void bar(int) {writeln("local");} int x; x.bar; // "module" } Adding UFCS support to locals, which one would be the expected call? It's difficult to imagine the local being the lower priority, but it would have to be that way to avoid code breakage.Thanks, that clarifies it. No turtles for UFCS.
Jun 18 2018
On Monday, 18 June 2018 at 17:58:11 UTC, Steven Schveighoffer wrote:What then can happen is that your local calls can get hijacked from outside the module, if someone happens to define something later that you happened to import. D tries to avoid such possibilities. There's not much precedent for local symbols being overridden by module-level symbols. -SteveI thought that happens already with non-nested functions: module a; struct A { void f(); // assume it's added later } module b; import a; void f(A) { } void g() { auto x = A(); a.f(); // this would be calling local f until someone added A.f } Or I misunderstood what you said? Cheers, - Ali PS: This is something I've worried about before actually [1] when I was more of a noob than now, but I've come to accept I guess :) ... though I could still be misunderstanding things of course :/ https://forum.dlang.org/post/crcbaautgmrglhzvxmvk forum.dlang.org
Jun 18 2018
On 6/18/18 2:58 PM, aliak wrote:On Monday, 18 June 2018 at 17:58:11 UTC, Steven Schveighoffer wrote:It's the same in the fact that your call is silently switched to a different call. However, in the current syntax, an external entity CANNOT override a local function. When you call the nested function, it's the nested function, no matter what else occurs outside (even in the local module). There is no precedent for local functions to be overridden by module-level functions. So if we allow this, we break a guarantee of which function is called, albeit via a different syntax. Generally, the local function takes precedence, then the member functions, then module-level functions. Making the module level functions override the local functions is not normal or expected. Generally you are defining locals to override what you see outside the function. But with UFCS, it's treated as part of the API of the type. The type defines the API first, and then you can add to it, you can't override it. Part of this is historical in nature -- UFCS came after member functions, and so they had to be lower priority.What then can happen is that your local calls can get hijacked from outside the module, if someone happens to define something later that you happened to import. D tries to avoid such possibilities. There's not much precedent for local symbols being overridden by module-level symbols.I thought that happens already with non-nested functions: module a; struct A { void f(); // assume it's added later } module b; import a; void f(A) { } void g() { auto x = A(); a.f(); // this would be calling local f until someone added A.f } Or I misunderstood what you said?PS: This is something I've worried about before actually [1] when I was more of a noob than now, but I've come to accept I guess :) .... though I could still be misunderstanding things of course :/ https://forum.dlang.org/post/crcbaautgmrglhzvxmvk forum.dlang.orgI think the current state of affairs still leaves some hijacking doors open, depending on your point of view. It's certainly not perfect. The only way to be sure you are doing things correctly is to use member syntax when you know it's a member, and function syntax otherwise. IMO, UFCS for locals isn't going to change, but I could also be wrong. It's not really up to me what goes into the language, I just am trying to help explain the rationale behind the current rules. -Steve
Jun 18 2018
On Monday, 18 June 2018 at 19:26:47 UTC, Steven Schveighoffer wrote:On 6/18/18 2:58 PM, aliak wrote:Ah I see. So it's basically that locals take priority, but if you allow them to UFCS then that's not true anymore because members need to take priority. Ok yep, that makes sense. Thanks ![...]It's the same in the fact that your call is silently switched to a different call. However, in the current syntax, an external entity CANNOT override a local function. When you call the nested function, it's the nested function, no matter what else occurs outside (even in the local module). There is no precedent for local functions to be overridden by module-level functions. [...]
Jun 18 2018