January 08, 2009
<fx chanting vikings in background>
Gripe, Gripe, Gripe. Gripe, Gripe, Gripe, Wonderful Gripe...

</fx>
January 08, 2009
dsimcha wrote:
> == Quote from BCS (ao@pathlink.com)'s article
>> Reply to Vishaal,
>>> Properties, such as array.length, should return lvalues to allow:
>>> a.length += 8;
>>> or other similar statements.
>> I think there is a (long standing) bug report about that one. Maybe if enough
>> people gripe about it it will get fixed! (NOT said sarcastically!)
> 
> Yeah, this has been mentioned in the past before.  The most obvious way to make it
> work w/o any breaking or significantly bulk-adding changes would be to define
> foo.length += 8 to mean foo = foo.length() + 8, or foo.length++ mean foo =
> foo.length + 1.  This would be pure syntactic sugar, as it is when working with
> primitives.
> 
> One problem that comes to mind is if, instead of length, which is presumably some
> kind of integer, you have a property for some user defined type with operator
> overloading.  This user-defined type could define opAdd to do something
> arbitrarily different from opAddAssign.  Even if we assume that no reasonable
> programmer would do this and treat this as a "who cares?" corner case,

It was recently pointed out in another thread that if prop is a class, it is currently nearly IMPOSSIBLE for prop += 8; to be the same as prop = prop + 8;.

Properties therefore seem to be another important reason for fixing up operator overloading.


 there's
> still the problem of opInc and opAddAssign being much cheaper in some cases than
> opAdd.  For example, in some cases opAdd might require copying of a whole bunch of
> stuff, where opInc or opAddAssign just increments a single primitive under the hood.



> 
> Bottom line is, unless we assume that properties of user-defined types aren't
> important, we need a better solution.  Oh yeah, and on the more special case of
> arrays, which the compiler already treats as special, yes, foo.length += 2 should
> be legal.  As far as I can tell, this is a no-brainer.
January 08, 2009
"Michiel Helvensteijn" <nomail@please.com> wrote in message news:gk4oi2$14tv$1@digitalmars.com...
> dsimcha wrote:
>
>> Yeah, this has been mentioned in the past before.  The most obvious way
>> to
>> make it work w/o any breaking or significantly bulk-adding changes would
>> be to define foo.length += 8 to mean foo = foo.length() + 8, or
>> foo.length++ mean foo =
>> foo.length + 1.  This would be pure syntactic sugar, as it is when
>> working
>> with primitives.
>>
>> One problem that comes to mind is if, instead of length, which is
>> presumably some kind of integer, you have a property for some user
>> defined
>> type with operator
>> overloading.  This user-defined type could define opAdd to do something
>> arbitrarily different from opAddAssign.  Even if we assume that no
>> reasonable programmer would do this and treat this as a "who cares?"
>> corner case, there's still the problem of opInc and opAddAssign being
>> much
>> cheaper in some cases than
>> opAdd.  For example, in some cases opAdd might require copying of a whole
>> bunch of stuff, where opInc or opAddAssign just increments a single
>> primitive under the hood.
>
> I've always thought properties should work somewhat like this:
>
> property int length {
>    get() { return this.len; }
>    set(newLen) { this.len = newLen; }
> }
>
> The return-type of get is automatically int, as is the parameter-type of set. These two functions are automatically called when the property is used.
>
> int a = length;
> // int a = length.get();
>
> length = 10;
> // length.set(10);
>
> In cases where read/write access is needed, the compiler can do this:
>
> length++;
> // int temp = length.get();
> // temp++;
> // length.set(temp);
>
> This can work for any user-defined type, since we're using the same operator. If you want it done faster 'under the hood', you can use operator-overloads inside the property:
>
> property int length {
>    get() { return this.len; }
>    set(newLen) { this.len = newLen; }
>    void opIncrement() { this.len++; }
> }
>

Agreed. The current way is just sloppy and it bothers me constantly. *gripe* *gripe* *gripe*

I would make two modifications to your suggestion though:

1. Like in C#, you shouldn't need to define paramater lists for "set" and "get". They're always going to be the same. In the case of "set", it's always going to be just the one param, and it'll be the new value, so just make a special predefined var. Something like:

get { return this.len; }
set { this.len = value; } // "value" (like in C#), or "$" or something like
that

2. You shouldn't have to manually define a private var to go along with the property. In languages with real properties, the following idiom is used constantly:

private int _var;
public property int var {
   get { return _var; }
   set { _var = $; }
   void opIncrement() { _var++; }
}

Why should that be needed? It should be like this:

public property int var {
   // int internalValue; // Automatically created (but named better)
   get { return internalValue; }
   set { internalValue = $; }
   void opIncrement() { internalValue++; }
}

In the minority of cases where a property doesn't need this variable, "internalValue" can just be optimized away.


January 08, 2009
Nick Sabalausky wrote:

