www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Property syntax revisited

reply "John C" <johnch_atms hotmail.com> writes:
As I see it, the problem with D's property syntax is that they're actually 
methods, and the compiler has to try to disamiguate between method and 
property calls/assignments, which it's not 100% successful at - sometimes 
you have to add a pair of parentheses '()' when using a property to stop the 
compiler from choking (for example, when used in conjunction with 'auto').

Another issue is that it introduces ambiguity in the way they are called, 
and users have no way of knowing how they are intended to be used - 
'my.name("John")' or 'my.name = "John"'.

The other issue is that properties have the semantics of fields, not methods 
(even if, in the end, the compiler just generates the same code as for a 
method). They just don't feel like first-class citizens.

I'd like to suggest a new syntax that I think addresses these issues. The 
only downside is the addition of a new keyword, 'property'. But otherwise 
it's quite elegant and is only slightly more verbose than the current syntax 
(the keyword itself). It's basically a way of grouping a pair of getters and 
setters in a 'property block'.

Here's a class that utilises it.

    class Person {

        private float weight_; // Manually written backing store for 
'weight' property

        protected void onWeightChanged() {
            // Warn of heart attack risk if above a certain weight
        }

        property weight { // 'weight' property block
            float() { // This defines the signature of the getter
                return weight_;
            }
            void(float value) { // This defines the signature of the setter;
                                        // setters must have a void return 
type
                weight_ = value;
                onWeightChanged();
            }
        } // end 'weight' property block

        // In this property block, we don't provide definitions,
        // which tells the compiler to generate a backing store
        // and the definitions on our behalf.
        // Let's call it a 'simple property'.
        property height {
            float();
            void(float);
        }

        // property block with getter only
        property bmi {
            float() {
                return weight / (height * height);
            }
        }

    }

Some notes:
1) Any attempt to define a setter with an argument type that doesn't match 
that of the getter return type would be an error (and vise versa).
2) Different protection attributes can be applied to the getter and setter, 
as with methods.
3) For property blocks without manual definitions (as in the 'height' 
example above), either the getter or setter signature can be omitted, making 
them either read- or write-only, which distinguishes them from public 
fields.
4) Within the scope of a property block, use of the property name itself is 
legal, since the compiler knows to refer to the automatically generated 
backing store (as opposed to introducing a recursive call).

No doubt there will be objections to this notation, so fire away. But I 
reckon it's a nice compromise between the C# and C++/CLI syntaxes (which 
require three contextual keywords: 'get', 'set' and 'value') and the current 
D syntax. 
Jan 04 2006
next sibling parent reply S. Chancellor <S._member pathlink.com> writes:
In article <dphgrp$nbt$1 digitaldaemon.com>, John C says...

 ....
        property weight { // 'weight' property block
            float() { // This defines the signature of the getter
                return weight_;
            }
            void(float value) { // This defines the signature of the setter;
                                        // setters must have a void return 
type
                weight_ = value;
                onWeightChanged();
            }
        } // end 'weight' property block

Your example seems a bit odd to me as the setter can have a different input type from the getter. If you're going to go the way of implementing a whole property block it seems that they should have their type specified in the property area. In which case we might as well adopt the C# syntax for properties. IE: float weight_; property float weight { get { return weight_; } set { weight_ = weight; } } If there is a requirement that a property be able to return differen types, the casting features of D should take over. IMHO. -S.
Jan 04 2006
next sibling parent reply Sean Kelly <sean f4.ca> writes:
S. Chancellor wrote:
 In article <dphgrp$nbt$1 digitaldaemon.com>, John C says...
 
 ....
        property weight { // 'weight' property block
            float() { // This defines the signature of the getter
                return weight_;
            }
            void(float value) { // This defines the signature of the setter;
                                        // setters must have a void return 
 type
                weight_ = value;
                onWeightChanged();
            }
        } // end 'weight' property block

Your example seems a bit odd to me as the setter can have a different input type from the getter. If you're going to go the way of implementing a whole property block it seems that they should have their type specified in the property area. In which case we might as well adopt the C# syntax for properties. IE: float weight_; property float weight { get { return weight_; } set { weight_ = weight; } } If there is a requirement that a property be able to return differen types, the casting features of D should take over. IMHO.

I think a property syntax is a reasonable idea so long as we don't lose the ability to use free functions as properties. I'm finding it quite useful that I can even replace global variables with no-argument functions and leave all other code unchanged. Sean
Jan 04 2006
next sibling parent "John C" <johnch_atms hotmail.com> writes:
"Sean Kelly" <sean f4.ca> wrote in message 
news:dphn95$s0l$1 digitaldaemon.com...
 S. Chancellor wrote:
 In article <dphgrp$nbt$1 digitaldaemon.com>, John C says...

 ....
        property weight { // 'weight' property block
            float() { // This defines the signature of the getter
                return weight_;
            }
            void(float value) { // This defines the signature of the 
 setter;
                                        // setters must have a void 
 return type
                weight_ = value;
                onWeightChanged();
            }
        } // end 'weight' property block

Your example seems a bit odd to me as the setter can have a different input type from the getter. If you're going to go the way of implementing a whole property block it seems that they should have their type specified in the property area. In which case we might as well adopt the C# syntax for properties. IE: float weight_; property float weight { get { return weight_; } set { weight_ = weight; } } If there is a requirement that a property be able to return differen types, the casting features of D should take over. IMHO.

I think a property syntax is a reasonable idea so long as we don't lose the ability to use free functions as properties. I'm finding it quite useful that I can even replace global variables with no-argument functions and leave all other code unchanged.

Yes, I find it useful too. But there's no reason why a property block couldn't be valid for modules as well.
 Sean 

Jan 04 2006
prev sibling next sibling parent reply Fredrik Olsson <peylow treyst.se> writes:
Sean Kelly skrev:
 S. Chancellor wrote:

 I think a property syntax is a reasonable idea so long as we don't lose 
 the ability to use free functions as properties.  I'm finding it quite 
 useful that I can even replace global variables with no-argument 
 functions and leave all other code unchanged.
 

My $0.02 (I like that one :) ). 1. IMHO it is bad to be able to call both as function and as property, it confuses adopters. 2. Breaking backward compatibility for properties is too late(?). 3. I want more syntactic sugar! Today we have int length(char[] str); That can be called in two ways: 1. int bar = length(foo); 2. int baz = foo.length; Why not add a "property" modifier, like this; property int length(char[] str); And now the 1. syntax is forbidden for the "function". For extra syntactic sugar, if we have more then one parameter the rest of the parameters can be used as indexers. Like this: property bool charIsNumber(char[] str, uint index) { return '0' <= str[index] && str[index] <= '9'; } char[] foo = "Atari 520STe"; bool jupp = foo.charIsNumber[4]; So in 0.150 the property modifier gets adopted and non property marked properties gets depricated, then people start cleaning out their code, and by 1.0 everything is nice and jolly :). // Fredrik Olsson.
Jan 05 2006
next sibling parent reply Ivan Senji <ivan.senji_REMOVE_ _THIS__gmail.com> writes:
Fredrik Olsson wrote:
 My $0.02 (I like that one :) ).

