I doubt it would have helped very much with respect to those responses which are bordering(?) on abusive
(You know the ones that go like: "You're such a dickhead!", which is meant by imputation to be understood as "I'm so smart.", which when given this exposition of what is really being said, I merely ask "Who is the dickhead?" Besides, aren't we supposed to be nice?)
if I had entitled the email slightly more correctly as:
"Why Does Hash Apparently Reorder By Its Internal Representation And Other Associated Ponderings"
That little "By" is important! As the ensuing discussion illustrates, the internal representation could be augmented in such a way so as to allow for it. Gee whiz, even Matz weighed in! Still, there was nowhere given an explicit statement as to the necessity of hashes being ordered, and to claim as much would require that what was written about internal representatons and optimisations (a crap reference to the hash table) be ignored. Even so, my understanding of hashes, well, it isn't very good, not unlike many of my skills; although I have written a few hashing functions some time ago.
Nevertheless, it would appear as if this is something which has been brought up before and appears to have sufficient value to be raised again. I assumed as much. And if it weren't so, then there wouldn't be what I and others appear also to have found to be useful discussion. Furthermore, not everyone has been on the list since the Nineties.
And while I do know how to search the mailing list, I went on to ask about whether it was at all useful to have ordered hashes in spite of lack of explicit support in Ruby. I wasn't asking for support for it, just as to whether I was wanting for something that I might write myself which might be useful and not ugly, or evil as I put it.
I do want it for something. Even so, after having read the differing opinions I don't know whether it should be there in Ruby by default or not. I think a subclass of OrderedHash would be a good compromise. (I'm yet take a look at the supplied code. Thanks for that, I will do...)
What I wanted it for was for honoring the order in which properties/attributes are attached at runtime to an object. I want to access properties by both order and key.
To that end I've subsequently written almost 200 additional lines of code to the following which supports the following:
module Enumerable
def all_but_first
d = self.dup
d.first!
d
end
def all_but_last
d = self.dup
d.last!
d
end
def each_but_first
all_but_first.each do |e|
yield e
end
end
def each_but_last
all_but_last.each do |e|
yield e
end
end
end
I liked the idea of having these as methods of Enumerable. Getting this to work for Array was trivial. Hashes were a nightmare and occupied about 80-90% of the additional stuff as it would appear to be consistent with others' experiences. Here's a snippet of that almost 200 lines to give you an idea of the complexity of it:
class Array
...
def sort_by_element_invariant(i)
self.sort {|x, y| by_element_invariant(x, y, i)}
end
def by_element_invariant(x, y, i)
if x.is_a?(Array) || y.is_a?(Array) && !(x.is_a?(Hash) || y.is_a?(Hash))
by_array_invariant(x, y, i)
elsif x.is_a?(Hash) || y.is_a?(Hash) && !(x.is_a?(Array) || y.is_a?(Array))
by_hash_invariant(x, y, i)
elsif (x.is_a?(Array) && y.is_a?(Hash)) || (x.is_a?(Hash) && y.is_a?(Array))
by_array_and_hash_invariant(x, y, i)
else
x.to_s <=> y.to_s
end
end
alias_method :sort_by, :sort_by_element_invariant
alias_method :sort_by_element, :sort_by_element_invariant
def by_array_invariant(x, y, i)
if x.is_a?(Array) && is_a?(Array)
x[i].to_s <=> y[i].to_s
elsif x.is_a?(Array)
x[i].to_s <=> y.to_s
else y.is_a?(Array)
x.to_s <=> y[i].to_s
end
end
...
end
The above code was part of what was required to get an aribitrary array to sort, which was in turn used by the extensions to the Hash class. Admittedly as much as a half of the code was written for symmetry and completeness and was not necessarily required for my immediate needs.
The code however will do the following, which I believe to be imperfect as to the consistency of its sorting as yet:
a = [[:b, 2], [:c, 4], :a, 45, "d", ["f"], [2], [:z, 1, 2, 3], {"s"=>"s"}, {:t=>"t"}, {}, {"v"=>"v", "u"=>"u"}]
=> [[:b, 2], [:c, 4], :a, 45, "d", ["f"], [2], [:z, 1, 2, 3], {"s"=>"s"}, {:t=>"t"}, {}, {"v"=>"v", "u"=>"u"}]
a.sort_by_element(0)
=> [{}, {"v"=>"v", "u"=>"u"}, [2], 45, :a, [:b, 2], [:c, 4], "d", {:t=>"t"}, ["f"], {"s"=>"s"}, [:z, 1, 2, 3]]
a.to_h
=> {:z=>[1, 2, 3], 0=>{}, 1=>{"v"=>"v", "u"=>"u"}, 7=>"d", :b=>2, 2=>[2], 8=>{:t=>"t"}, :c=>4, 3=>45, 9=>["f"], 4=>:a, 10=>{"s"=>"s"}}
a.to_h.sort_by_key
=> [[0, {}], [1, {"v"=>"v", "u"=>"u"}], [10, {"s"=>"s"}], [2, [2]], [3, 45], [4, :a], [7, "d"], [8, {:t=>"t"}], [9, ["f"]], [:b, 2], [:c, 4], [:z, [1, 2, 3]]]
a.as_h
=> {{"s"=>"s"}=>{:t=>"t"}, "d"=>["f"], [2]=>[:z, 1, 2, 3], {}=>{"v"=>"v", "u"=>"u"}, :a=>45, [:b, 2]=>[:c, 4]}
a.as_h.sort_by_key
=> [[{}, {"v"=>"v", "u"=>"u"}], [[2], [:z, 1, 2, 3]], [:a, 45], [[:b, 2], [:c, 4]], ["d", ["f"]], [{"s"=>"s"}, {:t=>"t"}]]
Yeah, it needs some tweaking!... It works fine for all but the most bizarre sets of objects.
And thanks to the discussion of that 55 lines of code I may implement something of the sort (pun only intended later) which implements an array to do ordering support as I go, rather than, or in addition to subsequent ordering by sorting.
Finally, to those who would take aim, I say "Piss off!', I'm quite capable of such of myself with respect to myself. Such attitudes will have a chiling effect on those who might be able to contribute given the opportunity and I refuse to cower to arrogance such as yours. Stupid and annoying people are best ignored. I'm happy to be ignored until I say something useful. Which means I myself should've written nothing of it, but anyway... Is it a deal?
Meanwhile, "I'm off to grow some hair on my tongue.", he says in an unconvincing attempt at a gruff voice...