> 1. Like in C#, you shouldn't need to define paramater lists for "set" and "get". They're always going to be the same. In the case of "set", it's always going to be just the one param, and it'll be the new value, so just make a special predefined var. Something like:
> 
> get { return this.len; }
> set { this.len = value; } // "value" (like in C#), or "$" or something
> like that

I have to disagree. By that logic, we would abolish parameter-names altogether and access formal parameters by number. set has a parameter, and the programmer should be able to name it.

Also, removing the parentheses would be confusing. I believe it might be better to make them look like this, even:

property int length {
    auto get() { .. }
    void set(auto name) { .. }
}

So they would clearly be function declarations.

> 2. You shouldn't have to manually define a private var to go along with the property. In languages with real properties, the following idiom is used constantly:
> 
> private int _var;
> public property int var {
>    get { return _var; }
>    set { _var = $; }
>    void opIncrement() { _var++; }
> }
> 
> Why should that be needed? It should be like this:
> 
> public property int var {
>    // int internalValue; // Automatically created (but named better)
>    get { return internalValue; }
>    set { internalValue = $; }
>    void opIncrement() { internalValue++; }
> }
> 
> In the minority of cases where a property doesn't need this variable, "internalValue" can just be optimized away.

If you really want that behavior, you should just use a public variable. Even changing it to a real property later would not matter for the public interface.

-- 
Michiel

January 08, 2009
Michiel Helvensteijn wrote:
> Nick Sabalausky wrote:
> 
>> 1. Like in C#, you shouldn't need to define paramater lists for "set" and
>> "get". They're always going to be the same. In the case of "set", it's
>> always going to be just the one param, and it'll be the new value, so just
>> make a special predefined var. Something like:
>>
>> get { return this.len; }
>> set { this.len = value; } // "value" (like in C#), or "$" or something
>> like that
> 
> I have to disagree. By that logic, we would abolish parameter-names
> altogether and access formal parameters by number. set has a parameter, and
> the programmer should be able to name it.

It's very different. A setter has a very specific meaning: set some value. That's why it's called "value". Another name could be the name of the property ("len") or something like "newLen". Which other name would you use?

A general function can have any kind of meaning, and so its parameters, and that's why it's ok to have names for them.

> 
> Also, removing the parentheses would be confusing.

That's more a matter of taste. In C# I find this ok.

 I believe it might be
