> Markus wrote:
> 
> My guess is that either++ 1) you will find in answering these questions
> that you are really wanting a simple combination of two standard
> collections, or 2) you will get tangled in trying to come up with
> something consistent, or 3) I will learn something interesting.
>  
> 
> Hal wrote:
>
> I fear 1 or 2, but I hope for 3. ;)

Here's a stab at an instance of case #1, the simplest way I could come
up with to model the semantics I think you are looking for (note: this
is _not_ claimed to be the best way to implement the semantics, just the
clearest way to express them):

class An_ordered_hash
    include Enumerable
    #
    # A pair of hashes, indicating for each key both the value paired
    #    with it and the order in which it was added. 
    #
    def initialize
        @ordered = {}
        @hash = {}
        @stamp = 0
        end
    def []=(k,v)
        @ordered[k] = @stamp += 1
        @hash[k] = v
        end
    #
    # Iterators proceed in order-of-insertion
    #
    def keys_in_insertion_order
        keys.sort_by { |k| @ordered[k] }
        end
    def each(*args,&block)
        keys_in_insertion_order.each { |k| block.call(k,@hash[k]) }
        end
    alias each_pair each
    def each_key(*args,&block)
        keys_in_insertion_order.each { |k| block.call(k) }
        end
    def each_value(*args,&block)
        keys_in_insertion_order.each { |k| block.call(@hash[k]) }
        end
    def collect(*args,&block)
        keys_in_insertion_order.collect { |k| block.call(k,@hash[k]) }
        end
    #
    # Pass anything we don't understand through to the hash
    #
    def method_missing(method,*args,&block)
        @ordered.send method,*args, &block
        @hash.send method,*args, &block
        end
    #
    # A few extensions suggested by the array-like nature of the class
    #
    def <<(kv_pairs)
        kv_pairs.each_pair { |k,v| self[k] = v }
        self
        end
    def +(kv_pairs)
        An_ordered_hash.new << self << kv_pairs
        end
    def |(kv_pairs)
        self+kv_pairs
        end
    def &(kv_pairs)
        result = self+{}
        each { |k,v| result.delete(k) unless result[k] == kv_pairs[k] }
        result
        end
    end


Since we don't have the syntactic sugar we'd like, I put together
something that at least preserves the meaning & intent of it:

class An_ordered_hash
    def to_s
        "_(" +collect { |k,v| "#{k}=>#{v}" }.join(')+_(')+')'
        end
    def to_str
        to_s
        end
    def inspect
        to_s
        end
    end

def _(kv_pairs)
    An_ordered_hash.new + kv_pairs
    end
    

This setup gives the following answers to the questions I'd asked
previously (properly translated of course):

p _(1=>2)+_(3=>4)            # _(1=>2)+_(3=>4)

p _(1=>2)+_(3=>4)+_(1=>5)    # _(3=>4)+_(1=>5)

x = _(1=>2)+_(3=>4)+_(1=>5)
p x[1]                       # 5

x = _(1=>2) << _(3=>4)
x[3] = 6
p x                          # _(1=>2)+_(3=>6)

x = _(1=>2) << _(3=>4)
x[3],x[1] = x[1],x[3]
p x                          # _(3=>2)+_(1=>4)

x = _(1=>2) << _(3=>4)
x << _(7=>8)
p x                          # _(1=>2)+_(3=>4)+_(7=>8)

x = _(1=>2) << _(3=>4)
x += _(7=>8)
p x                          # _(1=>2)+_(3=>4)+_(7=>8)

x = _(1=>2) << _(3=>4)
x << _(1=>8)
p x                          # _(3=>4)+_(1=>8)

x = _(1=>2) << _(3=>4)
x += _(1=>8)
p x                          # _(3=>4)+_(1=>8)

x = _(1=>2) << _(3=>4)
x << _(7=>8)
p x                          # _(1=>2)+_(3=>4)+_(7=>8)

x = _(1=>2) << _(3=>4)
x |= _(7=>8) << _(3=> 9)
p x                          # _(1=>2)+_(7=>8)+_(3=>9)

x = _(1=>2) << _(3=>4)
x &= _(1=>2) << _(3=>9) << _(6=>7)
p x                          # _(1=>2)

x = _(1=>2) << _(3=>4)
x << _(7=>8)
p x                          # _(1=>2)+_(3=>4)+_(7=>8)

x = _(1=>2) << _(3=>4)
x[1] = 3
p x                          # _(3=>4)+_(1=>3)

x = _(1=>2) << _(3=>4)
x[1] += 1
p x                          # _(3=>4)+_(1=>3)

x = _(1=>'2') << _(3=>'4')
x[1].sub!(/2/,'3')
p x                          # _(1=>3)+_(3=>4)

x = _(1=>2) << _(3=>4)
x[1] += 1
p x                          # _(3=>4)+_(1=>3)

x = _(1=>2) << _(3=>4)
x[3] = 6
x[1] = 7
p x                          # _(3=>6)+_(1=>7)

x = _(1=>2) << _(3=>4)
p x.delete(1)                # 2
x[3] = 6
x[1] = 7
p x                          # _(3=>6)+_(1=>7)

x = _(1=>2) << _(3=>4) << _(1=>5)
p x.delete(1)                # 5
x[3] = 6
x[1] = 7
p x                          # _(3=>6)+_(1=>7)


Does this agree with your intuition/desires?  Or am I still at sea?

    -- MarkusQ