www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Function call without parentheses?

reply Rainer <no spam.org> writes:
Hi,

why is it possible to leave out parentheses when you call a function?

This is pretty error prone :(

class Dummy {
    private bool isValid;

    ...
    bool isValid() {
        return this.isValid;
    }
}

Cheers,
Rainer
May 09 2011
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Rainer:

 why is it possible to leave out parentheses when you call a function?
 
 This is pretty error prone :(

This design mistake is going to be fixed, unless the "sloppy" party wins. Bye, bearophile
May 09 2011
prev sibling next sibling parent Jesse Phillips <jessekphillips+D gmail.com> writes:
Rainer Wrote:

 Hi,
 
 why is it possible to leave out parentheses when you call a function?
 
 This is pretty error prone :(
 
 class Dummy {
     private bool isValid;
 
     ...
     bool isValid() {
         return this.isValid;
     }
 }
 
 Cheers,
 Rainer

It is possible because Walter thought it was an easy/good way to achieve the same goal as those languages that implement a property syntax. How is this error prone? It doesn't compile. test.d(4): Error: function test.Dummy.isValid conflicts with variable test.Dummy .isValid at test.d(2)
May 09 2011
prev sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On 2011-05-09 12:33, Rainer wrote:
 Hi,
 
 why is it possible to leave out parentheses when you call a function?
 
 This is pretty error prone :(
 
 class Dummy {
     private bool isValid;
 
     ...
     bool isValid() {
         return this.isValid;
     }
 }

Originally, any function could be treated as a property function if it had the right signature for it. That's primarily functions which return something but take nothing (which are treated as getters) and functions which return nothing and take one argument (which are treated as setters) - though there are a few valide variations. As such, a function such as isValid is treated as a property function and can be called without parens. This behavior is rather messy and does cause certain problems (such as issues when a getter returns a delegate), so property was introduced. Per TDPL, any function marked with property is treated as a property function and _must_ be called with the property syntax (so, no parens), and any function which is _not_ marked with property is _not_ a property function and _cannot_ use the property syntax (so, it must use parens). dmd has not yet fully implemented everything in TDPL - including this. dmd has property, but it's not enforced. The old rules still apply. Now, some folks have been complaining about this strict enforcement of property and want it to be laxer (enforcing property syntax for property functions but not requiring parens for non-property functions), which would still allow for isValid to be called without parens. So, it's not entirely clear what's going to happen with the enforcement of property, but I expect that strict enforcement will eventually be put in place. Regardless, various compiler bugs will need to be addressed before property can be enforced. So, for now, you can use property syntax with functions not marked with property, because that's how property syntax was initially implemented. - Jonathan M Davis
May 09 2011
parent reply Rainer <no spam.org> writes:
== Quote from Jonathan M Davis (jmdavisProg gmx.com)'s article
 On 2011-05-09 12:33, Rainer wrote:
 Hi,

 why is it possible to leave out parentheses when you call a function?

 This is pretty error prone :(

 class Dummy {
     private bool isValid;

     ...
     bool isValid() {
         return this.isValid;
     }
 }

right signature for it. That's primarily functions which return something but take nothing (which are treated as getters) and functions which return nothing and take one argument (which are treated as setters) - though there are a few valide variations. As such, a function such as isValid is treated as a property function and can be called without parens. This behavior is rather messy and does cause certain problems (such as issues when a getter returns a delegate), so property was introduced. Per TDPL, any function marked with property is treated as a property function and _must_ be called with the property syntax (so, no parens), and any function which is _not_ marked with property is _not_ a property function and _cannot_ use the property syntax (so, it must use parens). dmd has not yet fully implemented everything in TDPL - including this. dmd has property, but it's not enforced. The old rules still apply. Now, some folks have been complaining about this strict enforcement of property and want it to be laxer (enforcing property syntax for property functions but not requiring parens for non-property functions), which would still allow for isValid to be called without parens. So, it's not entirely clear what's going to happen with the enforcement of property, but I expect that strict enforcement will eventually be put in place. Regardless, various compiler bugs will need to be addressed before property can be enforced. So, for now, you can use property syntax with functions not marked with property, because that's how property syntax was initially implemented. - Jonathan M Davis

Thanks for the explanation. I'm new to D and I haven't learned the property syntax yet. The problem is that it took me hours to find this simple bug. I wouldn't have named the variable and method both isValid myself, but this piece of code is coming from Java where variables and methods can have the same name since method invocations always require parentheses. In C++ this wouldn't compile since all members--be they variables or methods--have to be named uniquely. Here you can't tell from looking at the code what isValid actually refers to. It doesn't look like a clean design. I would never have thought that this method actually calls itself. How would I access the variable isValid here? Debugging doesn't work all that well under Linux which made it even more difficult to find the error. Add to that the fact that the stack probably had been corrupted from the recursive method call (stacktrace pointing to something unrelated) and you're this close to giving up on this language. I'd rather have the compiler issue an error or warning when you have a variable and method with the same name since you can't access the variable anyway. If property will be enforced I reckon that plenty of code is going to break. IMHO it doesn't look like a feature which is worth the trouble and confusion it causes. Cheers, Rainer
May 10 2011
next sibling parent Adam D. Ruppe <destructionator gmail.com> writes:
Rainer wrote:
 In C++ this wouldn't compile since all members-

It doesn't compile in D either :S What version of dmd do you have? (run it without arguments and the version is on the first line of the output)
May 10 2011
prev sibling next sibling parent Jacob Carlborg <doob me.com> writes:
On 2011-05-10 16:12, Rainer wrote:
 Thanks for the explanation.  I'm new to D and I haven't learned the  property
syntax yet.

 The problem is that it took me hours to find this simple bug.  I wouldn't have
named
 the variable and method both isValid myself, but this piece of code is coming
from Java
 where variables and methods can have the same name since method invocations
always require parentheses.

 In C++ this wouldn't compile since all members--be they variables or
methods--have to be named uniquely.

 Here you can't tell from looking at the code what isValid actually refers to. 
It doesn't look like a clean design.
 I would never have thought that this method actually calls itself.  How would
I access the variable isValid here?

Either name it something else or maybe you can use "this".
 Debugging doesn't work all that well under Linux which made it even more
difficult to find the error.
 Add to that the fact that the stack probably had been corrupted from the
recursive method call (stacktrace pointing to
 something unrelated) and you're this close to giving up on this language.

 I'd rather have the compiler issue an error or warning when you have a
variable and method with the same name since you
 can't access the variable anyway.

 If property will be enforced I reckon that plenty of code is going to break. 
IMHO it doesn't look like a feature which is
 worth the trouble and confusion it causes.

 Cheers,
 Rainer

Ruby works the same, but in Ruby all instance variables start with a sign. -- /Jacob Carlborg
May 10 2011
prev sibling next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Rainer:

 The problem is that it took me hours to find this simple bug.

Please, show me a minimal test case that reproduces the problem, and I'll put it in Bugzilla as bug or enhancement request, etc. This doesn't compile: class Foo { private bool bar; bool bar() { return this.bar; } } void main() {} Bye, bearophile
May 10 2011
prev sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On 2011-05-10 12:45, bearophile wrote:
 Rainer:
 The problem is that it took me hours to find this simple bug.

Please, show me a minimal test case that reproduces the problem, and I'll put it in Bugzilla as bug or enhancement request, etc. This doesn't compile: class Foo { private bool bar; bool bar() { return this.bar; } } void main() {}

Perhaps he had a module-level variable with the same name? In that case, the member function would shadow the module variable. - Jonathan M Davis
May 10 2011