www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Omittable parens is an evil

reply "Koroskin Denis" <2korden+dmd gmail.com> writes:
Sure, it's a handy feature for properties, but it is a source of too many  
bugs. I think that it is against the D design of avoiding features that  
are error-prone.

Today I once again came across with a problem with them and it's still  
open:

class Test
{
    void test() {}
}

How do I get a mangle of Test.test?

writefln(Test.test.mangleof);    // Should be ok, but prints v, which is  
not what I need
writefln((&Test.test).mangleof); // prints PFZv, which is a pointer to  
function
writefln(__traits(getMember, new Test(), "test").mangleof); // prints v  
(void, return value)

If you have other suggestions, please say, I need the solution. Custom  
mangling is not an option.

The following example was shown in bugzilla and it once again proves that  
ommitable parens lead to errors:

void main()
{
     int run()
     {
         // do the stuff
         return 0;
     }

     Thread thread = new Thread(run);  // run -> &run, this(int) is called  
instead of this(int delegate() dg).
}

Why not have special syntax for properties, like:

class Array(T)
{
    property T* ptr()
    {
       return _ptr;
    }

    property int length()
    {
        return _length;
    }

    void resize(int newSize)
    {
        // code here
    }

    int capacity()
    {
        // code here
    }

    private int _length;
    private T*  _ptr;
}

Usage:
Array!(int) array = new Array!(int);
int len = array.length;
array.resize = 100;       // forbidden
int capacity = array.capacity(); // okay

It is a breaking change, sure, but it solves the design flaw and fix is  
trivial.
Jul 19 2008
next sibling parent reply Mike <vertex gmx.at> writes:
On Sat, 19 Jul 2008 15:32:36 +0200, Koroskin Denis <2korden+dmd gmail.com>  
wrote:

 Why not have special syntax for properties, like:

This has come up multiple times - that's one of the few things where C# wins over D. If I may repeat a suggestion I made once, maybe Walter can be hypnotized into implementing it if I just repeat it often enough :) class foo { private int _bar; property int bar { opGet() { return _bar; } opSet(auto value) { _bar = value; } opAddAssign(auto value) { _bar += value; } // it's extremely extendable! } } -Mike -- Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
Jul 19 2008
next sibling parent "Nick Sabalausky" <a a.a> writes:
"Mike" <vertex gmx.at> wrote in message news:op.uejk9fs8kgfkbn lucia...
 On Sat, 19 Jul 2008 15:32:36 +0200, Koroskin Denis <2korden+dmd gmail.com> 
 wrote:

 Why not have special syntax for properties, like:

This has come up multiple times - that's one of the few things where C# wins over D. If I may repeat a suggestion I made once, maybe Walter can be hypnotized into implementing it if I just repeat it often enough :) class foo { private int _bar; property int bar { opGet() { return _bar; } opSet(auto value) { _bar = value; } opAddAssign(auto value) { _bar += value; } // it's extremely extendable! } } -Mike