OK, here is my 0.02kn (currency where i come from and < $0.02) :)
 
 1. IMHO it is bad to be able to call both as function and as property, 
 it confuses adopters.
 2. Breaking backward compatibility for properties is too late(?).
 3. I want more syntactic sugar!
 
 Today we have
 int length(char[] str);
 That can be called in two ways:
 1. int bar = length(foo);
 2. int baz = foo.length;
 
 Why not add a "property" modifier, like this;
 property int length(char[] str);
 And now the 1. syntax is forbidden for the "function".
 

I am strongly in favor for adding extendable properties to *all* types and this syntax is as good as any other sugested.
 For extra syntactic sugar, if we have more then one parameter the rest 
 of the parameters can be used as indexers. Like this:

But this isn't....
 property bool charIsNumber(char[] str, uint index) {
   return '0' <= str[index] && str[index] <= '9';
 }
 char[] foo = "Atari 520STe";
 bool jupp = foo.charIsNumber[4];
 

...beacuse the rest of the parameters are in 99% of the cases not going to semanticaly be indexes.
Jan 05 2006
parent reply Fredrik Olsson <peylow treyst.se> writes:
Ivan Senji skrev:
 Fredrik Olsson wrote:
 My $0.02 (I like that one :) ).

OK, here is my 0.02kn (currency where i come from and < $0.02) :)
 1. IMHO it is bad to be able to call both as function and as property, 
 it confuses adopters.
 2. Breaking backward compatibility for properties is too late(?).
 3. I want more syntactic sugar!

 Today we have
 int length(char[] str);
 That can be called in two ways:
 1. int bar = length(foo);
 2. int baz = foo.length;

 Why not add a "property" modifier, like this;
 property int length(char[] str);
 And now the 1. syntax is forbidden for the "function".

I am strongly in favor for adding extendable properties to *all* types and this syntax is as good as any other sugested.
 For extra syntactic sugar, if we have more then one parameter the rest 
 of the parameters can be used as indexers. Like this:

But this isn't....
 property bool charIsNumber(char[] str, uint index) {
   return '0' <= str[index] && str[index] <= '9';
 }
 char[] foo = "Atari 520STe";
 bool jupp = foo.charIsNumber[4];

...beacuse the rest of the parameters are in 99% of the cases not going to semanticaly be indexes.

In 99% of the cases indexes are probably int and char[]. But allowing any type makes it dead easy to emulate any kind of associative arrays. Perhaps even making the opIndex() function obsolete? As this one: property int this(uint index); Could mean the same thing and be consistent as well. // Fredrik Olsson
Jan 05 2006
parent Ivan Senji <ivan.senji_REMOVE_ _THIS__gmail.com> writes:
Fredrik Olsson wrote:
 Ivan Senji skrev:
 ...beacuse the rest of the parameters are in 99% of the cases not 
 going to semanticaly be indexes.

In 99% of the cases indexes are probably int and char[]. But allowing any type makes it dead easy to emulate any kind of associative arrays. Perhaps even making the opIndex() function obsolete? As this one: property int this(uint index); Could mean the same thing and be consistent as well.

I think there might be a missunderstanding here. I will try to explain what i wanted to say with an example: property int[] selectIfGreaterThan(int[] numbers, int condition); int[] numbers; numbers.selectIfGreaterThan(5); 5 in this case is not an index and i think in most cases of extending other types with additional properties the other parameters aren't going to be indexes but something else as in the example above.
Jan 05 2006
prev sibling parent reply Don Clugston <dac nospam.com.au> writes:
Fredrik Olsson wrote:
 Sean Kelly skrev:
 
 S. Chancellor wrote:

<snip>
 I think a property syntax is a reasonable idea so long as we don't 
 lose the ability to use free functions as properties.  I'm finding it 
 quite useful that I can even replace global variables with no-argument 
 functions and leave all other code unchanged.

My $0.02 (I like that one :) ). 1. IMHO it is bad to be able to call both as function and as property, it confuses adopters. 2. Breaking backward compatibility for properties is too late(?). 3. I want more syntactic sugar! Today we have int length(char[] str); That can be called in two ways: 1. int bar = length(foo); 2. int baz = foo.length; Why not add a "property" modifier, like this; property int length(char[] str); And now the 1. syntax is forbidden for the "function".

I love it. Especially if it meant that properties could be added to any type (including built-in types), rather than just arrays.
Jan 05 2006
parent Fredrik Olsson <peylow treyst.se> writes:
Don Clugston skrev:
 Fredrik Olsson wrote:
 Sean Kelly skrev:

 S. Chancellor wrote:

<snip>
 I think a property syntax is a reasonable idea so long as we don't 
 lose the ability to use free functions as properties.  I'm finding it 
 quite useful that I can even replace global variables with 
 no-argument functions and leave all other code unchanged.

My $0.02 (I like that one :) ). 1. IMHO it is bad to be able to call both as function and as property, it confuses adopters. 2. Breaking backward compatibility for properties is too late(?). 3. I want more syntactic sugar! Today we have int length(char[] str); That can be called in two ways: 1. int bar = length(foo); 2. int baz = foo.length; Why not add a "property" modifier, like this; property int length(char[] str); And now the 1. syntax is forbidden for the "function".

I love it. Especially if it meant that properties could be added to any type (including built-in types), rather than just arrays.

I can not see why this could not be made to work with any type. But then again I see no reason why the "void func(T foo)" only creates "fake methods" for arrays. // Fredrik Olsson
Jan 05 2006
prev sibling parent Ivan Senji <ivan.senji_REMOVE_ _THIS__gmail.com> writes:
Sean Kelly wrote:
 
 I think a property syntax is a reasonable idea so long as we don't lose 
 the ability to use free functions as properties.  I'm finding it quite 
 useful that I can even replace global variables with no-argument 
 functions and leave all other code unchanged.
 

I find it really useful too, but wouldn't agree on the unchanged part. int x; and replace it with: int x(){return ...} int x(int ... this code will break: void bla(inout int v); bla(x); I really wish there was a reasonable way of solving this problem. Not ideal but maybe translating the above code to: int __x = x(); bla(__x); x(__x);
Jan 05 2006
prev sibling parent reply "John C" <johnch_atms hotmail.com> writes:
 Your example seems a bit odd to me as the setter can have a different 
 input type
 from the getter.

No it can't. I do note in my original post that the types have to match.
 If you're going to go the way of implementing a whole property
 block it seems that they should have their type specified in the property 
 area.
 In which case we might as well adopt the C# syntax for properties.

It was an attempt to avoid context-sensitive keywords, which Walter's not fond of. Hence type signatures in my design take the place of 'get' and 'set'.
Jan 04 2006
parent reply S. Chancellor<dnewsgr mephit.kicks-ass.org> writes:
n article <dphnia$si9$1 digitaldaemon.com>, John C says...
 Your example seems a bit odd to me as the setter can have a different
 input type
 from the getter.

No it can't. I do note in my original post that the types have to match.

It can as long as I type it twice. If there's a restriction that it has to be what I typed the first time... then I shouldn't have to type it twice.
 If you're going to go the way of implementing a whole property
 block it seems that they should have their type specified in the property
 area.
 In which case we might as well adopt the C# syntax for properties.

It was an attempt to avoid context-sensitive keywords, which Walter's not fond of. Hence type signatures in my design take the place of 'get' and 'set'.

