I just watched a thought-provoking talk by Andrei Alexandrescu at DConf15. It highlights a shortcoming of Java interfaces aka Rust traits aka C++ concepts: You have to name everything. Having a name for everything is nice, but it becomes a problem if you have to deal with combinations, because it blows up exponentially. Alexandrescu proposes "Design by Introspection" instead.
The general idea of interfaces (traits, concepts) is to give a name to a set of features. For example, Iterator, Cloneable, Comparable, or Serializable.
What should we do, if we want something like a cloneable iterator? In Java, you have to create a "sub-interface". Maybe "CloneableIterator"? Now what about a comparable iterator? A comparable clonable iterator? The number of combinations explodes very fast. Well, dynamically typed languages like Python do not have such a problems. Python promotes duck typing.
When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck.
Alexandrescu proposes something similar, but relies on compile-time mechanisms. He discovered this technique while writing modular generic memory allocators. Allocators can be distinguished by lots of properties. Trying to give a name to all possible combinations is not feasible. Instead, he uses static if to check for properties and act accordingly without using names.
It also applies to containers. Here are a few properties of containers/collections (list, array, queue, map, set, ...):
- Random (indexed) access?
- Add to front/back?
- Pop from front/back?
- Iterate forwards/backwards/bidirectional?
- Has a length?
- Is bounded?
- Thread-safe?
- Infinite?
How do you write generic operations for all of these? In practice, you don't. You do not sort a queue.
Can we conclude that interfaces/concepts/traits are broken? We know the work for a lot of cases. It seems D with its static-if can do better, but there downsides. Having names for everything gives much better (shorter) error messages, for example. It will be interesting to look back at this in 10 years.
I know a lot of the programming community is sold on exclusive constraints (C++ concepts, Rust traits) rather than inclusive ones (D constraints). What I don't see is a lot of experience actually using them long term. They may not turn out so well. –Walter Bright