> better to make them look like this, even:
> 
> property int length {
>     auto get() { .. }
>     void set(auto name) { .. }

name? But it's the length. :-P
January 08, 2009
Ary Borenszweig wrote:

>>> get { return this.len; }
>>> set { this.len = value; } // "value" (like in C#), or "$" or something
>>> like that
>> 
>> I have to disagree. By that logic, we would abolish parameter-names altogether and access formal parameters by number. set has a parameter, and the programmer should be able to name it.
> 
> It's very different. A setter has a very specific meaning: set some value. That's why it's called "value". Another name could be the name of the property ("len") or something like "newLen". Which other name would you use?

It's not for me to say. It should be up to the programmer.

You've already shown that there are at least three possibilities.

-- 
Michiel

January 08, 2009
Michiel Helvensteijn wrote:
> Ary Borenszweig wrote:
> 
>>>> get { return this.len; }
>>>> set { this.len = value; } // "value" (like in C#), or "$" or something
>>>> like that
>>> I have to disagree. By that logic, we would abolish parameter-names
>>> altogether and access formal parameters by number. set has a parameter,
>>> and the programmer should be able to name it.
>> It's very different. A setter has a very specific meaning: set some
>> value. That's why it's called "value". Another name could be the name of
>> the property ("len") or something like "newLen". Which other name would
>> you use?
> 
> It's not for me to say. It should be up to the programmer.
> 
> You've already shown that there are at least three possibilities.

Yes, three. And that's it. That was my point. And they all have pretty much the same meaning.

Well, unless you want to name it "nuevaLen", "novaLen", "nouvelleLen", etc. :-P
January 08, 2009
Ary Borenszweig wrote:

>>> It's very different. A setter has a very specific meaning: set some value. That's why it's called "value". Another name could be the name of the property ("len") or something like "newLen". Which other name would you use?
>> 
>> It's not for me to say. It should be up to the programmer.
>> 
>> You've already shown that there are at least three possibilities.
> 
> Yes, three. And that's it. That was my point. And they all have pretty much the same meaning.
> 
> Well, unless you want to name it "nuevaLen", "novaLen", "nouvelleLen", etc. :-P

Perhaps the implicit declaration "value" (or whatever *you* would call it) inadvertently overshadows a member variable with that name. That could result in a bug that would be pretty hard to find.

-- 
Michiel

January 08, 2009
Michiel Helvensteijn wrote:
> Nick Sabalausky wrote:
> 
>> 2. You shouldn't have to manually define a private var to go along with the property. In languages with real properties, the following idiom is used constantly:
>>
>> private int _var;
>> public property int var {
>>    get { return _var; }
>>    set { _var = $; }
>>    void opIncrement() { _var++; }
>> }
>>
>> Why should that be needed? It should be like this:
>>
>> public property int var {
>>    // int internalValue; // Automatically created (but named better)
>>    get { return internalValue; }
>>    set { internalValue = $; }
>>    void opIncrement() { internalValue++; }
>> }
>>
>> In the minority of cases where a property doesn't need this variable, "internalValue" can just be optimized away.
> 
> If you really want that behavior, you should just use a public variable. Even changing it to a real property later would not matter for the public interface.
> 

That's not quite why it was suggested.

I actually like the idea.

It is true that a public member would be preferred in the trivial case.
In the general case though, people will have some internal value they
are working with and whenever someone works with it they want side
effects to happen.
Here's an example:

int nTimesVarRead = 0;

public property int var
{
    get
    {
        nTimesVarRead++;
        return internalValue;
    }

    set { internalValue = $; }
}

compare against:

int nTimesVarRead = 0;
int m_var; // Annoying extra declaration that is common practice.

public property int var
{
    get
    {
        nTimesVarRead++;
        return m_var;
    }

    set { m_var = $; }
}

Thus I rather like that idea.

Perhaps, since the compiler knows the name of the property, the name of the generated internal value could just be the name of the property:

public property int var
{
    get { return var; }
    set { var = $; }
}

public property int foo
{
    get { return foo; }
    set { foo = $; }
}

etc.
January 08, 2009
"Michiel Helvensteijn" <nomail@please.com> wrote in message news:gk5b4m$2ekd$1@digitalmars.com...
> Nick Sabalausky wrote:
>
>> 1. Like in C#, you shouldn't need to define paramater lists for "set" and
>> "get". They're always going to be the same. In the case of "set", it's
>> always going to be just the one param, and it'll be the new value, so
>> just
>> make a special predefined var. Something like:
>>
>> get { return this.len; }
>> set { this.len = value; } // "value" (like in C#), or "$" or something
>> like that
>
> I have to disagree. By that logic, we would abolish parameter-names altogether and access formal parameters by number.

I don't think that follows at all. Function parameters have user-definable names because functions are a general concept that, for all the syntax is aware, could have any number of params that could each represent just about anything. Property getters/setters are different: A property getter is ALWAYS going to take nothing in and return a value of the same type as the property that represents the value of the property. Otherwise it wouldn't be a property getter. A property setter is ALWAYS going to return nothing and take in exactly one argument, of the same type as the property, and that value will ALWAYS represent the intended new value. Otherwise it wouldn't be a property setter. With this information, requiring a custom user-defined name for the setter parameter becomes completely frivolous. You may as well require people to make up their own names for "void", "if", "while" and "{some array here}.length": they're always going to mean the same thing so it's much better to have it standardized.

> set has a parameter, and
> the programmer should be able to name it.
>
> Also, removing the parentheses would be confusing. I believe it might be better to make them look like this, even:
>
> property int length {
>    auto get() { .. }
>    void set(auto name) { .. }
> }
>
> So they would clearly be function declarations.
>

What benefit would that provide?

Downside:
The fact that they're part of the language-defined property getter/setter
syntax renders any explicitly-stated parameter and return-value information
completely redundant. Of course, I'm aware that sometimes redundancy can be
good since it can help catch errors, but this particular redundancy doesn't
do anything to help catch errors. In fact, it could cause confusion because
it obscures the fact that "get" and "set" are special function names within
a "property" block. (Plus it's just not as clean-looking as a C#-style "get
{} set{}")

I suppose explicitly stating the return type and parameter lists could open the door for "multitype" properties that could "get" or "set" different types without relying on the caller to cast/convert. I'm not sure how I feel about that though...it might be nice...

>> 2. You shouldn't have to manually define a private var to go along with the property. In languages with real properties, the following idiom is used constantly:
>>
>> private int _var;
>> public property int var {
>>    get { return _var; }
>>    set { _var = $; }
>>    void opIncrement() { _var++; }
>> }
>>
>> Why should that be needed? It should be like this:
>>
>> public property int var {
>>    // int internalValue; // Automatically created (but named better)
>>    get { return internalValue; }
>>    set { internalValue = $; }
>>    void opIncrement() { internalValue++; }
>> }
>>
>> In the minority of cases where a property doesn't need this variable, "internalValue" can just be optimized away.
>
> If you really want that behavior, you should just use a public variable. Even changing it to a real property later would not matter for the public interface.
>

The bodies of those get's and set's were just trivial examples. I agree an actual property like that would be pointless. But a typical use-case for properties is to intercept accesses to a member variable and perform some sort of action on each access (validation, logging, updating a related value, etc). In other words, you still frequently need the "private int _x; property int x {}" idiom. In my experience, these sorts of things are the most common uses for properties, and even if they weren't it would be simple enough to optimize away the implied private var whenever it's not needed, so the feature would never cause any trouble, it would just help in many cases (plus provide a standardized name).