True, but either way uses context-sensitive something. The current method doesn't require context sensitive anything. If we're going to introduce new semantic regions, and change the syntax for function declarations within, we might as well introduce keywords for it. Your method just reuses keywords, for something they weren't intended, which is arguably more confusing. -S.
Jan 04 2006
parent James Dunne <james.jdunne gmail.com> writes:
S. Chancellor wrote:
 n article <dphnia$si9$1 digitaldaemon.com>, John C says...
 
Your example seems a bit odd to me as the setter can have a different
input type
from the getter.

No it can't. I do note in my original post that the types have to match.

It can as long as I type it twice. If there's a restriction that it has to be what I typed the first time... then I shouldn't have to type it twice.
If you're going to go the way of implementing a whole property
block it seems that they should have their type specified in the property
area.
In which case we might as well adopt the C# syntax for properties.

It was an attempt to avoid context-sensitive keywords, which Walter's not fond of. Hence type signatures in my design take the place of 'get' and 'set'.

True, but either way uses context-sensitive something. The current method doesn't require context sensitive anything. If we're going to introduce new semantic regions, and change the syntax for function declarations within, we might as well introduce keywords for it. Your method just reuses keywords, for something they weren't intended, which is arguably more confusing. -S.

Well said!
Jan 04 2006
prev sibling next sibling parent reply James Dunne <james.jdunne gmail.com> writes:
John C wrote:
 As I see it, the problem with D's property syntax is that they're actually 
 methods, and the compiler has to try to disamiguate between method and 
 property calls/assignments, which it's not 100% successful at - sometimes 
 you have to add a pair of parentheses '()' when using a property to stop the 
 compiler from choking (for example, when used in conjunction with 'auto').
 
 Another issue is that it introduces ambiguity in the way they are called, 
 and users have no way of knowing how they are intended to be used - 
 'my.name("John")' or 'my.name = "John"'.
 
 The other issue is that properties have the semantics of fields, not methods 
 (even if, in the end, the compiler just generates the same code as for a 
 method). They just don't feel like first-class citizens.

Properties are meant to have the same semantics as methods, NOT fields. They are made to have the same SYNTAX as fields. I agree, they don't feel like first-class citizens in D.
 I'd like to suggest a new syntax that I think addresses these issues. The 
 only downside is the addition of a new keyword, 'property'. But otherwise 
 it's quite elegant and is only slightly more verbose than the current syntax 
 (the keyword itself). It's basically a way of grouping a pair of getters and 
 setters in a 'property block'.

 
 Here's a class that utilises it.
 
     class Person {
 
         private float weight_; // Manually written backing store for 
 'weight' property
 
         protected void onWeightChanged() {
             // Warn of heart attack risk if above a certain weight
         }
 
         property weight { // 'weight' property block
             float() { // This defines the signature of the getter
                 return weight_;
             }
             void(float value) { // This defines the signature of the setter;
                                         // setters must have a void return 
 type
                 weight_ = value;
                 onWeightChanged();
             }
         } // end 'weight' property block

Why must the return value of the setter be void? What if I want to chain my property setter calls in an 'a = b = c = d' manner? Then if you change the void-return rule to allow returning any type, you must then define if that return type is required to match the implied type of the property. It follows that it becomes increasingly more difficult to determine the actual type of the property. Another note, it would be much clearer to the D beginner if he/she were required to name the getter method as "get" and the setter method as "set", instead of the quirky-looking identifier-removed function definition syntax proposed above. Best to remain consistent with the rest of the language - it also makes implementation easier.
         // In this property block, we don't provide definitions,
         // which tells the compiler to generate a backing store
         // and the definitions on our behalf.
         // Let's call it a 'simple property'.
         property height {
             float();
             void(float);
         }

Does this mean that properties can be inherited and overridden?
 
         // property block with getter only
         property bmi {
             float() {
                 return weight / (height * height);
             }
         }
 
     }
 
 Some notes:
 1) Any attempt to define a setter with an argument type that doesn't match 
 that of the getter return type would be an error (and vise versa).

Lol. There is no vice-versa in this case. =P
 2) Different protection attributes can be applied to the getter and setter, 
 as with methods.

So, hypothetically, I can read from a property in public and perhaps write to it only in a child class? What's the point of that?
 3) For property blocks without manual definitions (as in the 'height' 
 example above), either the getter or setter signature can be omitted, making 
 them either read- or write-only, which distinguishes them from public 
 fields.

This would make them read-only, write-only, OR read/write properties, not just either read-only or write-only. Best to be clear about such things. In fact, the notion of a field being read-only doesn't really apply here in the true sense of the return value being read-only.
 4) Within the scope of a property block, use of the property name itself is 
 legal, since the compiler knows to refer to the automatically generated 
 backing store (as opposed to introducing a recursive call).

You mean use of the property name when defining a local variable to one of the setter/getter methods, right? AFAIK, we don't allow such things in regular functions so this would be inconsistent with the rest of D.
 No doubt there will be objections to this notation, so fire away. But I 
 reckon it's a nice compromise between the C# and C++/CLI syntaxes (which 
 require three contextual keywords: 'get', 'set' and 'value') and the current 
 D syntax.

Nobody says that "get" or "set" must be keywords (or contextual keywords). They can be context-dependent special identifiers. ------------------- Why not propose also a 'reflect' sort-of syntax, such that a public property may reflect the value of a corresponding private member without having to write redundant code. I see a lot of situations like this in C#, where public properties simply reflect values of private members. It seems completely silly to write such redundant code as C#: property float Height { get { return _height; } set { _height = value; } } Your proposed D syntax: property Height { float() { return _height; } void (float value) { _height = value; } } Why not reduce the potential for bugs in such a case by telling the compiler what you actually want to do? I don't see any clean way to do this in addition to your syntax proposal, unfortunately.
Jan 04 2006
next sibling parent reply Derek Parnell <derek psych.ward> writes:
On Wed, 04 Jan 2006 20:00:53 -0600, James Dunne wrote:

 It seems completely silly to write such redundant code as
 
 C#:
 property float Height {
 	get { return _height; }
 	set { _height = value; }
 }
 
 Your proposed D syntax:
 property Height {
 	float() { return _height; }
 	void (float value) { _height = value; }
 }

And current D syntax: float Height() { return _height; } void Height(float value) { _height = value; }
 Why not reduce the potential for bugs in such a case by telling the 
 compiler what you actually want to do?  I don't see any clean way to do 
 this in addition to your syntax proposal, unfortunately.

