www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - A small annoyance, can D make this better?

reply "Regan Heath" <regan netwin.co.nz> writes:
Today a friend of mine (a less experienced programmer) made a mistake  
which he could not immediately figure out, so he asked me, the mistake was:

time_t time;
time(&time);

I immediately spotted it because I've done this or something like it a few  
times before. :)

This lead me to thinking, what does D do in this situation? and so I coded:

void foo(int foo) {}
void main() {
	int foo;	
	foo(5); //function expected before (), not foo of type int
}

in short, the same thing. However it was pleasing to note that the error  
is better in D's case, the C complier gave simply...

   'time' : not a function

I think we all realise the int 'foo' is hiding the function 'foo'. But,  
the reason that it hides it, is it that D looks for a match in the lowest  
enclosing scope (that of 'main') and when it finds a match it stops  
looking, it does not step back up a scope and see the function 'foo'?

I believe this is the case. I believe this is due to the resolution rules  
D uses, which were copied from C.

Next question, can D handle this any 'better'?

I realise there is no chance that the resolution rules for D will be  
changed, it will likely always stop as soon as it finds a 'match'. (and I  
don't want to restart this old argument!) However.. I wonder if D's  
"context free grammar" allows us to make the resolution smarter by  
defining more exactly what constitutes a match? In this case, can it tell  
for certain that:

foo(5);

is a function call? and if it can, can it not ignore non function symbols  
as it tries to resolve the function call?

In other words can the above validly/correctly find and call the function  
foo?

Even assuming there are cases which remain ambiguous provided there are  
cases which are not, can't the resolution still be made smarter by  
ignoring symbols of the wrong type?

Thoughts?

Regan
Dec 14 2005
next sibling parent reply Derek Parnell <derek psych.ward> writes:
On Thu, 15 Dec 2005 14:56:57 +1300, Regan Heath wrote:

 In this case, can it tell  
 for certain that:
 
 foo(5);
 
 is a function call? 
This might not help but from the syntax alone, you cannot tell if it is a call to a function called 'foo', or to 'foo.opCall(5)'. So it might not be so easy for the compiler. -- Derek (skype: derek.j.parnell) Melbourne, Australia "A learning experience is one of those things that says, 'You know that thing you just did? Don't do that.'" - D.N. Adams 15/12/2005 1:19:37 PM
Dec 14 2005
parent "Regan Heath" <regan netwin.co.nz> writes:
On Thu, 15 Dec 2005 13:23:38 +1100, Derek Parnell <derek psych.ward> wrote:
 On Thu, 15 Dec 2005 14:56:57 +1300, Regan Heath wrote:

 In this case, can it tell
 for certain that:

 foo(5);

 is a function call?
This might not help but from the syntax alone, you cannot tell if it is a call to a function called 'foo', or to 'foo.opCall(5)'. So it might not be so easy for the compiler.
Good point. In either case it's not an 'int' though, so theoretically it could skip some types and not others when looking for a match, assuming it has such knowledge at the time. Regan
Dec 14 2005
prev sibling next sibling parent reply Tom <Tom_member pathlink.com> writes:
In article <ops1syc7n623k2f5 nrage.netwin.co.nz>, Regan Heath says...
Today a friend of mine (a less experienced programmer) made a mistake  
which he could not immediately figure out, so he asked me, the mistake was:

time_t time;
time(&time);

I immediately spotted it because I've done this or something like it a few  
times before. :)

This lead me to thinking, what does D do in this situation? and so I coded:

void foo(int foo) {}
void main() {
	int foo;	
	foo(5); //function expected before (), not foo of type int
}

in short, the same thing. However it was pleasing to note that the error  
is better in D's case, the C complier gave simply...

   'time' : not a function

I think we all realise the int 'foo' is hiding the function 'foo'. But,  
the reason that it hides it, is it that D looks for a match in the lowest  
enclosing scope (that of 'main') and when it finds a match it stops  
looking, it does not step back up a scope and see the function 'foo'?

I believe this is the case. I believe this is due to the resolution rules  
D uses, which were copied from C.

Next question, can D handle this any 'better'?

I realise there is no chance that the resolution rules for D will be  
changed, it will likely always stop as soon as it finds a 'match'. (and I  
don't want to restart this old argument!) However.. I wonder if D's  
"context free grammar" allows us to make the resolution smarter by  
defining more exactly what constitutes a match? In this case, can it tell  
for certain that:

foo(5);

is a function call? and if it can, can it not ignore non function symbols  
as it tries to resolve the function call?

In other words can the above validly/correctly find and call the function  
foo?

Even assuming there are cases which remain ambiguous provided there are  
cases which are not, can't the resolution still be made smarter by  
ignoring symbols of the wrong type?

Thoughts?
IMO it would lead to confusing and unclear code (also very error prone). If this was allowed, couldn't it create hard-to-find errors? (I'm not good to fabricate mean examples) :) Tom
Dec 14 2005
parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Thu, 15 Dec 2005 02:25:32 +0000 (UTC), Tom <Tom_member pathlink.com>  
wrote:
 In article <ops1syc7n623k2f5 nrage.netwin.co.nz>, Regan Heath says...
 Thoughts?
