array.length++ not an lvalue

Nick Sabalausky a at a.a
Wed Jun 18 13:46:51 PDT 2008


"Mike" <vertex at gmx.at> wrote in message 
news:g3bcub$11dk$1 at digitalmars.com...
> This could work if we had real properties. I'd really like to see an 
> extended/modified version of the C# property syntax in D:
>
> private int _length;
> public property int length
> {
>    opSet() { return _length = value; }
>    opGet() { return value; }
>    opPostIncrement() { _length++; }
>    // ...
> }
>
> That would solve the problem.
>
> -Mike
>

"Mike" <vertex at gmx.at> wrote in message 
news:g3bcub$11dk$1 at digitalmars.com...
> This could work if we had real properties. I'd really like to see an 
> extended/modified

version of the C# property syntax in D:
>
> private int _length;
> public property int length
> {
>    opSet() { return _length = value; }
>    opGet() { return value; }
>    opPostIncrement() { _length++; }
>    // ...
> }
>
> That would solve the problem.
>
> -Mike
>

That's just what I was going to post. The way this currently works is 
insanely inconsistent:

--------

1. D doesn't have accessors (to borrow C# terminology), and yet 
'array'.length *is* separate getter/setter functions called using member 
variable syntax, which of course is the very definition of an accessor. So 
what, D has accessors, but doesn't let you create any? (I like accessors 
BTW, because I'm of the mind that "member variable" vs "member function" is 
often an implementation detail and therefore should be hidable just like any 
other implementation detail.)

--------

2. The statement/expression "x++" is considered to be shorthand for:

yield x; // C#-inspired psuedo-code
// Execute the rest of the statement or expression
x = x + 1;

So, *even if* "x = a.length" and "a.length = x" are turned into "x = 
a.length()" and "a.length(x)" by the compiler, then logically, "a.length++" 
should *first* turn into:

yield a.length;
// Execute the rest of the statement or expression
a.length = a.length + 1;

Which then turns into:
yield a.length();
// Execute the rest of the statement or expression
a.length(a.length() + 1);

Since this substitution isn't happening, that means that "x++" is only 
*sometimes* equivilent to the "yield x, execute the rest, x = x + 1" 
sequence that "x++" is normally considered to be. So, the definition goes 
"'x++' means ... unless x is something like 'array'.length". Inconsistency.

So I don't see the problem here, unless there's some reason why the compiler 
*has* to proccess the "'array'.length" part *before* the 
"'PostfixExpression'++" part.

> It was to prevent:
> array [array.length ++] = 45;
> Which is dependent on undefined behaviou

If I'm understanding postfix right, then:

array[array.length++] = 45;

Becomes =>

array[array.length] = 45;
array.length++;

The first line, of course, is an index-out-of-bounds error. So where's the 
undefined behavior? Is the index-out-of-bounds error the undefined behavior 
part? But then what makes this scenario any more special than any other 
index-out-of-bounds error?

Is "++a.length" allowed? I assume not, and if that's the case, then that 
simplifies the argument somewhat:

++a.length;

Becomes =>

a.length = a.length + 1;
yield a.length;

Becomes =>

a.length(a.length() + 1);
yield a.length();

And:

array[++array.length] = 45;

Becomes =>

array.length = array.length + 1;
array[array.length] = 45;

Becomes =>

array.length(array.length() + 1);
array[array.length()] = 45; // Index Out-of-Bounds

--------

3. Regarding the following:

> Walter thought that
> array.length++;
> hid too much complexity.  That statement can cause:
> * realloc
> * malloc/memcpy (if realloc has to move the array)
> * GC run (if malloc doesn't have space)

If that's the case, then that means he's against the concept of accessors. 
While I don't agree with it, I can certainly understand it. BUT, 
"array.length = array.length + 1" hides the exact same complexity, and 
overloaded operators can also hide that sort of complexity. 
So...inconsistent reasoning.

If the problem with the hidden complexity in "array.length++;" is that a 
useless temporary copy of the array might be made, then well, part of my 
above argument still applies, so combine that with all the usual ins and 
outs of "postfix" vs. "prefix".

--------

So if the ability to create accessors was both 1. considered a good thing 
and 2. implemented, then all that stuff would solve itself. Accessors 
wouldn't be a "kinda/sorta exists" thing as they are now. The fact that 
"array.length = array.length + 1" hides complexity wouldn't matter because, 
hey, so can any other accessor. The statement/expression "a.length++" could 
get turned into the appropriate function calls, just as in any other 
language that supports accessors. And, of course, things *other* than 
built-in properties like "'array'.length" would be able to hide the 
implementation detail of "is ColorChangingHighGlossPaint.Color implemented 
as a member variable, or as get/set member functions?".

"But accessors can hide the fact that an operation is resource-intensive or 
computationally expensive."

So can overloaded operators, but as far as I can tell we all seem to be ok 
with those being allowed in D.





More information about the Digitalmars-d mailing list