properties - Why not the set/get syntax?

Søren J. Løvborg web at kwi.dk
Sun Apr 2 07:11:08 PDT 2006


Cris wrote:
> Why the properties in D do not use the set/get syntax? It looks more clear 
> and natural to me.

The big question is, which syntax?

The (current) D way, with no explicit syntax for declaring properties:

:    int length() { return length_; }
:    void length(value) { length_ = value; }

The C# way, with context-sensitive keywords "get"/"set", and implicit 
"value" variable:

:    int length {
:        get { return length_; }
:        set { length_ = value; }
:    }

The Delphi/Object Pascal way (done C-style), with context-sensitive keywords 
"read"/"write":

:    property int length read getLength write setLength;
:private:
:    int getLength() { return length_; }
:    void setLength(int value) { length_ = value; }

Except that Object Pascal doesn't require one to write such trivial accessor 
methods, so this particular example becomes simply:

:    property int length read length_ write length_;

I'm not really familiar with Python, but apparently there's a similar syntax 
(also done C-style here; Python's construct provides some more options that 
does not apply in D):

:    length = property(getLength, setLength)
:private:
:    int getLength() { return length_; }
:    void setLength(int value) { length_ = value; }

Advantages of the Python construct are the lack of context-sensitive 
keywords, and that it easily supports the same trick as Object Pascal, where 
simple getter/setter methods are implicit:

:    length = property(length_, length_)

Of course, there's not much point in a property that simply gets and sets a 
member variable, but I find that you very often need a property that simply 
gets a member variable, and only performs special processing when setting 
the property. Thus, I also feel that any explicit property syntax should 
allow one to skip defining trivial getter methods.

------

Another, somewhat unrelated topic, is the semantics of properties -- just to 
throw some more balls into the air.

In the previous thread, I notices James Dunne saying:
> Properties are meant to have the same semantics as methods, NOT fields. 
> They are made to have the same SYNTAX as fields.

I disagree. I find that the whole point of properties is to provide 
field-semantics, but with possible side-effects when setting the property.

When I assign a value to a property, I expect to be able to read the 
property and get the same value, as if it was a field.

Ex.: The text on a label (with some UI toolkit or other):

:    label.setText("Hi"); // side effect: the label is repainted.
:    return label.getText(); // returns "Hi".

This is a prime candidate for using property syntax, exactly because of the 
field-like semantics:

:    label.text = "Hi"; // still has side effect, of course.
:    return label.text; // returns "Hi".

A bad candidate for using property syntax (IMO) would be e.g.:

:    console.text = "Hello world."; // prints "Hello world." to the console.
:    return console.text; // reads a line of text from the console.

Not only does console.text not return the value that was just assigned to 
it, it also changes its value everytime it's read.

There are many on this NG (me included) that want the following to be legal 
for properties:

:    obj.prop++;

Again, constructs like this one only makes sense if the property has 
field-like semantics. Whereas

:    console.text ~= "abc";

doesn't make a whole lot of sense.

I'd also expect reading and writing of a property to be non-blocking and not 
terribly computationally expensive, so in my book,

:    thingymabob.terriblyComputationallyExpensiveOp = arg;

is a big no-no, and should be:

:    thingymabob.terriblyComputationallyExpensiveOp(arg);

Of course, this is a matter of preference. But basically, I find that both 
the programmer (and ideally the compiler) should be allowed to make some 
assumptions about properties.

Example:
:    int sum = 0;
:    for (int i = 0; i < list.count; i ++) { sum += list.elements[i]; }

If count is a field, the compiler only needs to evaluate it once, since the 
loop body is known to be side-effect free.

Ideally, if count is a property, the compiler should be able to assume 
field-like semantics, and also only evalute it once.

(Of course, if the loop body called any methods, or assigned to any 
properties, on any object, it would no longer be side-effect free, and the 
above optimizations would not apply, even if count was a field.)

Note that list.elements could be an indexed property, if that was to be 
supported in D, and the compiler would still be allowed to assume no 
side-effects.

I'm aware that in most languages, there are no such assumptions about 
properties: they are merely syntactic sugar. I'll propose that, if we 
introduce an explicit property syntax, we make it into more than just 
syntactic sugar.

This would also introduce one of the (many) functionalities of C++'s const 
into D, namely constant member functions:

In C++, the following explicitly states that the method has no side-effects:

:    int getLength() const;

If we were to mandate field-like semantics for properties in D, we'd 
automatically have this functionality in property getters.

(The fact that (some? many? all?) C++ compilers are over-zealous in their 
attempts to enforce the const'ness of constant methods, and how D should 
handle this, is really a separate discussion...)

--
Søren J. Løvborg
web at kwi.dk 





More information about the Digitalmars-d mailing list