Just playing here but something like this seems nice to me ... float _height; property Height { get float { Height = _height; } // Value must be zero or greater. set float { _height = fmax(0.0, Height); } set real { _height = fmax(0.0, cast(float)Height); } set char[]{ _height = fmax(0.0, atof(Height)); } } And assignment chaining would be achieved by calling the getter whenever needed. a.Height = b.Height = "4.0"; would be equivalent to ... b.setHeight("4.0"); a.setHeight( b.getHeight() ); -- 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 5/01/2006 1:51:53 PM
Jan 04 2006
next sibling parent reply S. Chancellor<dnewsgr mephit.kicks-ass.org> writes:
Derek Parnell <derek psych.ward> wrote:
Just playing here but something like this seems nice to me ...

  float _height;
  property Height {
     get float { Height = _height; }
     // Value must be zero or greater.
     set float { _height = fmax(0.0, Height); }
     set real  { _height = fmax(0.0, cast(float)Height); }
     set char[]{ _height = fmax(0.0, atof(Height)); }
  }
 
And assignment chaining would be achieved by calling the getter whenever
needed.

   a.Height = b.Height = "4.0";

would be equivalent to ...

   b.setHeight("4.0");
   a.setHeight( b.getHeight() );

I don't know that I like the idea of having properties accept more than one type input. I think they should use the normal type conversion rules if the property doesn't accept the type of data you want to shove into it. -S. -- Email works.
Jan 04 2006
parent Derek Parnell <derek psych.ward> writes:
On Thu, 5 Jan 2006 03:39:24 +0000 (UTC), S. Chancellor wrote:

 I don't know that I like the idea of having properties accept more than
 one type input.  I think they should use the normal type conversion
 rules if the property doesn't accept the type of data you want to shove into
 it.

Why? And as a side point, I would really like to be able to specify abnormal type conversions that are called by the compiler on assignment. -- 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 5/01/2006 3:22:11 PM
Jan 04 2006
prev sibling parent reply Chris Sauls <ibisbasenji gmail.com> writes:
Derek Parnell wrote:
 Just playing here but something like this seems nice to me ...
 
   float _height;
   property Height {
      get float { Height = _height; }
      // Value must be zero or greater.
      set float { _height = fmax(0.0, Height); }
      set real  { _height = fmax(0.0, cast(float)Height); }
      set char[]{ _height = fmax(0.0, atof(Height)); }
   }

I proposed something similar to this many ages ago. Mine looked like: # class Foo { # property int height { # int _height; # int get () { return _height; } # int set (int x) { return _height = x; } # int set (char[] x) { return _height = toInt(x); } # } # } If I remember right. I'm not sure how I feel about the reflective style, where property 'height' has an auto-generated storage of '_height' as mentioned in another post, but it does solve a problem. Maybe the syntax should be more like what you suggest, but with the gettor not concernings itself with type (in other words, the property is considered strongly typed for get purposes). So, something like: # property int height { # get { return _height; } // leave out to make input-only # set (int x) { _height = x; } // leave out to make read-only # set (char[] x) { _height = toInt(x); } // user-defined implicit conversion # } No redundant type information, yet we get keywords... that's one notable downside, especially the keywords 'get' and 'set' which can make perfectly good sense as collection object methods. -- Chris Sauls
Jan 04 2006
next sibling parent reply James Dunne <james.jdunne gmail.com> writes:
Chris Sauls wrote:
 Derek Parnell wrote:
 
 Just playing here but something like this seems nice to me ...

   float _height;
   property Height {
      get float { Height = _height; }
      // Value must be zero or greater.
      set float { _height = fmax(0.0, Height); }
      set real  { _height = fmax(0.0, cast(float)Height); }
      set char[]{ _height = fmax(0.0, atof(Height)); }
   }

I proposed something similar to this many ages ago. Mine looked like: # class Foo { # property int height { # int _height; # int get () { return _height; } # int set (int x) { return _height = x; } # int set (char[] x) { return _height = toInt(x); } # } # } If I remember right. I'm not sure how I feel about the reflective style, where property 'height' has an auto-generated storage of '_height' as mentioned in another post, but it does solve a problem. Maybe the syntax should be more like what you suggest, but with the gettor not concernings itself with type (in other words, the property is considered strongly typed for get purposes). So, something like: # property int height { # get { return _height; } // leave out to make input-only # set (int x) { _height = x; } // leave out to make read-only # set (char[] x) { _height = toInt(x); } // user-defined implicit conversion # } No redundant type information, yet we get keywords... that's one notable downside, especially the keywords 'get' and 'set' which can make perfectly good sense as collection object methods. -- Chris Sauls

<rant> What is it with you people and the dependence on keywords? =P You only need a special context-dependent identifier - this is NOT A KEYWORD. Keywords are language tokens and can only be used for the one thing that they mean. OTOH, a special context-dependent identifier (as I call it, I guess) means that the compiler tests the name of the identifier given for a special word only within certain contexts. In this case, when getter/setter methods are defined within a property block, the identifiers "get" and "set" have special meaning and are not just regular identifiers anymore. HOWEVER, EVERYWHERE ELSE THEY HAVE NO SPECIAL MEANING. </rant> Not blowing up on you particularly, Chris. =)
Jan 04 2006
parent reply Chris Sauls <ibisbasenji gmail.com> writes:
James Dunne wrote:
 <rant>
 What is it with you people and the dependence on keywords? =P  You only 
 need a special context-dependent identifier - this is NOT A KEYWORD. 
 Keywords are language tokens and can only be used for the one thing that 
 they mean.  OTOH, a special context-dependent identifier (as I call it, 
 I guess) means that the compiler tests the name of the identifier given 
 for a special word only within certain contexts.
 
 In this case, when getter/setter methods are defined within a property 
 block, the identifiers "get" and "set" have special meaning and are not 
 just regular identifiers anymore.  HOWEVER, EVERYWHERE ELSE THEY HAVE NO 
 SPECIAL MEANING.
 </rant>
 
 Not blowing up on you particularly, Chris. =)

No worries, actually what you say makes perfectly good sense. I probably shouldn't post to the NG right after ten hour shifts, else I might've realised that on my own. :) -- Chris Sauls
Jan 05 2006
parent James Dunne <james.jdunne gmail.com> writes:
Chris Sauls wrote:
 James Dunne wrote:
 
 <rant>
 What is it with you people and the dependence on keywords? =P  You 
 only need a special context-dependent identifier - this is NOT A 
 KEYWORD. Keywords are language tokens and can only be used for the one 
 thing that they mean.  OTOH, a special context-dependent identifier 
 (as I call it, I guess) means that the compiler tests the name of the 
 identifier given for a special word only within certain contexts.

 In this case, when getter/setter methods are defined within a property 
 block, the identifiers "get" and "set" have special meaning and are 
 not just regular identifiers anymore.  HOWEVER, EVERYWHERE ELSE THEY 
 HAVE NO SPECIAL MEANING.
 </rant>

 Not blowing up on you particularly, Chris. =)

No worries, actually what you say makes perfectly good sense. I probably shouldn't post to the NG right after ten hour shifts, else I might've realised that on my own. :) -- Chris Sauls

Ouch. Yeah this whole week I'm pulling 10-12 hour shifts, 9am to 9pm or so. Deadlines are so stupid and pointless... especially when no one outside your organization is depending on them, and even when they have no effect on anything.
Jan 05 2006
prev sibling parent reply Derek Parnell <derek psych.ward> writes:
On Thu, 05 Jan 2006 00:46:02 -0600, Chris Sauls wrote:

 I proposed something similar to this many ages ago.  Mine looked like:
 
 # class Foo {
 #   property int height {
 #     int _height;
 #     int get () { return _height; }
 #     int set (int x) { return _height = x; }
 #     int set (char[] x) { return _height = toInt(x); }
 #   }
 # }
 
 If I remember right.  I'm not sure how I feel about the reflective style,
where property 
 'height' has an auto-generated storage of '_height' as mentioned in another
post, but it 
 does solve a problem.  Maybe the syntax should be more like what you suggest,
but with the 
 gettor not concernings itself with type (in other words, the property is
considered 
 strongly typed for get purposes).  So, something like:
 
 # property int height {
 #   get { return _height; } // leave out to make input-only
 #   set (int x) { _height = x; } // leave out to make read-only
 #   set (char[] x) { _height = toInt(x); } // user-defined implicit conversion
 # }

