On Mon, 8 Nov 2010 17:08:32 -0800
Jonathan M Davis <[email protected]> wrote:
> As Jesse says, they _are_ passed by reference. The struct itself _is_ the
> reference.
(Well, that is a sensible redefinition of "reference"; but it is simply _not_
what the word means in any other context.)
It is true that the inner, hidden, memory area (static array) containing the
elements is indeed referenced, actually "pointed", from the dynamic array
struct:
struct ValueArray(Element) {
Element* elements;
uint length;
}
(Well, actually, this may not be a struct, but it's easier to imagine it so.)
But: the dyn array itself, meaning the struct, is not referenced: "a2 = a1"
copies it, as well as parameter passing. And the fact that the internal memory
is referenced is an implementation detail that should *not* affect semantics.
The inner pointer is there because we need some kind of indirection to
implement variable-size thingies, and the means for this is pointers.
This is precisely where & why people get bitten: implementation leaks out into
semantics.
Actually, one could conceptually replace the (pointer,length) pair by a single
field of type MemoryArea -- which would be a plain value. Then, there would be
no more (visible) pointer in the dyn array, right? (Actually, it would just be
hidden deeper inside the MemoryArea field... but that is again implementation
detail!)
We should not mess up pointers used for implementation mechanics, like in the
case of dyn arrays, or more generally variable size data structure, with
pointers used as true references carrying semantics, like in the case of the
difference between struct and class.
And precisely, replacing array struct by a class, or explicitely referencing
the struct, would make a *reference* dyn array type. See below an example of a
primitive sort of such an array type (you can only put new elements in it ;-),
implemented as class.
After "a2 = a1", every change to one of the vars affects the other var; whether
the change requires reallocation is irrelevant; this detail belongs to
implementation, not to semantics.
Now, replace class with struct and you have a type for *value* dyn arrays.
Which works exactly like D ones.
The assertion will fail; and output should be interesting ;-)
Hope it's clear, because I cannot do better.
I do not mean that D arrays are bad in any way. They work perfectly and are
very efficient. Enforcing a true interface between implementation and semantics
would certainly have a relevant cost in terms of space & time. But please, stop
stating D arrays are referenced if you want newcomers to have a chance &
understand the actual behaviour, to use them without beeing constantly bitten,
and to stop & complain.
Denis
class RefArray(Element) {
Element* elements;
uint length;
private uint capacity;
this () {
this.elements = cast(Element*) malloc(Element.sizeof);
this.capacity = 1;
this.length = 0;
}
void reAlloc() {
writeln("realloc");
this.capacity *= 2;
size_t memSize = this.capacity * Element.sizeof;
realloc(this.elements, memSize);
}
void put(Element element) {
if (this.length >= this.capacity)
this.reAlloc();
this.elements[this.length] = element;
++ this.length;
}
void opBinary(string op) (Element element)
if (op == "+") {
this.put(element);
}
}
void main () {
auto a1 = new RefArray!int();
auto a2 = a1;
foreach (int i ; 1..8) {a2.put(i);}
assert(a1.length == a2.length);
foreach (int i ; 0 .. a2.length)
writef("%s=%s ", a1.elements[i], a2.elements[i]);
writeln();
a1 + 8; a1 + 9;
foreach (int i ; 0 .. a2.length)
writef("%s=%s ", a1.elements[i], a2.elements[i]);
writeln();
}
-- -- -- -- -- -- --
vit esse estrany ☣
spir.wikidot.com