I am coming late into this discussion, some comments:
I like a duck typing approach whenever possible, and don't need runtime
adaptability (which seems to be in line with others)
different container have different trade offs, and switching between
them should be a design choice
Generic algorithm in my opinion are useful to easily (and with little
well tested code) give a wise range interface to several containers.
They should not "forbid" special implementation of some algorithms in a
To have a common interface one can always use a trampoline function,
that looks for the specialized implementation in various places.
I know that in theory one should be able to write specialized templates
instead, but in practice I have often encountered bugs and strange
behavior, in container implementation seems much cleaner to me
Different containers have different "threadsafeness". Normally some
subset of operations is threadsafe, but mixing in other might break it.
This in my opinion *must* be documented, for example one should not
have to look to the source to know if addition of an element to an AA
breaks a foreach loop or not.
Threadsafeness has a cost, in general non threadsafe structures are
faster, so it makes sense to have them (especially thinking that often
even in the non threadsafe structures one can use a subset of
operations concurrently without problems.
There is a large class of structures that *are* threadsafe, these have
some beautiful properties, and are very useful to know. A very good
review of them (I don't say introduction because the book is quite
advanced) is "Purely Functional Data Structures" by Chris Okasaki. In
these structures the values read are always the same, but lazy
evaluation might be used to transform amortized cost in non amortized
I had already spoken about these back during the const discussion,
because I would have liked that these structures were "immutable" and
usable by pure functions, which meant a slighlty different thing from
immutable. Some casting might be used to implement them, if one assumes
that casting a mutable structure to immutable and modifying it later is
doable (no compiler optimization on immutable disallow it, this could
be done even just for a special "thunk" that contain a lazy function
that will produce the value). Anyway that is another discussion.
For the current discussion the important thing is that yes, there are
fully threadsafe structures, and it would be useful to have them, but
in general they have a slightly larger cost.
Not safe structures are also useful as they are faster, in general in
the documentation one expects to find which operations are safe and
The minima baseline typically is that just reading is threadsafe,
modifications in general aren't and might invalidate all pointers to
Exceptions to this should be clearly stated, for example appending to
an array can be made threadsafe without a large cost, whereas insertion
(if the update of an element is not atomic) cannot.
If D really wants to go after multithreading it makes sense to offer as
many safe structures as possible, and in any case clearly document the
non threadsafeness of the others.
it might make sense to give "safe" interfaces (I would say basically
just reading without updates), but one cannot expect to really express
all threadsafeness of a container though interfaces, because that would
be too complicated and then one would end up with one container per
interface without much gain.