However, there is no necessary requirement for a property to be implemented by just a single internal (private?) variable. Also, other members in the class might deal with the internal property variables in a more efficient manner than using the get/set paradigm. Ok, so here's another refinement ... private { float A; long B; } property goofy { out (float) { goofy = cast(float)B + A; } in (float) { B = cast(long) toInt(goofy); A = goofy - cast(float)B;} } void someFunc(long x) { if (B > 0) B *= x; } Sure this is contrived, but you get my point. I imagine the purpose of properties is to totally divorce the implementation from the usage. Such that the 'public' face of the property is a float, for example, but the implementation can change over time without haven't to change any referencing source code. The implementation can start off being a simple, single float variable but later can change to some complex function and all the source code that references the property doesn't have to be modified.
 No redundant type information, yet we get keywords... that's one notable
downside, 
 especially the keywords 'get' and 'set' which can make perfectly good sense as
collection 
 object methods.

So maybe 'gettor' and 'settor' as special and unusual words? -- 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 5/01/2006 6:01:22 PM
Jan 04 2006
next sibling parent Chris Sauls <ibisbasenji gmail.com> writes:
Derek Parnell wrote:
 However, there is no necessary requirement for a property to be implemented
 by just a single internal (private?) variable. Also, other members in the
 class might deal with the internal property variables in a more efficient
 manner than using the get/set paradigm.
 
 Ok, so here's another refinement ...
 
   private {
     float A;
     long  B;
   }
   property goofy {
      out (float) { goofy = cast(float)B + A; }
      in  (float) { B = cast(long) toInt(goofy);
                  A = goofy - cast(float)B;}
   }
   void someFunc(long x)
   {
       if (B > 0) B *= x;
   }
 
 Sure this is contrived, but you get my point.
 

Actually, Derek, I think I like your refined proposal, even the new use of the in/out keywords (despite my recent education on that matter, see other posts). It might've been arguable that internally a class might be able to do something like 'this.height._height' but... ew. My only quirk, is I really would prefer the gettor type of a property be strong. I just don't trust the compiler enough, I guess? There would have to be fairly explicit rules about how it determines which 'out' clause to use. -- Chris Sauls
Jan 05 2006
prev sibling parent reply "Kris" <fu bar.com> writes:
"Derek Parnell" <derek psych.ward> wrote...
 On Thu, 05 Jan 2006 00:46:02 -0600, Chris Sauls wrote:

 I proposed something similar to this many ages ago.  Mine looked like:

 # class Foo {
 #   property int height {
 #     int _height;
 #     int get () { return _height; }
 #     int set (int x) { return _height = x; }
 #     int set (char[] x) { return _height = toInt(x); }
 #   }
 # }


 Ok, so here's another refinement ...

  private {
    float A;
    long  B;
  }
  property goofy {
     out (float) { goofy = cast(float)B + A; }
     in  (float) { B = cast(long) toInt(goofy);
                 A = goofy - cast(float)B;}
  }
  void someFunc(long x)
  {
      if (B > 0) B *= x;
  }

 Sure this is contrived, but you get my point.

 I imagine the purpose of properties is to totally divorce the
 implementation from the usage. Such that the 'public' face of the property
 is a float, for example, but the implementation can change over time
 without haven't to change any referencing source code. The implementation
 can start off being a simple, single float variable but later can change 
 to
 some complex function and all the source code that references the property
 doesn't have to be modified.

