I think Ruby added this recently. I'm not using it yet. A crappy hack can just dump the next/prev key into the value, plus a pointer to the first, and drop them all in a hash. It's not really pretty, but would give you ordering if you want it. Another hack is to store just the keys in a sorted list and keep the values in the hash (but this is equally inelegant to the list+hash hack and it has the same maintenance overhead).
I think most of the ordered-hashes are implemented with something like list pointers between the hash keys, but then again I haven't looked too closely under that kimono.
Edit: trees are also a good compromise.
But it can be uncommon to require this, usually for two reasons. One, the data set may be huge. And two, much of your code may not even "care" if the data is sorted. In either of those cases, if automatic sorting occurs, a lot of compute time may be wasted for no net benefit. (A solution is to have data sorted "on demand" within the code that actually cares about sort order.)
But it's hard to say without better examples, and there are times when you do want order and lookup. Can you give a couple situations where you want ordered dictionaries?
I guess you could use two data structures, with one of them being an ordered dictionary. But then the ordered dictionary doesn't actually have to support lookup; you could just use a heap.
The major reason I care about it is that when loading data from yaml files the key order doesn't get messed up. In ruby 1.8 the order got messed up.
So yeah.. use ruby 1.9 :)
Modern scripting languages have several data structures: mostly arrays, hashes and strings. But it is a hassle move data between them.
The next language should only have one, the ordered dictionary.
x = [], x << "hi" # 1=>"hi", x["seven"]=6 # 1=>"hi", "seven"=>6,
Etc
So, here I am designing the Next Big Language. And I'll take your suggestion.
Now, first issue: if I say x = "dog", then the value of x is really
1 => 'd', 2 => 'o', 3 => 'g'
Right? And despite the fact that this is an O.D., it should print in a string-like way: dog. Now suppose I do
x['z'] = (1 => 2, 2 => 3)
Now x is
1 => 'd', 2 => 'o', 3 => 'g', 'z' => (1 => 2, 2 => 3)
How should it print now?
Next issue: If I do y[1] = 'a' and y[3] = 'b', and then y << 'c', what is the value of y?
Final issue: Do the above questions really matter?
One could argue in the first case that if I want something to print nicely, then I will probably keep it in a "reasonable" form, and not mix data types in odd ways. So it really doesn't matter much how the O.D. I came up with prints.
Similarly, in the second case, if I want a collection to work well as a stack or queue, then I am probably not going to use the bracket operator to do strange things with it. So it doesn't matter which of the multiple reasonable options for the behavior of << is chosen.
Or maybe it does matter?
I would assume that strings and "ordinary" O.D. would differ in their object type: each would inherit from an abstract O.D. and each would have a different print/display function (you could have a "hidden" variable specifying this function if you wished to keep in all concrete).
If I do y[1] = 'a' and y[3] = 'b', and then y << 'c', what is the value of y?
probably y = { 1=>'a', 3=>'b', 4=>'c'}, though like any good OO/metaprogramming language, "<<" would be an overidable function.
"Do the above questions really matter?"
I am arguing for the next language and by that token, I haven't answered all the questions this raises. I think old languages like lisp and new languages like Ruby prove that new languages can unleash new possibilities, even more than fifty years after the original computer languages were created.
Thanks for your detailed reply, seriously...
Javascript has eliminated many differences between arrays and hashes (objects) but this leads to many bugs. For example, you have a third-party library that adds a .toString function on every object. But you also have code that iterates over the keys in an array, and now that iteration code hits a "toString" key instead of just the array indices you expect. Admittedly you could blame this on the object-hash identification rather than the array-hash identification....
Of course, I don't claim to have put all this is into the codified form it needs in order to form the basis of a language. I'll do that if and when I ever create a new language.