Robert Klemme
10/20/2004 2:33:00 PM
"Matt Maycock" <ummaycoc@gmail.com> schrieb im Newsbeitrag
news:e86cebfb04102007046b2c189c@mail.gmail.com...
> So, unless you count merge! and update, there doesn't seem to be a way
> to shove stuff into a hash and get the resulting updated hash back.
> Now, I know merge and update make it real easy:
>
> h = {}
> h.update(:a => :b).update(:c => :d).update(:e => :f)
>
> but this some how feels unnatural to me. maybe the following is
> better for me and others?
>
> ---code---
> require 'ext/singleton_class'
>
> class Hash
> def <<(k)
> if @shift_value.nil? then
> @shift_value = Object.new.singleton_def(:key) {k}
> else
> key, @shift_value = @shift_value.key, nil
> self[key] = k
> end
> self
> end
> end
> ---end code---
>
> ---usage---
> h = {}
> h << :language << :ruby << :creator << :matz << :users <<
:"comp.lang.ruby"
> p h
> ---result---
> {:language=>:ruby, :creator=>:matz, :users=>:"comp.lang.ruby"}
> -------------
>
> Just a question of flavour, really.
I don't like this solution because you have to store state in the Hash
that is solely connected to the appending. That's bad because this state
solely belongs to the operation, not to the Hash. This will have
surprising effects:
h = {}
h << :key1 << :val1 << :key2 # forgot :val2
# many lines later
h << :key3 << :val3
Also, as James wrote already, you can use update with multiple pairs.
If you want to have << then I'd do any of the following:
Opt 1:
class Hash
def <<(pair)
self[ pair[0] ]= pair[1]
self
end
end
h = {}
h << [:key, :val] << [:key2, :val2]
Opt 2.
class HashAdder < Struct.new(:hash, :key)
def <<(val)
self.hash[ self.key ] = val
self.hash
end
end
class Hash
def <<(key) HashAdder.new( self, key ) end
end
h = {}
h << :key << :val << :key2 << :val2
Opt 3:
Like opt 2 but reuse a single HashAdder instance toggling between key and
value much like you suggested in your post.
However, these options are far worse than simply using Hash.update(:key1
=> :val1, :key2 => :val2).
Regards
robert