I've always been in favor of this sort of thing as well. My reasoning is that "member variable" vs "getter/setter function" is an implementation detail, and implementation details should be possible to abstract away. The creator of a library/API/etc should be able to design their classes in way such that if a class has a property (for instance, the color of it), then the user of the object wouldn't have to stop and think "Ok, now is color accessed as a member variable or through getters/setters?". The library creator should be able to make it so that it's the same either way. Additionally, the ability to abstract away the "member variable" vs "getter/setter function" distinction would allow a library/API creator to develop like this: When first creating a class, the class has a property "x". At this point in time, there's nothing special that needs to be done when "x" is read from or written to. So implementing "x" as a member variable is perfectly sufficient. Later on, the class gains enhancements, some of which require additional actions to be taken whenever "x" is accessed. You're working on a library/API, so you don't want this change to be a breaking one. So instead of needing to religously implement all trivial and non-trivial properties as getters/setters right from day one in order to avoid this situation, all you'd need to do is say "Ok, property 'x' now needs getter/setter functionlity, so I'll convert it into this special 'property accessing' feature of the language instead of getter/setter functions, and that way my change won't break anything." A third reason: Project management (Although I really think of this sort of thing more as being "lead programmer" than "manager". A manager's role is administrative, they're there to make sure the developers have what they need to do their job - chairs, computers, tools, distraction-free workspace, competent co-workers, etc. It's not their role to go sticking their fingers into the code. But I digress.). Just like how the built-in unittests, documentation, invariants, and debug conditionals allow...whoever is in charge...to have one less thing to arbitrarily define in their "coding standards", this would alliviate the need to define a standard naming convention for getters/setters. Whatever standard variable naming convention exists would be sufficient. So, four reasons for a special "property accessing" syntax like the above: 1. The "member variable" vs "getter/setter function" distinction is an implementation detail, and as such, should be possible to abstract away. 2. User of a library doesn't always have to think "Ok, now is this property implemented as a member variable or as getters/setters?". 3. Creator of a library can change a member variable into a "getter/setter" of sorts without it being a breaking change, and without needing to religously implement all properties as getters/setters from day one. 4. Lead developer doesn't have to come up with an arbitrary "getter/setter" naming convention. They can simply say "Just use the built-in 'property accessing' syntax, and follow the usual variable naming conventions".
Jul 19 2008
prev sibling next sibling parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Mike" <vertex gmx.at> wrote in message news:op.uejk9fs8kgfkbn lucia...
 On Sat, 19 Jul 2008 15:32:36 +0200, Koroskin Denis <2korden+dmd gmail.com> 
 wrote:

 Why not have special syntax for properties, like:

This has come up multiple times - that's one of the few things where C# wins over D. If I may repeat a suggestion I made once, maybe Walter can be hypnotized into implementing it if I just repeat it often enough :) class foo { private int _bar; property int bar { opGet() { return _bar; } opSet(auto value) { _bar = value; } opAddAssign(auto value) { _bar += value; } // it's extremely extendable! }

I agree, but having to reimplement the opXxxAssign methods for every property would quickly become tedious. A much simpler way to do it is to define that: obj.property op= expr; is exactly the same as: obj.property.opSet(obj.property.opGet() op expr); I believe C# does this. Still it'd be nice to allow opXxxAssign for properties to overload the default behavior, but it'd at least have a reasonable fallback. In the initial designs for MiniD, when it was still a statically-typed language, I defined them exactly in this way, and then abstracted the idea by having a 'namespace' construct which could be used to implement properties, group symbols logically, and so on. None of this will ever get into D.
Jul 19 2008
parent reply Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
Jarrett Billingsley wrote:
 "Mike" <vertex gmx.at> wrote in message news:op.uejk9fs8kgfkbn lucia...
 On Sat, 19 Jul 2008 15:32:36 +0200, Koroskin Denis <2korden+dmd gmail.com> 
 wrote:

 Why not have special syntax for properties, like:

wins over D. If I may repeat a suggestion I made once, maybe Walter can be hypnotized into implementing it if I just repeat it often enough :) class foo { private int _bar; property int bar { opGet() { return _bar; } opSet(auto value) { _bar = value; } opAddAssign(auto value) { _bar += value; } // it's extremely extendable! }

I agree, but having to reimplement the opXxxAssign methods for every property would quickly become tedious. A much simpler way to do it is to define that: obj.property op= expr; is exactly the same as: obj.property.opSet(obj.property.opGet() op expr); I believe C# does this. Still it'd be nice to allow opXxxAssign for properties to overload the default behavior, but it'd at least have a reasonable fallback.

I agree, there is not worth in having to define another accessor other than get or set. My initial brainstorming gives me this design: class Foo { private int bar; int op_bar() { return bar; } // getter int op_bar(int value) { return bar = value; } // setter } No additional "property" syntax is required. You may note that this is more redundant (both the "int" type and the "bar" name have duplicate occurrences). However, if your properties have default getters and setters (the ones that only get and set respectively), then you can just use a mixin to avoid the redundancies: class Foo { private int bar; mixin(propGetSet!(bar)); }
 
 None of this will ever get into D. 
 
 

Most likely :( And it sucks because the implicit function call syntax is more problem than worth. -- Bruno Medeiros - Software Developer, MSc. in CS/E graduate http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Aug 04 2008
parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Bruno Medeiros" <brunodomedeiros+spam com.gmail> wrote in message 
news:g77dh7$1k7q$1 digitalmars.com...

 My initial brainstorming gives me this design:

 class Foo {

   private int bar;

   int op_bar() { return bar; } // getter
   int op_bar(int value) { return bar = value; } // setter

 }

 No additional "property" syntax is required. You may note that this is 
 more redundant (both the "int" type and the "bar" name have duplicate 
 occurrences). However, if your properties have default getters and setters 
 (the ones that only get and set respectively), then you can just use a 
 mixin to avoid the redundancies:


 class Foo {

   private int bar; mixin(propGetSet!(bar));

 }

I kind of like that. One of the things that a true property construct would enable, however, is better information when introspecting types. I know that in writing the binding library for MiniD (and Kirk has encountered this in PyD as well), I've really wished that there were some way to get the getter/setter(s) of a property given a name, instead of having to derive those types and running the risk that the class writer did something weird, like having two params on the setter with the second one optional. If we had true properties, the language could be queried for this kind of information and types would be restricted.
 Most likely :(
 And it sucks because the implicit function call syntax is more problem 
 than worth.

I feel the same about const-correctness. Sigh, whatever. OT, you often tend to reply about two weeks late. Why is that?
Aug 04 2008
parent Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
Jarrett Billingsley wrote:
 
 OT, you often tend to reply about two weeks late.  Why is that? 
 
 

Nowadays I'm much more busy than I used to be, so trying to keep with the newsgroups is more complicated. I usually only have time for that in the weekends. -- Bruno Medeiros - Software Developer, MSc. in CS/E graduate http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Aug 11 2008
prev sibling next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Mike" <vertex gmx.at> wrote in message news:op.uejk9fs8kgfkbn lucia...
 On Sat, 19 Jul 2008 15:32:36 +0200, Koroskin Denis <2korden+dmd gmail.com> 
 wrote:

 Why not have special syntax for properties, like:

This has come up multiple times - that's one of the few things where C# wins over D. If I may repeat a suggestion I made once, maybe Walter can be hypnotized into implementing it if I just repeat it often enough :) class foo { private int _bar; property int bar { opGet() { return _bar; } opSet(auto value) { _bar = value; } opAddAssign(auto value) { _bar += value; } // it's extremely extendable! } } -Mike

I'm just kind of brainstorming possible improvements to the usual way of doing properties. What if the above were adjusted into something like this (there's a few things I've done differently here): class foo { // Similar to how classes define an implict member "this", // "property int bar" defines an implicit "private int bar.value" // (Or maybe "protected int bar.value"? Or maybe adjustable somehow?). // This 1, elimininates the need to manually create "private _bar" // and 2, follows in the spirit of naming all constructors "this" // instead of having a different ctor name for each class // (and therefore achieves the same benefits - such as easier renaming). property int bar { // "get" and "set" can each be set separately to "public", "private", "protected" // (Maybe "protected" would be useless, though? Depends if these should // be overrideable.) get { return value; } set { value = set; } // The rvalue "set" is an implied param, and // works just like the implied "value" in C#'s setters. // Never needed, but possibly allowed just for things like performance. opAddAssign(auto addend) { value += addend; } } private func() { Stdout.formatln("{}", this.bar); // Use property Stdout.formatln("{}", this.bar.value); // Sidestep property } } void main() { int x; auto f = new foo(); f.bar = 5; // ok x = f.bar; // ok f.func(); // ok, displays "5" twice f.bar.value = 7; // Illegal, "bar.value" is private to "foo" x = f.bar.value; // Illegal, "bar.value" is private to "foo" }
Jul 19 2008
parent "Nick Sabalausky" <a a.a> writes:
"Mike" <vertex gmx.at> wrote in message news:op.uej2aznskgfkbn lucia...
 On Sat, 19 Jul 2008 21:42:22 +0200, Nick Sabalausky <a a.a> wrote:

 Hey - I like that implicit value declaration very much. However, there 
 needs to be a way to declare pseudo properties (without the implicit 
 value), so I'd add an initializer to the property:

 class foo
 {
     property int bar
     {
         value = void; // this is the initial value; void means that there 
 is no implicit value
         // here be getters/setters
     }
 }

 Maybe something like that?

 -Mike

My thought on that scenario was that if nothing within the "property int bar" block actually accesses the implied "value" member (I would think that wouldn't be too hard to detect, but maybe I'm wrong), then any access to the implied "value" from outside the block would be either completely meaningless or a sign that something is being done wrong. So in that case, the implied "value" is sort of "optimized away" (in a mannar of speaking, since it's not exactly the same as normal "optimizing away") and any attempt to access it from outside the block becomes an error.
Jul 19 2008
prev sibling parent Mike <vertex gmx.at> writes:
On Sat, 19 Jul 2008 21:42:22 +0200, Nick Sabalausky <a a.a> wrote:

Hey - I like that implicit value declaration very much. However, there  
needs to be a way to declare pseudo properties (without the implicit  
value), so I'd add an initializer to the property:

class foo
{
     property int bar
     {
         value = void; // this is the initial value; void means that there  
is no implicit value
         // here be getters/setters
     }
}

Maybe something like that?

-Mike

-- 
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
Jul 19 2008
prev sibling next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Koroskin Denis" <2korden+dmd gmail.com> wrote in message 
news:op.uejjwmv6n8fdl4 korden...
 Sure, it's a handy feature for properties, but it is a source of too many 
 bugs. I think that it is against the D design of avoiding features that 
 are error-prone.

 Today I once again came across with a problem with them and it's still 
 open:

 class Test
 {
    void test() {}
 }

 How do I get a mangle of Test.test?

 writefln(Test.test.mangleof);    // Should be ok, but prints v, which is 
 not what I need
 writefln((&Test.test).mangleof); // prints PFZv, which is a pointer to 
 function
 writefln(__traits(getMember, new Test(), "test").mangleof); // prints v 
 (void, return value)

 If you have other suggestions, please say, I need the solution. Custom 
 mangling is not an option.

 The following example was shown in bugzilla and it once again proves that 
 ommitable parens lead to errors:

 void main()
 {
     int run()
     {
         // do the stuff
         return 0;
     }

     Thread thread = new Thread(run);  // run -> &run, this(int) is called 
 instead of this(int delegate() dg).
 }

 Why not have special syntax for properties, like:

 class Array(T)
 {
    property T* ptr()
    {
       return _ptr;
    }

    property int length()
    {
        return _length;
    }

    void resize(int newSize)
    {
        // code here
    }

    int capacity()
    {
        // code here
    }

    private int _length;
    private T*  _ptr;
 }

 Usage:
 Array!(int) array = new Array!(int);
 int len = array.length;
 array.resize = 100;       // forbidden
 int capacity = array.capacity(); // okay

 It is a breaking change, sure, but it solves the design flaw and fix is 
 trivial.

I'm not sure if I'm completely following you here. Are you basically saying that being able to call function foo by shortening "foo();" into "foo;" confuses the issue of whether you're referring to the function itself or actually trying to invoke it? If so, then 1. I should pay more attention because I didn't realize you could do that ;). And 2. I agree.
Jul 19 2008
next sibling parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Nick Sabalausky" <a a.a> wrote in message 
news:g5tdll$2sjj$1 digitalmars.com...

 I'm not sure if I'm completely following you here. Are you basically 
 saying that being able to call function foo by shortening "foo();" into 
 "foo;" confuses the issue of whether you're referring to the function 
 itself or actually trying to invoke it?

It's true!
Jul 19 2008
next sibling parent reply "Manfred_Nowak" <svv1999 hotmail.com> writes:
Mike wrote:

 "this does something" (parens) and "this is data" (no parens)

Compare this with this extract of your other posting:
  opAddAssign(auto value) { _bar += value; }
                // it's extremely extendable!

Yes it is extremely extentable because one can incorporate calls to some arbitrary functions into the body of `opAddAssign': opAddAssign(auto value) { _bar += value; action(); procedure(); } ... bang!!! Your "clear _VISUAL_ distinction" has been lost. -manfred -- Maybe some knowledge of some types of disagreeing and their relation can turn out to be useful: http://blog.createdebate.com/2008/04/07/writing-strong-arguments/
Jul 19 2008
parent reply "Nick Sabalausky" <a a.a> writes:
"Manfred_Nowak" <svv1999 hotmail.com> wrote in message 
news:g5tmqq$b99$2 digitalmars.com...
 Mike wrote:

 "this does something" (parens) and "this is data" (no parens)

Compare this with this extract of your other posting:
  opAddAssign(auto value) { _bar += value; }
                // it's extremely extendable!

Yes it is extremely extentable because one can incorporate calls to some arbitrary functions into the body of `opAddAssign': opAddAssign(auto value) { _bar += value; action(); procedure(); } ... bang!!! Your "clear _VISUAL_ distinction" has been lost. -manfred

When looking at code that accesses a property or uses an operator that is overloadable, you don't usually need to know if extra processing is going on behind-the-scenes (typically only when optimizing). But when looking at code that involves a function, the distrinction between "invoked"/"not invoked" is almost always (if not always) a very important make-or-break matter.
Jul 19 2008
next sibling parent reply Robert Fraser <fraserofthenight gmail.com> writes:
Nick Sabalausky wrote:
 "Manfred_Nowak" <svv1999 hotmail.com> wrote in message 
 news:g5tmqq$b99$2 digitalmars.com...
 Mike wrote:

 "this does something" (parens) and "this is data" (no parens)

  opAddAssign(auto value) { _bar += value; }
                // it's extremely extendable!

some arbitrary functions into the body of `opAddAssign': opAddAssign(auto value) { _bar += value; action(); procedure(); } ... bang!!! Your "clear _VISUAL_ distinction" has been lost. -manfred

When looking at code that accesses a property or uses an operator that is overloadable, you don't usually need to know if extra processing is going on behind-the-scenes (typically only when optimizing). But when looking at code that involves a function, the distrinction between "invoked"/"not invoked" is almost always (if not always) a very important make-or-break matter.

I agree. A property getter should be idempotent (cached values aside). That cannot be assumed about all parameter-less functions.
Jul 19 2008
parent reply "Manfred_Nowak" <svv1999 hotmail.com> writes:
Robert Fraser wrote:

 A property getter should be idempotent

How can one assure this? -manfred -- Maybe some knowledge of some types of disagreeing and their relation can turn out to be useful: http://blog.createdebate.com/2008/04/07/writing-strong-arguments/
Jul 20 2008
next sibling parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Manfred_Nowak" <svv1999 hotmail.com> wrote in message 
news:g5vgr4$1buh$2 digitalmars.com...
 Robert Fraser wrote:

 A property getter should be idempotent

How can one assure this?

Making it const/invariant?
Jul 20 2008
prev sibling next sibling parent Ary Borenszweig <ary esperanto.org.ar> writes:
Manfred_Nowak a écrit :
 Robert Fraser wrote:
 
 A property getter should be idempotent

How can one assure this? -manfred

Maybe marking the getter as const.
Jul 20 2008
prev sibling parent Robert Fraser <fraserofthenight gmail.com> writes:
Manfred_Nowak Wrote:

 Robert Fraser wrote:
 
 A property getter should be idempotent

How can one assure this? -manfred -- Maybe some knowledge of some types of disagreeing and their relation can turn out to be useful: http://blog.createdebate.com/2008/04/07/writing-strong-arguments/

You can't, of course. You can mark it invariant, but it may not be in the face of cached values or non-memory stores. It's just an assumption many people make and my own rule whether to make something a function or a property. It might be an argument for property specific syntax' though.
Jul 20 2008
prev sibling parent reply "Manfred_Nowak" <svv1999 hotmail.com> writes:
Nick Sabalausky wrote:

 distrinction between "invoked"/"not invoked"

The need for such a distinction is unclear to me, because it seems to be dependent on the level of abstraction one is able to tolerate. Example: `int a; a= 1;' can be imagined as writing the value `1' on some peace of paper labeled `a'. Under this abstraction one need not care about the physical quality or location of the paper or the writing utensil---or some agent watching that peace of paper and starting some strange action on detecting the value 1. I.e., although there might be some actions going on, when one assigns a value to a variable, they are moot. Please note, that it is the habit of thinking, that makes `f' passive and `f()' active. Digital Mars D introduces indeed a change of paradigm into this habit, by peeling off that hiding cover of abstraction. It should stay this way. The only shortcoming I see, is that there is no element in the language that expresses the wish to have no actions on using some identifier, which is similar to the wish to have some constant values. But I doubt that one really wants to code: `T a; a#= 1;' or similar to express that one does not want anything executed, even if T represents a class with overloaded opAssign. -manfred -- Maybe some knowledge of some types of disagreeing and their relation can turn out to be useful: http://blog.createdebate.com/2008/04/07/writing-strong-arguments/
Jul 20 2008
parent =?ISO-8859-1?Q?Tomasz_Sowi=f1ski?= <tomeksowi gmail.com> writes:
Mike Wrote:

 foo.   // <- subject
 foo;   // <- object
 foo(); // <- verb

now that's a good one!
Jul 20 2008
prev sibling parent reply =?ISO-8859-1?Q?Tomasz_Sowi=f1ski?= <tomeksowi gmail.com> writes:
Mike Wrote:

 For me it's mostly that there's a clear _VISUAL_ distinction between "this  
 does something" (parens) and "this is data" (no parens); and in D there's  
 no difference in this one (arbitrary) edge case. It's easy to "eyeball  
 scan" code using parens pairs as visual anchors.
 

I agree. When coding, at first, I was glad to be able to snip the parens (makes code look cleaner), but then I came to the same conclusion - the illusory cleanness of code strikes back in the form of trouble with telling "something" and "do something" apart. C# has proper properties. Why mess with the classic? Tomek
Jul 19 2008
next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Tomasz Sowiński:
 When coding, at first, I was glad to be able to snip the parens (makes code
look cleaner), but then I came to the same conclusion - the illusory cleanness
of code strikes back in the form of trouble with telling "something" and "do
something" apart.<

I agree that omittable parens is bad, I always put them. If parens become compulsive you don't need to use "&somefunc", you just use "somefunc" to denote the pointer/delegate and "somefunc()" to call it. Bye, bearophile
Jul 20 2008
parent reply downs <default_357-line yahoo.de> writes:
bearophile wrote:
 Tomasz Sowiński:
 When coding, at first, I was glad to be able to snip the parens (makes code
look cleaner), but then I came to the same conclusion - the illusory cleanness
of code strikes back in the form of trouble with telling "something" and "do
something" apart.<

I agree that omittable parens is bad, I always put them. If parens become compulsive you don't need to use "&somefunc", you just use "somefunc" to denote the pointer/delegate and "somefunc()" to call it. Bye, bearophile

Seeing as I don't share your opinion on this topic, I humbly submit that this is not a problem with the language but with the coders, specifically, people who have used function pointers in C. Since I acquired D before I had much need for that atrocious syntax, &function has always made more sense to me. Because of this, I do not see a problem with foo or foo() - both are clearly not the function address. --downs
Jul 20 2008
parent reply =?ISO-8859-1?Q?Tomasz_Sowi=f1ski?= <tomeksowi gmail.com> writes:
downs Wrote:

 bearophile wrote:
 Tomasz Sowiński:
 When coding, at first, I was glad to be able to snip the parens (makes code
look cleaner), but then I came to the same conclusion - the illusory cleanness
of code strikes back in the form of trouble with telling "something" and "do
something" apart.<

I agree that omittable parens is bad, I always put them. If parens become compulsive you don't need to use "&somefunc", you just use "somefunc" to denote the pointer/delegate and "somefunc()" to call it. Bye, bearophile

Seeing as I don't share your opinion on this topic, I humbly submit that this is not a problem with the language but with the coders, specifically, people who have used function pointers in C. Since I acquired D before I had much need for that atrocious syntax, &function has always made more sense to me. Because of this, I do not see a problem with foo or foo() - both are clearly not the function address.

I think functions should be called thisWay() and function addresses should be obtained &thisWay. But then we would have the question what should thisWay symbol mean without parens or ampersand? Maybe it shouldn't mean anything? or use it only to pass functions into other functions as arguments? hm... Tomek
Jul 20 2008
parent reply "Koroskin Denis" <2korden gmail.com> writes:
On Sun, 20 Jul 2008 23:56:26 +0400, Tomasz SowiƱski <tomeksowi gmail.com>  
wrote:

 downs Wrote:

 bearophile wrote:
 Tomasz SowiƱski:
 When coding, at first, I was glad to be able to snip the parens  


illusory cleanness of code strikes back in the form of trouble with telling "something" and "do something" apart.<
 I agree that omittable parens is bad, I always put them.
 If parens become compulsive you don't need to use "&somefunc", you  

call it.
 Bye,
 bearophile

Seeing as I don't share your opinion on this topic, I humbly submit that this is not a problem with the language but with the coders, specifically, people who have used function pointers in C. Since I acquired D before I had much need for that atrocious syntax, &function has always made more sense to me. Because of this, I do not see a problem with foo or foo() - both are clearly not the function address.

I think functions should be called thisWay() and function addresses should be obtained &thisWay. But then we would have the question what should thisWay symbol mean without parens or ampersand? Maybe it shouldn't mean anything? or use it only to pass functions into other functions as arguments? hm... Tomek

I think it should be used to address to the function itself, like typeof(func), func.stringof, func.mangleof, etc. func() <- function result &func <- function pointer func <- function itself
Jul 20 2008
next sibling parent =?ISO-8859-1?Q?Tomasz_Sowi=f1ski?= <tomeksowi gmail.com> writes:
Koroskin Denis Wrote:

 I think it should be used to address to the function itself, like  
 typeof(func), func.stringof, func.mangleof, etc.
 
 func() <- function result
 &func  <- function pointer
 func   <- function itself

Good idea... Now all we have to do is figure out what this stuff has to do with const, to make Walter think about this :)
Jul 20 2008
prev sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Koroskin Denis" <2korden gmail.com> wrote in message 
news:op.uelw2ttaenyajd worker...
 On Sun, 20 Jul 2008 23:56:26 +0400, Tomasz Sowiński <tomeksowi gmail.com> 
 wrote:

 downs Wrote:

 bearophile wrote:
 Tomasz Sowiński:
 When coding, at first, I was glad to be able to snip the parens


illusory cleanness of code strikes back in the form of trouble with telling "something" and "do something" apart.<
 I agree that omittable parens is bad, I always put them.
 If parens become compulsive you don't need to use "&somefunc", you

call it.
 Bye,
 bearophile

Seeing as I don't share your opinion on this topic, I humbly submit that this is not a problem with the language but with the coders, specifically, people who have used function pointers in C. Since I acquired D before I had much need for that atrocious syntax, &function has always made more sense to me. Because of this, I do not see a problem with foo or foo() - both are clearly not the function address.

I think functions should be called thisWay() and function addresses should be obtained &thisWay. But then we would have the question what should thisWay symbol mean without parens or ampersand? Maybe it shouldn't mean anything? or use it only to pass functions into other functions as arguments? hm... Tomek

I think it should be used to address to the function itself, like typeof(func), func.stringof, func.mangleof, etc. func() <- function result &func <- function pointer func <- function itself

I've always liked in other languages where the "function pointer/reference" and "function itself" are considered one and the same. This just seems like extra unnecessary complexity.
Jul 20 2008
parent downs <default_357-line yahoo.de> writes:
Nick Sabalausky wrote:
 I think it should be used to address to the function itself, like 
 typeof(func), func.stringof, func.mangleof, etc.

 func() <- function result
 &func  <- function pointer
 func   <- function itself

I've always liked in other languages where the "function pointer/reference" and "function itself" are considered one and the same. This just seems like extra unnecessary complexity.

For what it's worth, I'd hate that. A symbol is not its address. It would be the same as saying "float f. I'd like f and &f to be the same. " It's simply not true. (I blame C) --downs
Jul 20 2008
prev sibling parent Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
Tomasz Sowiński wrote:
 Mike Wrote:
 
 For me it's mostly that there's a clear _VISUAL_ distinction between "this  
 does something" (parens) and "this is data" (no parens); and in D there's  
 no difference in this one (arbitrary) edge case. It's easy to "eyeball  
 scan" code using parens pairs as visual anchors.

I agree. When coding, at first, I was glad to be able to snip the parens (makes code look cleaner), but then I came to the same conclusion - the illusory cleanness of code strikes back in the form of trouble with telling "something" and "do something" apart. C# has proper properties. Why mess with the classic? Tomek

I agree. In the few D code I've written, I've already run into several bouts with that problem. I'm sure it looked cool at first ("hey, here's a simple trick that allows one to implement properties cleanly"), but while it implements properties "cleanly", it messes up function invocation and introspection *a lot*... :( I think the ommitable parenthesis syntax should be removed, and a proper syntax for properties created (and I don't mind that the first is done before the second is). -- Bruno Medeiros - Software Developer, MSc. in CS/E graduate http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Aug 04 2008
prev sibling next sibling parent Mike <vertex gmx.at> writes:
On Sat, 19 Jul 2008 21:03:28 +0200, Jarrett Billingsley  
<kb3ctd2 yahoo.com> wrote:

 "Nick Sabalausky" <a a.a> wrote in message
 news:g5tdll$2sjj$1 digitalmars.com...

 I'm not sure if I'm completely following you here. Are you basically
 saying that being able to call function foo by shortening "foo();" into
 "foo;" confuses the issue of whether you're referring to the function
 itself or actually trying to invoke it?

It's true!

For me it's mostly that there's a clear _VISUAL_ distinction between "this does something" (parens) and "this is data" (no parens); and in D there's no difference in this one (arbitrary) edge case. It's easy to "eyeball scan" code using parens pairs as visual anchors. -Mike -- Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
Jul 19 2008
prev sibling next sibling parent Mike <vertex gmx.at> writes:
Hmm. I thought the whole thing since yesterday, and this is what I think  
describes it best:

foo.   // <- subject
foo;   // <- object
foo(); // <- verb

So it's not a technical question at all, but a grammatical (it only  
affects syntax anyway).

-- 
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
Jul 20 2008
prev sibling parent "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
Tomasz Sowiński <tomeksowi gmail.com> wrote:

 downs Wrote:

 bearophile wrote:
 Tomasz Sowiński:
 When coding, at first, I was glad to be able to snip the parens  


illusory cleanness of code strikes back in the form of trouble with telling "something" and "do something" apart.<
 I agree that omittable parens is bad, I always put them.
 If parens become compulsive you don't need to use "&somefunc", you  

call it.
 Bye,
 bearophile

Seeing as I don't share your opinion on this topic, I humbly submit that this is not a problem with the language but with the coders, specifically, people who have used function pointers in C. Since I acquired D before I had much need for that atrocious syntax, &function has always made more sense to me. Because of this, I do not see a problem with foo or foo() - both are clearly not the function address.

I think functions should be called thisWay() and function addresses should be obtained &thisWay. But then we would have the question what should thisWay symbol mean without parens or ampersand? Maybe it shouldn't mean anything? or use it only to pass functions into other functions as arguments? hm... Tomek

I usually think that a function called without parens should have no side effects (except, of course, when used as the lhs. Also, debug code and logging are also allowed to have side effects). So, SomeFunc(); // is a valid line SomeFunc; // is invalid SomeVar = SomeFunc; // is valid (getter) SomeOtherFunc = SomeFunc(); // is valid (setter) Of course, this is only a coding standard I have set for myself, but I think it makes code easier to read and understand. As we all know, WTFs/min is the best way to measure code quality. http://www.osnews.com/images/comics/wtfm.jpg -- Simen
Jul 20 2008
prev sibling parent reply "Manfred_Nowak" <svv1999 hotmail.com> writes:
Koroskin Denis wrote:

 writefln((&Test.test).mangleof); // prints PFZv, which is a
 pointer to  function
 

Whre is the bug? writefln( typeof( Test.test).stringof); writefln( typeof( Test.test).mangleof); writefln( typeof( Test.test()).stringof); writefln( typeof( Test.test()).mangleof); prints (void())() v void v -manfred -- Maybe some knowledge of some types of disagreeing and their relation can turn out to be useful: http://blog.createdebate.com/2008/04/07/writing-strong-arguments/
Jul 19 2008
parent "Koroskin Denis" <2korden gmail.com> writes:
On Sun, 20 Jul 2008 01:26:53 +0400, Manfred_Nowak <svv1999 hotmail.com>  
wrote:

 Koroskin Denis wrote:

 writefln((&Test.test).mangleof); // prints PFZv, which is a
 pointer to  function

Whre is the bug? writefln( typeof( Test.test).stringof); writefln( typeof( Test.test).mangleof); writefln( typeof( Test.test()).stringof); writefln( typeof( Test.test()).mangleof); prints (void())() v void v -manfred

I expected to get `FZv' or, better, `_D4test4Test4testMFZv' and not `v' nor `(void())()'. The only way I have found so far is to strip the function body and analyze compiler error message: Error 42: Symbol Undefined _D4test4Test4testMFZv
Jul 19 2008