On Fri, 21 May 2010 13:42:14 -0400, Andrei Alexandrescu
<seewebsiteforem...@erdani.org> wrote:
On 05/19/2010 08:42 PM, Steven Schveighoffer wrote:
Andrei Alexandrescu Wrote:
I.e. there aren't many
kinds of HashMaps that derive from each other. But the interfaces
are not detrimental to your ideas. The only thing interfaces require
is that the entities implementing them are classes and not structs.
As long as you agree that classes are the right call, then interfaces
can co-exist with your other suggestions without interference.
This brings back a discussion I had with Walter a while ago, with echoes
in the newsgroup. Basically the conclusion was as follows: if a
container never escapes the addresses of its elements, it can manage its
own storage. That forces, however, the container to be a struct because
copying references to a class container would break that encapsulation.
I called those "perfectly encapsulated containers" and I think they are
good candidates for manual memory management because they tend to deal
in relatively large chunks.
I noticed that your collections return things by value, so they are good
candidates for perfect encapsulation.
Then you need reference counting, I don't think that is a good design.
Yes, if you want to define "this function needs something that is
both addable and purgeable, I don't have an interface for that. But
a concept can certainly define that generically (which is what you
want anyways), or you could just say "I need a List" and get those
functions also. It also does not force entities other than
dcollections objects to be classes, they could be structs and
implement the correct concepts.
I myself don't really use the interface aspect of the classes, it is
mostly a carryover from the Java/Tango inspirations.
I don't know Tango, but Java's containers are a terrible example to
follow. Java's container library is a ill-advised design on top of an
underpowered language, patched later with some half-understood seeming
of genericity. I think Java containers are a huge disservice to the
programming community because they foster bad design.
Java has some warts as you have rightfully pointed out in the past (i.e.
O(n) lookup), but I have attempted to remove all those warts.
Dcollections I would hope does not suffer from the problems that Java's
collections suffer from.
But I can see
one good reason to keep them -- binary interoperability. For
example, it might be the case some day when D has good support with
dynamic libraries that a library exposes some piece of itself as a
Map or List interface.
I need to disagree with that. I've done and I do a ton of binary
interoperability stuff. You never expose a generic container interface!
Interoperable objects always embody high-level logic that is specific to
the application. They might use containers inside, but they invariably
expose high-level, application-specific functionality.
It's done all the time in Java and .NET. For example, A GUI listbox
widget exposes its elements as an array of elements, which implement the
List interface. You don't ever see the implementation or need it.
Granted Java and .NET have less problems than C++ and D with binary
compatibility, since the function tables are dynamic, but the potential is
there for D to make binary compatibility possible with interfaces.
In the past I have built a C++ library that abstracted features of the
OS. My goal was to make it possible to dynamically load a module that
abstracted things like setting the IP address of a network interface. My
modules used std::string instead of char * to lookup services to get
objects that implement the interface. Big mistake. On a later version of
the standard C++ runtime, the private implementation of std::string
changed, so the dynamically loaded libraries crashed horribly. No change
in string's interface, just the private stuff changed, but because it's a
template, the code that uses it necessarily has to be aware of it. We
ended up ditching the standard C++ library's version of string, and used
STLPort so we could control the library.
I envision this same sort of problem would be likely with D collection
objects that were not used via interfaces.
So my answer is -- go ahead and define these concepts and required
names, and you can ignore the interfaces if they don't interest you.
They do not subtract from the possibilities, and others may find good
use for them.
Does that make sense?
I understand I could ignore the interfaces and call it a day, but it
seems that at this point we are both convinced they are not quite good
at anything: you only put them in because you suffered the Stockholm
syndrome with Java, and I hate them with a passion.
The reason I put them in is because they existed before, but thinking
about what they would be useful for, D doesn't really support dynamic
libraries all that well (recent advances have brought that closer). But
once it does, I think it will be much more important to keep compiled
libraries compatible between versions of the standard library. This is
typically not possible with templates, I know C++ is horrible at it from
personal experience.
So I'm not convinced it is not quite good at anything. I think it's a
solution to a problem that doesn't exist yet on D because D's linking
features are stuck in 1995.
Why would we keep in the standard library bad design with the advice
that "if you don't like it ignore it"?
People have continuously used that argument against const and immutable.
Really that argument is fine, as long as you don't consider it bad design,
which I don't :)
-Steve