UCFS does not work for nested functions?

2014-05-18 Thread Steffen Wenz via Digitalmars-d-learn

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'
}



Re: UCFS does not work for nested functions?

2014-05-18 Thread bearophile via Digitalmars-d-learn

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


Re: UCFS does not work for nested functions?

2018-06-18 Thread Bastiaan Veelo via Digitalmars-d-learn

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'
}
```


Re: UCFS does not work for nested functions?

2018-06-18 Thread Steven Schveighoffer via Digitalmars-d-learn

On 6/18/18 7:16 AM, Bastiaan Veelo wrote:

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'
}
```


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.


-Steve


Re: UCFS does not work for nested functions?

2018-06-18 Thread aliak via Digitalmars-d-learn
On Monday, 18 June 2018 at 14:19:30 UTC, Steven Schveighoffer 
wrote:

On 6/18/18 7:16 AM, Bastiaan Veelo wrote:

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'
}
```


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.


-Steve


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,
- Ali


Re: UCFS does not work for nested functions?

2018-06-18 Thread bauss via Digitalmars-d-learn

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:

On 6/18/18 7:16 AM, Bastiaan Veelo wrote:

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'
}
```


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.


-Steve


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,
- Ali


I second this.


Re: UCFS does not work for nested functions?

2018-06-18 Thread Steven Schveighoffer via Digitalmars-d-learn

On 6/18/18 1:25 PM, bauss wrote:

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:

On 6/18/18 7:16 AM, Bastiaan Veelo wrote:

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'
}
```


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.




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?




I second this.


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.


-Steve


Re: UCFS does not work for nested functions?

2018-06-18 Thread Bastiaan Veelo via Digitalmars-d-learn
On Monday, 18 June 2018 at 17:58:11 UTC, Steven Schveighoffer 
wrote:

On 6/18/18 1:25 PM, bauss wrote:

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:

On 6/18/18 7:16 AM, Bastiaan Veelo wrote:

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'
}
```


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.




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?




I second this.


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.


-Steve


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;
}
```


Re: UCFS does not work for nested functions?

2018-06-18 Thread aliak via Digitalmars-d-learn
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.


-Steve


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?

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/crcbaautgmrglhzvx...@forum.dlang.org



Re: UCFS does not work for nested functions?

2018-06-18 Thread Steven Schveighoffer via Digitalmars-d-learn

On 6/18/18 2:58 PM, aliak wrote:

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.


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?


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.


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/crcbaautgmrglhzvx...@forum.dlang.org


I 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


Re: UCFS does not work for nested functions?

2018-06-18 Thread Steven Schveighoffer via Digitalmars-d-learn

On 6/18/18 2:57 PM, Bastiaan Veelo wrote:

On Monday, 18 June 2018 at 17:58:11 UTC, Steven Schveighoffer wrote:

On 6/18/18 1:25 PM, bauss wrote:

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:

On 6/18/18 7:16 AM, Bastiaan Veelo wrote:

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'
}
```


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.




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?




I second this.


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 don't understand. What local symbol would be overwritten by which 
module-level symbol?


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.


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


Re: UCFS does not work for nested functions?

2018-06-18 Thread Bastiaan Veelo via Digitalmars-d-learn
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.





Re: UCFS does not work for nested functions?

2018-06-18 Thread aliak via Digitalmars-d-learn
On Monday, 18 June 2018 at 19:26:47 UTC, Steven Schveighoffer 
wrote:

On 6/18/18 2:58 PM, aliak 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.


[...]


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 !