Not so much the purpose of properties, but the purpose of behavioral abstraction. 'Normal' methods are no different in this regard, and classes are just larger-grained instances. Programs themselves are larger-grained again. I know you know this, but it's worth regurgitating anyway. While I think the idea of special 'property' sugar is seductive, one has to wonder whether it really has value? For instance, the 'normal' implementation of the above example is approximately as follows: private float A; private long B; void setGoofy (float goofy) { B = cast(long) toInt(goofy); A = goofy - cast(float) B; } float getGoofy () { return cast(float) B + A; } void someFunc (long x) { if (B > 0) B *= x; } I think it's arguable that the above is actually clearer (partly because you don't have to understand alternate syntax), plus you also have the options to inherit, override, implement call-chaining etc. Sure, it might be nice to have some means of reducing the amount of typing involved for trivial properties; but isn't there always a tradeoff? And, isn't the 'typing aspect' a job for an IDE? 2 Cents;
Jan 05 2006
parent reply "Derek Parnell" <derek psych.ward> writes:
On Fri, 06 Jan 2006 05:52:44 +1100, Kris <fu bar.com> wrote:


[snip]

 While I think the idea of special 'property' sugar is seductive, one has  
 to
 wonder whether it really has value? For instance, the 'normal'
 implementation of the above example is approximately as follows:

 private float A;
 private long B;

 void setGoofy (float goofy)
 {
     B = cast(long) toInt(goofy);
    A = goofy - cast(float) B;
 }

 float getGoofy ()
 {
    return cast(float) B + A;
 }

 void someFunc (long x)
 {
     if (B > 0) B *= x;
 }

 I think it's arguable that the above is actually clearer (partly because  
 you
 don't have to understand alternate syntax), plus you also have the  
 options
 to inherit, override, implement call-chaining etc.

 Sure, it might be nice to have some means of reducing the amount of  
 typing
 involved for trivial properties; but isn't there always a tradeoff? And,
 isn't the 'typing aspect' a job for an IDE?

Yes, I understood all of that but the difference is in how you refer to the 'property'. With a true property it would X = A.goofy; and in your version it would be X = A.getGoofy(); The difference is not just how much you type in. For example the original version of the class might have defined 'goofy' as just ... float goofy; So code referring to it would have been ... X = A.goofy; And then later when it was turned into a property, that type of reference would not also have to be changed but if the function-type property was implemented (ala your example) all references to 'goofy' would also have to be changed. Why can't one inherit, override, and implement call-chaining with properties? There is nothing built into the concept which precluses those functionalities. You can even get compilers to cope with properties beibg used as 'inout' parameters if one wanted to. -- Derek Parnell Melbourne, Australia
Jan 05 2006
next sibling parent reply "Kris" <fu bar.com> writes:
"Derek Parnell" <derek psych.ward> wrote ...
 On Fri, 06 Jan 2006 05:52:44 +1100, Kris <fu bar.com> wrote:


 [snip]
 Yes, I understood all of that but the difference is in how you refer to 
 the 'property'. With a true property it would

     X = A.goofy;

 and in your version it would be

     X = A.getGoofy();

Isn't that's just a naming concern? The method approach could just as easily be: float goofy() { return XYZ; } Thus producing X = A.goofy(); which the compiler will currently map to X = A.goofy;
 The difference is not just how much you type in. For example the original 
 version of the class might have defined 'goofy' as just ...

      float goofy;

 So code referring to it would have been ...

     X = A.goofy;

 And then later when it was turned into a property, that type of reference 
 would not also have to be changed but if the function-type property was 
 implemented (ala your example) all references to 'goofy' would also have 
 to be changed.

I thought the compiler currently supports method references in an identical manner e.g. X = A.goofy; Does it not?
Jan 05 2006
parent reply Chris Sauls <ibisbasenji gmail.com> writes:
Kris wrote:
 I thought the compiler currently supports method references in an identical 
 manner e.g. X = A.goofy;
 
 Does it not?

It does, although the last time I tried playing with this syntax, it would break in random places, requiring the addition of the parenthesis to resolve correctly. That might have been mostly resolved, though; I don't know. -- Chris Sauls
Jan 05 2006
parent "Kris" <fu bar.com> writes:
"Chris Sauls" <ibisbasenji gmail.com> wrote ...
 Kris wrote:
 I thought the compiler currently supports method references in an 
 identical manner e.g. X = A.goofy;

 Does it not?

It does, although the last time I tried playing with this syntax, it would break in random places, requiring the addition of the parenthesis to resolve correctly. That might have been mostly resolved, though; I don't know.

OK, Gotcha. I think that's still the case? It seems to be that it always works from within an expression e.g. if (x.goofy) ... but sometimes fails when used as the rValue of an assignment? Should that be reported as a bug?
Jan 05 2006
prev sibling parent "Kris" <fu bar.com> writes:
Doh! Forgot to add something:

"Derek Parnell" <derek psych.ward> wrote ..
 On Fri, 06 Jan 2006 05:52:44 +1100, Kris <fu bar.com> wrote:
 [snip]
 The difference is not just how much you type in. For example the original 
 version of the class might have defined 'goofy' as just ...

      float goofy;

 So code referring to it would have been ...

     X = A.goofy;

 And then later when it was turned into a property, that type of reference 
 would not also have to be changed but if the function-type property was 
 implemented (ala your example) all references to 'goofy' would also have 
 to be changed.

This is a refactoring issue, which is surely a much larger problem than the specific handling of 'properties'? For example, what happens when I want to change the name of a method? Or the order of method-arguments? Or the types or number of arguments? Or the name of a class? etc.etc. As a recent post noted, this is the domain of 3rd party tools, such as Eclipse or IntelliJ, which handle just this kind of thing with aplomb. It is certainly a delight to heavily refactor a large body of code in just a few minutes rather than possibly days of tedious grunt-work. And to do it all in a manner that does not introduce errors <g> A refactoring module for one of the developing D IDE would be a very useful thing to have. - Kris
Jan 05 2006
prev sibling next sibling parent S. Chancellor<dnewsgr mephit.kicks-ass.org> writes:
James Dunne <james.jdunne gmail.com> wrote:

Why not propose also a 'reflect' sort-of syntax, such that a public 
property may reflect the value of a corresponding private member without 
having to write redundant code.  I see a lot of situations like this in 
C#, where public properties simply reflect values of private members. 
It seems completely silly to write such redundant code as

C#:
property float Height {
	get { return _height; }
	set { _height = value; }
}

Your proposed D syntax:
property Height {
	float() { return _height; }
	void (float value) { _height = value; }
}

Why not reduce the potential for bugs in such a case by telling the 
compiler what you actually want to do?  I don't see any clean way to do 
this in addition to your syntax proposal, unfortunately.

I fully agree with your here. I'm glad to find out I'm not alone in the war against blank properties! In fact .NET requires you to write blank properties in some cases. (IE: passing a collection of classes to a DataGrid, you can only specify property names for output.) -S. -- Email works.
Jan 04 2006
prev sibling parent reply "John C" <johnch_atms hotmail.com> writes:
"James Dunne" <james.jdunne gmail.com> wrote in message 
news:dphugm$11vq$1 digitaldaemon.com...
 John C wrote:
 As I see it, the problem with D's property syntax is that they're 
 actually methods, and the compiler has to try to disamiguate between 
 method and property calls/assignments, which it's not 100% successful 
 at - sometimes you have to add a pair of parentheses '()' when using a 
 property to stop the compiler from choking (for example, when used in 
 conjunction with 'auto').

 Another issue is that it introduces ambiguity in the way they are called, 
 and users have no way of knowing how they are intended to be used - 
 'my.name("John")' or 'my.name = "John"'.

 The other issue is that properties have the semantics of fields, not 
 methods (even if, in the end, the compiler just generates the same code 
 as for a method). They just don't feel like first-class citizens.

Properties are meant to have the same semantics as methods, NOT fields. They are made to have the same SYNTAX as fields. I agree, they don't feel like first-class citizens in D.
 I'd like to suggest a new syntax that I think addresses these issues. The 
 only downside is the addition of a new keyword, 'property'. But otherwise 
 it's quite elegant and is only slightly more verbose than the current 
 syntax (the keyword itself). It's basically a way of grouping a pair of 
 getters and setters in a 'property block'.

 Here's a class that utilises it.

     class Person {

         private float weight_; // Manually written backing store for 
 'weight' property

         protected void onWeightChanged() {
             // Warn of heart attack risk if above a certain weight
         }

         property weight { // 'weight' property block
             float() { // This defines the signature of the getter
                 return weight_;
             }
             void(float value) { // This defines the signature of the 
 setter;
                                         // setters must have a void 
 return type
                 weight_ = value;
                 onWeightChanged();
             }
         } // end 'weight' property block

Why must the return value of the setter be void? What if I want to chain my property setter calls in an 'a = b = c = d' manner?

I just hadn't considered it. Makes sense to allow that.
 Then if you change the void-return rule to allow returning any type, you 
 must then define if that return type is required to match the implied type 
 of the property.  It follows that it becomes increasingly more difficult 
 to determine the actual type of the property.

 Another note, it would be much clearer to the D beginner if he/she were 
 required to name the getter method as "get" and the setter method as 
 "set", instead of the quirky-looking identifier-removed function 
 definition syntax proposed above.  Best to remain consistent with the rest 
 of the language - it also makes implementation easier.

I won't contradict you - it is quirky, but I was trying to placate those who might gasp at the propsect of introducing yet more keywords. Once you realise that in fact 'get' and 'set' would only have special meaning within the property block, and that they remain valid identifiers elsewhere, it's ok. The other thing is what name to use for the compiler-generated setter parameter? 'value' is the obvious choice. That the compiler has to generate a magic variable at all shouldn't be an issue, since there's a precedent for this with variadic functions ('_arguments' and '_argptr').
         // In this property block, we don't provide definitions,
         // which tells the compiler to generate a backing store
         // and the definitions on our behalf.
         // Let's call it a 'simple property'.
         property height {
             float();
             void(float);
         }

Does this mean that properties can be inherited and overridden?

Like methods, yes.
         // property block with getter only
         property bmi {
             float() {
                 return weight / (height * height);
             }
         }

     }

 Some notes:
 1) Any attempt to define a setter with an argument type that doesn't 
 match that of the getter return type would be an error (and vise versa).

Lol. There is no vice-versa in this case. =P

Any attempt to define a) a setter with an argument type that doesn't match that of the getter return type, or b) a getter with a return type that doesn't match that of the setter argument type, would be an error. Better?
 2) Different protection attributes can be applied to the getter and 
 setter, as with methods.

So, hypothetically, I can read from a property in public and perhaps write to it only in a child class? What's the point of that?

The same rules that apply to methods should apply to properties.
 3) For property blocks without manual definitions (as in the 'height' 
 example above), either the getter or setter signature can be omitted, 
 making them either read- or write-only, which distinguishes them from 
 public fields.

This would make them read-only, write-only, OR read/write properties, not just either read-only or write-only. Best to be clear about such things.