IMO it would lead to confusing and unclear code (also very error prone).
I'd say that it would _allow_ confusing and unclear code. I don't expect people like Derek :) would ever use it intentionally. It could be said that the fact that it allows it is bad enough :)
 If this was allowed, couldn't it create hard-to-find errors?  (I'm not  
 good to fabricate mean examples) :)
I can't think of one, if anyone can please post it. Regan
Dec 14 2005
next sibling parent reply Derek Parnell <derek psych.ward> writes:
On Thu, 15 Dec 2005 15:50:25 +1300, Regan Heath wrote:

 On Thu, 15 Dec 2005 02:25:32 +0000 (UTC), Tom <Tom_member pathlink.com>  
 wrote:
 In article <ops1syc7n623k2f5 nrage.netwin.co.nz>, Regan Heath says...
 Thoughts?
IMO it would lead to confusing and unclear code (also very error prone).
I'd say that it would _allow_ confusing and unclear code. I don't expect people like Derek :) would ever use it intentionally.
LOL ... of course not. I use a half-decent naming convention for variables so I wouldn't have a function and a variable with the same name in my programs. void foo(int pFoo) // 'p' means a parameter { } void main() { int lFoo; // 'l' means local scope foo(5); } -- Derek (skype: derek.j.parnell) Melbourne, Australia "A learning experience is one of those things that says, 'You know that thing you just did? Don't do that.'" - D.N. Adams 15/12/2005 2:29:04 PM
Dec 14 2005
parent reply Manfred Nowak <svv1999 hotmail.com> writes:
Derek Parnell wrote:

[...]
 so I wouldn't have a function and a variable with the
 same name in my programs.
[...]
     int lFoo;     // 'l' means local scope
[...] But maybe integer and float local variables are called the same? void f(){ int lFoo: void g(){ real lFoo; lFoo= 1; // now what? } } -manfred
Dec 14 2005
parent reply Derek Parnell <derek psych.ward> writes:
On Thu, 15 Dec 2005 06:16:40 +0000 (UTC), Manfred Nowak wrote:

 Derek Parnell wrote:
 
 [...]
 so I wouldn't have a function and a variable with the
 same name in my programs.
[...]
     int lFoo;     // 'l' means local scope
[...] But maybe integer and float local variables are called the same? void f(){ int lFoo: void g(){ real lFoo; lFoo= 1; // now what? } }
Yuck! Who'd be mad enough to write code like that! That's just plainly silly. Would it not be better to give variables a meaningful name for the purpose that they are used for? But I digress .. the 'l' prefix still means 'local' to me. So the 'lFoo= 1;' line assigns a value to the variable that is *local* to the assignment's scope. In this case, the one defined inside the g() function. -- Derek (skype: derek.j.parnell) Melbourne, Australia "A learning experience is one of those things that says, 'You know that thing you just did? Don't do that.'" - D.N. Adams 15/12/2005 5:41:37 PM
Dec 14 2005
parent reply Manfred Nowak <svv1999 hotmail.com> writes:
Derek Parnell wrote:

[...]
 In this case, the one defined inside the g() function. 
And that is opposite to the scope rule Regan proposes. Following Regan the plausible extension would be: void g(){ int lRead; real lRead, lRead= 1; lRead= 2.0L; writefln( int.lRead, " ", real.lRead); } Because in essence he wants to change the identifier look up to a lookup for the pair consisting of the identifier and a type, making variables attributes of types and introducing the (nearly?) same overloading mechanisms for variables as for functions. Hmmmm ... interesting, never thought of that before. -manfred
Dec 14 2005
parent Derek Parnell <derek psych.ward> writes:
On Thu, 15 Dec 2005 07:21:40 +0000 (UTC), Manfred Nowak wrote:

 Derek Parnell wrote:
 
 [...]
 In this case, the one defined inside the g() function. 
And that is opposite to the scope rule Regan proposes. Following Regan the plausible extension would be: void g(){ int lRead; real lRead, lRead= 1; lRead= 2.0L; writefln( int.lRead, " ", real.lRead); } Because in essence he wants to change the identifier look up to a lookup for the pair consisting of the identifier and a type, making variables attributes of types and introducing the (nearly?) same overloading mechanisms for variables as for functions. Hmmmm ... interesting, never thought of that before. -manfred
Something wicked this way comes ... I can only see tears if this is adopted. On the other hand, we still have goto so this is just as trouble-causing as that construct. -- Derek (skype: derek.j.parnell) Melbourne, Australia "A learning experience is one of those things that says, 'You know that thing you just did? Don't do that.'" - D.N. Adams 15/12/2005 6:34:36 PM
Dec 14 2005
prev sibling parent Tom <Tom_member pathlink.com> writes:
In article <ops1s0ubkp23k2f5 nrage.netwin.co.nz>, Regan Heath says...
On Thu, 15 Dec 2005 02:25:32 +0000 (UTC), Tom <Tom_member pathlink.com>  
wrote:
 In article <ops1syc7n623k2f5 nrage.netwin.co.nz>, Regan Heath says...
 Thoughts?
IMO it would lead to confusing and unclear code (also very error prone).
I'd say that it would _allow_ confusing and unclear code. I don't expect people like Derek :) would ever use it intentionally. It could be said that the fact that it allows it is bad enough :)
You're right, maybe it's my poor english narrative :P
 If this was allowed, couldn't it create hard-to-find errors?  (I'm not  
 good to fabricate mean examples) :)
