FAQ? Hash concatenation

M

Mark J. Reed

I've read matz's explanation for the lack of a concatenation operator for
Hashes in Ruby, but I was wondering if there were a module that supplied one
anyway. Or at least a self-modifying method that works like update() but
without clobbering existing values.

It's easy enough to write my own, but if there's one in the standard library or
on RAA module I'd rather use that.

Thanks for any help.
 
G

Gene Tani

myhash['keyval'] ||= newval ## won't stomp on existing value if
'keyval' already in my #keys

also, Hash#merge and Hash#merge! take blocks to say how to handle
duplicated key values
 
D

Daniel Brockman

Hi Mark,
I was wondering if there were a module that supplied [...]
a self-modifying method that works like update() but
without clobbering existing values.

Here's what I use, FWIW:

def compensate(defaults)
defaults.merge self
end

def compensate!(defaults)
for key, value in defaults do
self[key] = value unless include? key
end
end

I mostly use these methods to provide defaults for options
that are passed in a hash.
 
W

William James

Mark said:
I've read matz's explanation for the lack of a concatenation operator for
Hashes in Ruby, but I was wondering if there were a module that supplied one
anyway. Or at least a self-modifying method that works like update() but
without clobbering existing values.

h={'a',1, 'c',3, 'd',4}
h={'a',99, 'b',2}.update(h)
--> {"a"=>1, "b"=>2, "c"=>3, "d"=>4}
 
D

David A. Black

Hi --

h={'a',1, 'c',3, 'd',4}
h={'a',99, 'b',2}.update(h)
--> {"a"=>1, "b"=>2, "c"=>3, "d"=>4}

However....

irb(main):006:0> h={'a',1, 'c',3, 'd',4}
=> {"a"=>1, "c"=>3, "d"=>4}
irb(main):007:0> h.object_id
=> 537888058
irb(main):008:0> h={'a',99, 'b',2}.update(h)
=> {"a"=>1, "b"=>2, "c"=>3, "d"=>4}
irb(main):009:0> h.object_id
=> 537863828

So if it matters that it be the same object, this technique won't be
appropriate. Also, if you're using something other than a hash
literal, for example:

h1 = h2.update(h1)

you're going to change h2, which might also be undesireable in some
cases.


David
 
D

David A. Black

Hi --

Hi Mark,
I was wondering if there were a module that supplied [...]
a self-modifying method that works like update() but
without clobbering existing values.

Here's what I use, FWIW:

def compensate(defaults)
defaults.merge self
end

I'm curious what this gains you. Is it better than just saying
defaults.merge(self)?
def compensate!(defaults)
for key, value in defaults do
self[key] = value unless include? key
end
end

That one seems to do more :)


David
 
B

Brian Schröder

myhash['keyval'] ||=3D newval ## won't stomp on existing value if
'keyval' already in my #keys

Though beware of nil and false

irb(main):001:0> h =3D {1 =3D> nil, 2 =3D> false, 3 =3D> true}
=3D> {1=3D>nil, 2=3D>false, 3=3D>true}
irb(main):002:0> h[1] ||=3D 2
=3D> 2
irb(main):003:0> h[2] ||=3D 3
=3D> 3
irb(main):004:0> h[4] ||=3D 5
=3D> 5
irb(main):005:0> h
=3D> {1=3D>2, 2=3D>3, 3=3D>true, 4=3D>5}

regards,

Brian

=20
also, Hash#merge and Hash#merge! take blocks to say how to handle
duplicated key values
=20
=20


--=20
http://ruby.brian-schroeder.de/

Stringed instrument chords: http://chordlist.brian-schroeder.de/
 
D

Daniel Brockman

David A. Black said:
I'm curious what this gains you. Is it better than just
saying defaults.merge(self)?

Good point. Come to think about it, I doubt if I ever used
the non-destructive variant. I guess depending on your
taste it could be nicer when defaults is a hash literal and
self isn't.

def foo1(options)
bar { :moomin =3D> 123 }.merge(options)
end

def foo2(options)
bar options.compensate:)moomin =3D> 123)
end

The former is shorter and uses standard operations only,
but the latter is arguably conceptually simpler once you
get used to the compensate method.

Also, you could argue that if there's a =E2=80=98compensate!=E2=80=99,
then there should also be a =E2=80=98compensate=E2=80=99.

But yeah... :)

--=20
Daniel Brockman <[email protected]>

So really, we all have to ask ourselves:
Am I waiting for RMS to do this? --TTN.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,176
Messages
2,570,949
Members
47,500
Latest member
ArianneJsb

Latest Threads

Top