Yes, that's clearer.
 In fact, the notion of a field being read-only doesn't really apply here 
 in the true sense of the return value being read-only.

 4) Within the scope of a property block, use of the property name itself 
 is legal, since the compiler knows to refer to the automatically 
 generated backing store (as opposed to introducing a recursive call).

You mean use of the property name when defining a local variable to one of the setter/getter methods, right? AFAIK, we don't allow such things in regular functions so this would be inconsistent with the rest of D.

I should have said with a "simple property" block, since there's no backing store variable to refer to until compilation.
 No doubt there will be objections to this notation, so fire away. But I 
 reckon it's a nice compromise between the C# and C++/CLI syntaxes (which 
 require three contextual keywords: 'get', 'set' and 'value') and the 
 current D syntax.

Nobody says that "get" or "set" must be keywords (or contextual keywords). They can be context-dependent special identifiers.

Point taken, although if you've read some of the other replies, you'll see people are inferring that this would require them to be keywords.
 -------------------
 Why not propose also a 'reflect' sort-of syntax, such that a public 
 property may reflect the value of a corresponding private member without 
 having to write redundant code.  I see a lot of situations like this in 
 C#, where public properties simply reflect values of private members. It 
 seems completely silly to write such redundant code as

 C#:
 property float Height {
 get { return _height; }
 set { _height = value; }
 }

It's redundant until the class writer decides to perform more complex operations within the accessor functions (such as resizing a window or repainting a shape). But yes, if it's just going to update a private field, and it's read/write, then you may as well use a public field. Unless there's extra value in tagging something as a property (perhaps for the benefit of an IDE or Ddoc documentation).
 Your proposed D syntax:
 property Height {
 float() { return _height; }
 void (float value) { _height = value; }
 }

 Why not reduce the potential for bugs in such a case by telling the 
 compiler what you actually want to do?  I don't see any clean way to do 
 this in addition to your syntax proposal, unfortunately.

Maybe something analogous to an alias: property Height _height;
Jan 05 2006
parent reply Chris Sauls <ibisbasenji gmail.com> writes:
John C wrote:
 Any attempt to define a) a setter with an argument type that doesn't match 
 that of the getter return type, or b) a getter with a return type that 
 doesn't match that of the setter argument type, would be an error.
 
 Better?

Clearer, yes... Better, no, IMHO. :) I don't see the utility in requiring that a property only allow one data type for its settor. I'm all for locking down the gettor, but being able to send different kinds of data into a property can make perfectly good sense in some designs. Stupid example: a property for setting an HTTP response code, which accepts either a ushort (401, 202, etc) or a string (char[], wchar[], dchar[]) containing the code number.
2) Different protection attributes can be applied to the getter and 
setter, as with methods.



I do like this. -- Chris Sauls
Jan 05 2006
parent "John C" <johnch_atms hotmail.com> writes:
"Chris Sauls" <ibisbasenji gmail.com> wrote in message 
news:dpjn4t$2i2k$1 digitaldaemon.com...
 John C wrote:
 Any attempt to define a) a setter with an argument type that doesn't 
 match that of the getter return type, or b) a getter with a return type 
 that doesn't match that of the setter argument type, would be an error.

 Better?

Clearer, yes... Better, no, IMHO. :) I don't see the utility in requiring that a property only allow one data type for its settor. I'm all for locking down the gettor, but being able to send different kinds of data into a property can make perfectly good sense in some designs. Stupid example: a property for setting an HTTP response code, which accepts either a ushort (401, 202, etc) or a string (char[], wchar[], dchar[]) containing the code number.

I think I see what you're getting at - like overloads, but contained within the property block? That sounds useful, I hadn't considered it.
2) Different protection attributes can be applied to the getter and 
setter, as with methods.



I do like this. -- Chris Sauls

Jan 05 2006
prev sibling parent reply "Chris Miller" <chris dprogramming.com> writes:
How about simply adding a 'property' attribute? The compiler could at  
least enforce more rules with it, like making sure the get/set types  
match, allow them to be used more like fields, not allow them to be used  
like functions (which the magic, built-in ones already enforce  
(inconsistent)), and not allow regular functions to be used as properties.
Example:


private int _foo = 1;

    property int foo() { return 3; }


Or use a property block to group them, since it's an attribute:


    property
    {
       int foo() { return 3; }
       void foo(int value) { _foo = value; }
    }


Yes, there's duplicated information, but it's much simpler on the compiler  
and will require minimal changes to existing code.
- Chris
Jan 05 2006
parent reply "Kris" <fu bar.com> writes:
"Chris Miller" <chris dprogramming.com> wrote
 How about simply adding a 'property' attribute? The compiler could at 
 least enforce more rules with it, like making sure the get/set types 
 match, allow them to be used more like fields, not allow them to be used 
 like functions (which the magic, built-in ones already enforce 
 (inconsistent)), and not allow regular functions to be used as properties.
 Example:


 private int _foo = 1;

    property int foo() { return 3; }


 Or use a property block to group them, since it's an attribute:


    property
    {
       int foo() { return 3; }
       void foo(int value) { _foo = value; }
    }


 Yes, there's duplicated information, but it's much simpler on the compiler 
 and will require minimal changes to existing code.

I'm still trying to get a handle on this, Chris, so please forgive the naiive questions: a) Is this based on a desire to use 'property' methods as lValues? b) what exactly are the characteristics that distinguish a 'property' method from a 'normal' one? - Kris
Jan 05 2006
parent reply "Chris Miller" <chris dprogramming.com> writes:
On Thu, 05 Jan 2006 17:24:16 -0500, Kris <fu bar.com> wrote:

 "Chris Miller" <chris dprogramming.com> wrote
 How about simply adding a 'property' attribute? The compiler could at
 least enforce more rules with it, like making sure the get/set types
 match, allow them to be used more like fields, not allow them to be used
 like functions (which the magic, built-in ones already enforce
 (inconsistent)), and not allow regular functions to be used as  
 properties.
 Example:


 private int _foo = 1;

    property int foo() { return 3; }


 Or use a property block to group them, since it's an attribute:


    property
    {
       int foo() { return 3; }
       void foo(int value) { _foo = value; }
    }


 Yes, there's duplicated information, but it's much simpler on the  
 compiler
 and will require minimal changes to existing code.

I'm still trying to get a handle on this, Chris, so please forgive the naiive questions: a) Is this based on a desire to use 'property' methods as lValues?

No, so that you can't use properties as functions and you can't use functions as properties, so they're used as intended; and the other reasons I explained above; also so that documentation generation like Ddoc can output function or property as appropriate.
 b) what exactly are the characteristics that distinguish a 'property'  
 method
 from a 'normal' one?

property attribute; personal preference to have property or method.. not sure what you want me to say here beyond what I already said.
Jan 05 2006
parent reply "Kris" <fu bar.com> writes:
"Chris Miller" <chris dprogramming.com> wrote ...
[snip]
 I'm still trying to get a handle on this, Chris, so please forgive the
 naiive questions:

 a) Is this based on a desire to use 'property' methods as lValues?

No, so that you can't use properties as functions and you can't use functions as properties, so they're used as intended;