I can't think of one, if anyone can please post it. Regan
Tom
Dec 15 2005
prev sibling next sibling parent reply "Ameer Armaly" <ameer_armaly hotmail.com> writes:
"Regan Heath" <regan netwin.co.nz> wrote in message 
news:ops1syc7n623k2f5 nrage.netwin.co.nz...
 Today a friend of mine (a less experienced programmer) made a mistake 
 which he could not immediately figure out, so he asked me, the mistake 
 was:

 time_t time;
 time(&time);

 I immediately spotted it because I've done this or something like it a few 
 times before. :)

 This lead me to thinking, what does D do in this situation? and so I 
 coded:

 void foo(int foo) {}
 void main() {
 int foo; foo(5); //function expected before (), not foo of type int
 }

 in short, the same thing. However it was pleasing to note that the error 
 is better in D's case, the C complier gave simply...

   'time' : not a function

 I think we all realise the int 'foo' is hiding the function 'foo'. But, 
 the reason that it hides it, is it that D looks for a match in the lowest 
 enclosing scope (that of 'main') and when it finds a match it stops 
 looking, it does not step back up a scope and see the function 'foo'?

 I believe this is the case. I believe this is due to the resolution rules 
 D uses, which were copied from C.

 Next question, can D handle this any 'better'?

 I realise there is no chance that the resolution rules for D will be 
 changed, it will likely always stop as soon as it finds a 'match'. (and I 
 don't want to restart this old argument!) However.. I wonder if D's 
 "context free grammar" allows us to make the resolution smarter by 
 defining more exactly what constitutes a match? In this case, can it tell 
 for certain that:

 foo(5);

 is a function call? and if it can, can it not ignore non function symbols 
 as it tries to resolve the function call?

 In other words can the above validly/correctly find and call the function 
 foo?

 Even assuming there are cases which remain ambiguous provided there are 
 cases which are not, can't the resolution still be made smarter by 
 ignoring symbols of the wrong type?

 Thoughts?
I believe this could be useful to an extent, though it could open up the possibilities for wrong or vague naming; calling a function and variable the same thing is something (and please correct me if I'm wrong) that by definition should not happen too often. On the other hand, the compiler should not attempt to instruct the programmer in naming, and I can see definite uses in the variable/function pools beeing separate.
 Regan 
Dec 14 2005
parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Wed, 14 Dec 2005 21:36:01 -0500, Ameer Armaly  
<ameer_armaly hotmail.com> wrote:
 "Regan Heath" <regan netwin.co.nz> wrote in message
 news:ops1syc7n623k2f5 nrage.netwin.co.nz...
 Thoughts?
I believe this could be useful to an extent, though it could open up the possibilities for wrong or vague naming; calling a function and variable the same thing is something (and please correct me if I'm wrong) that by definition should not happen too often.
Perhaps, perhaps not, perhaps we are simply used to not being able to do it? I suspect the cases in which this idea could be applied are fairly limited (maybe reason enough not to bother), they're the really obvious ones, in which case they shouldn't be confusing in and of themselves and it does allow us to call our variables what we want, where we want.
 On the other hand, the compiler should not attempt to instruct the
 programmer in naming, and I can see definite uses in the  
 variable/function pools beeing separate.
Indeed. A case which has caught me in the past was using "read" to indicate how many things I had read, this then conflicted with the function "read" which reads data. Regan
Dec 14 2005
parent Manfred Nowak <svv1999 hotmail.com> writes:
Regan Heath wrote:

[...]
 Indeed. A case which has caught me in the past was using "read"
 to  indicate how many things I had read, this then conflicted
 with the  function "read" which reads data.
... and next time you have a function variable named `read' that conflicts with a function named `read'? -manfred
Dec 14 2005
prev sibling parent Manfred Nowak <svv1999 hotmail.com> writes:
Regan Heath wrote:

[...]
 is a function call? and if it can, can it not ignore non
 function symbols  as it tries to resolve the function call?
[...] That is BASIC-like. In fact the scope rules used in D are currently C-like and algol- like. Both scope rules stemmed from the idea that functions or blocks would be coded by different people and then textually merged into another function or block. Doing so would introduce naming conflicts in case of not supporting this action. This assumption is not true any more, if it ever was. The module concept isolates the work of each individual and make it reachable, shielded by the protection rules. Therefore Walters decision to drop the C-like scoping, change to algol-like scoping and drop the exception for inner scopes is the right way to go. algol-like scope rule: A binding is valid within the whole smallest range containing the definition, except in inner ranges where a binding for the same identifier holds. An identifier may be used before its definition. D-like scope rule should be: A binding is valid within the whole smallest range containing the definition. An identifier may be used before its definition. -manfred
Dec 14 2005