On Wednesday, 21 October 2015 at 16:36:46 UTC, Brad Anderson
wrote:
On Wednesday, 21 October 2015 at 11:05:12 UTC, Andrei
Alexandrescu wrote:
[snip]
2. Reference containers.
These have classic reference semantics (à la Java).
Internally, they may be implemented either as class objects or
as reference counted structs.
They're by default mutable. Qualifiers should apply to them
gracefully.
3. Eager value containers.
These are STL-style. Somewhat surprisingly I think these are
the worst of the pack; they expensively duplicate at the drop
of a hat and need to be carefully passed around by reference
lest performance silently drops. Nevertheless, when used as
members inside other data structures value semantics might be
the appropriate choice. Also, thinking of them as values often
makes code simpler.
By default eager value containers are mutable. They should
support immutable and const meaningfully.
Having both reference and value semantics for containers would
be great. I don't understand why reference semantics would be
implemented by the container themselves though. Why not a
general purpose RC! (or RefCounted! if the current design is
deemed sufficient) that can apply to anything, including
containers? Then you'd only need to implement the value
semantic containers (and maybe throw in some RC version aliases
to promote the use of the RC versions so the option isn't
overlooked). It seems kind of crazy that anything in D that
wants to be reference counted would need to implement the logic
themselves.
If there are performance advantages (I haven't thought of any
but perhaps there are) to bake the RC right into the container
it might also be possible to use DbI take advantage of it in
RC! when appropriate.
It just seems so wrong to implement reference counting dozens
of times independently, especially when that means implementing
all the containers twice too.
If we had value type containers and reference type containers, I
would assume that they would at least share implementation, and
maybe the reference types would just be wrappers around the value
types. However, I completely fail to understand why you'd ever
want a container that was a value type. In my experience, it's
very error-prone and adds no value. It just makes it too easy to
accidentally copy a container, and it can be pretty easy to have
an iterator, range, etc. referring to a container that's already
been destroyed (similar to having a dynamic array referring to a
static array that's left scope). As long as the containers have a
dup method (or whatever we call it) so that they can be copied
when you do want to copy them, I would think that that was more
than enough. What do you get with a value type container that you
consider better than a reference type? It's not like it lives on
the stack as a value type. Most of the container's guts are on
the heap regardless.
- Jonathan M Davis