I'll admit that I don't see a solid semantic distinction (at the code-usage level) between 'property' methods and 'normal' methods (or did you mean some other kind of function?). They are both an exposure of capability via some level of abstraction. They can both set or expose internal state. They can both be arbitrarily complex or completely trivial. They are both intended to encapsulate behaviour specific to their containing entity. Why is one somehow special? I don't get it :-(
 and the other reasons I explained above;

While it does seem reasonable for set/get to be consistent in type usage, it's not necessarily a hard rule. If it were, some people might use 'functions' instead of 'properties' to get around it, leading to other problems? And, could this kind of thing (auto-generation of appropriate methods, with consistent types) perhaps be handled by an IDE, similar to the refactoring angle? Do Eclipse and IntelliJ (etc) do it this way?
 also so that documentation generation like Ddoc  can output function or 
 property as appropriate.

That makes sense only if you view them as sematically distinct from a code usage-aspect? OTOH, I do see a usage distinction regarding IDE handling of properties, such as property sheets and so on? But that seems quite different from a code-usage perpective ~ instead, IDE property sheets expose an alternative to explicit, configuration of components? If so, could the notion of a 'property' be just some kind of convenient tagging that an IDE looks for? For example: class X { property double velocity; property char[] description; ... } Perhaps the notion could be used by an IDE to expand into other composite aggregates? e.g. class Y { property int something; property X x; ... } There would presumeably be no need to do the same via inheritance? Perhaps, with introspection, such a tag might be useful for other things? These examples use 'property' purely for attribute-decoration only ~ they don't change the behaviour of the compiler per se, except perhaps to imply "private"? - Kris
Jan 05 2006
next sibling parent tj0258 gmail.com writes:
I myself see setters & getters being different from ordinary functions:

1) Set always is passed a single parameter and returns void.
2) Get always returns a single type.
3) Set will always change the state of an object (unless rvalue is current
value).  Functions don't necessarily change the state of the value.
4) Get and Set provide a standardization to access the properties of an object.
Otherwise we could have code like car.setwheelcount(4), assert
(car.passengerscount(4)!=0) and if(car.wiperblades()=3) { writefln("mgb!\n") }


Tom J

From http://c2.com/cgi/wiki?AccessorsAreEvil

..Setters and Getters are different breeds of dog.

A setter involves this-here-object modifying the state of that-there-object.
This almost always creates maintenence problems and is smelly in the extreme.

If fu needs data from bar because (and only because) bar is the authoritative
source or an agent of the authoritative source (users, databases and other
outside things need agents), then bar needs to provide a getter interface for fu
to use. There are a half-dozen design patterns to choose from that let bar tell
any and all interested fus that new or changed data is available and to "come
and get it". Since fu is in control, and the coupling is kept to the minimum
required for bar to provide its service, it doesn't smell at all. This is the
essence of MVC.


In article <dpkeff$462$1 digitaldaemon.com>, Kris says...
"Chris Miller" <chris dprogramming.com> wrote ...
[snip]
 I'm still trying to get a handle on this, Chris, so please forgive the
 naiive questions:

 a) Is this based on a desire to use 'property' methods as lValues?

No, so that you can't use properties as functions and you can't use functions as properties, so they're used as intended;

I'll admit that I don't see a solid semantic distinction (at the code-usage level) between 'property' methods and 'normal' methods (or did you mean some other kind of function?). They are both an exposure of capability via some level of abstraction. They can both set or expose internal state. They can both be arbitrarily complex or completely trivial. They are both intended to encapsulate behaviour specific to their containing entity. Why is one somehow special? I don't get it :-(
 and the other reasons I explained above;

While it does seem reasonable for set/get to be consistent in type usage, it's not necessarily a hard rule. If it were, some people might use 'functions' instead of 'properties' to get around it, leading to other problems? And, could this kind of thing (auto-generation of appropriate methods, with consistent types) perhaps be handled by an IDE, similar to the refactoring angle? Do Eclipse and IntelliJ (etc) do it this way?
 also so that documentation generation like Ddoc  can output function or 
 property as appropriate.

That makes sense only if you view them as sematically distinct from a code usage-aspect? OTOH, I do see a usage distinction regarding IDE handling of properties, such as property sheets and so on? But that seems quite different from a code-usage perpective ~ instead, IDE property sheets expose an alternative to explicit, configuration of components? If so, could the notion of a 'property' be just some kind of convenient tagging that an IDE looks for? For example: class X { property double velocity; property char[] description; ... } Perhaps the notion could be used by an IDE to expand into other composite aggregates? e.g. class Y { property int something; property X x; ... } There would presumeably be no need to do the same via inheritance? Perhaps, with introspection, such a tag might be useful for other things? These examples use 'property' purely for attribute-decoration only ~ they don't change the behaviour of the compiler per se, except perhaps to imply "private"? - Kris

Jan 05 2006
prev sibling parent reply "Zeljko" <gzeljko sezampro.yu> writes:
"Kris" <fu bar.com> wrote in message news:dpkeff$462>
 I'll admit that I don't see a solid semantic distinction (at the

 level) between 'property' methods and 'normal' methods (or did you mean

 other kind of function?). They are both an exposure of capability via some
 level of abstraction. They can both set or expose internal state. They can
 both be arbitrarily complex or completely trivial. They are both intended

 encapsulate behaviour specific to their containing entity. Why is one
 somehow special? I don't get it :-(

Let me cite Dylan Reference Manual: " Order of execution aside, the following pairs of function calls are equivalent: america.capital capital(america) window.position position(window) " and: " name(arg1,...argn ) := new-value behaves exactly the same as begin let temp = new-value; name-setter(temp, arg1,...argn ); temp end " (note: ':=' is Dylan assigment operator as it is '=' in D) No semantics here! Programmers add semantics. What is importan here to have SIMPLE and CONSISTENT GENERAL rule! No special cases. It's beter for programmer and compiler :) At first look D here remembers me Dylan, but it was only half way. Zeljko
Jan 06 2006
parent "Zeljko" <gzeljko sezampro.yu> writes:
 Let me cite Dylan Reference Manual:
 "
 Order of execution aside, the following pairs of function calls are
 equivalent:

 america.capital
 capital(america)

 window.position
 position(window)
 "
 and:
 "
 name(arg1,...argn ) := new-value

 behaves exactly the same as

 begin
   let temp = new-value;
   name-setter(temp, arg1,...argn );
   temp
 end
 "
 (note: ':=' is Dylan assigment operator as it is '=' in D)

 No semantics here! Programmers add semantics.
 What is importan here to have SIMPLE and CONSISTENT GENERAL rule!
 No special cases. It's beter for programmer and compiler :)

Along this lines proposal for D can be (taking in account that D has 'natural methods' what Dylan has not): 1. a.f is equivalent a.f() and a.f() is equivalent to f(a) so: resolve a.f as rvalue: try a.f, then a.f() resolve a.f(): try a.f() then f(a) resolve f(a): unambiguous 2. Only for methods (as it is now, well done IMHO): a.f = x is equivalent a.f(x) Dot! 1a. Sugestion for programmers: use a.f for constant methods only (in C++ sense) (note: some_array.sort or some_aaray.rehash is really wrong, but it is not a big problem if one can use some_array.sort() and everything follows one simple rule. It is always possible to add sam declarative modifier to enforce this pattern of usage.) Not sure, but probably no current code break. Zeljko What is a property? There is no satch thing in D! :) What is a extended method? There is no satch thing in D! :)
Jan 06 2006