<< for Hash?

class Hash
def <<(arg)
self.merge!(arg)
end
end

Eg,

thing = {
:foo => 1,
}

thing << {
:bar => 2,
:baz => 3,
}

thing #=> {:foo=>1, :bar=>2, :baz=>3 }

Of course it overwrites existing keys. I think it’s a little sexier than

thing.merge!({
:bar => 2,
:baz => 3,
})

or
thing[:bar] = 1
thing[:baz] = 3

Is it safe to use this? Is there some good reason why << is not already
defined for Hash?

Simon
(newbie)

Ps, my first ruby project:
http://tiddlyspot.com/

{:foo,1}.merge! :bar => 2

{:foo=>1, :bar=>2}

2006/6/26, Simon B. [email protected]:

}

Is it safe to use this? Is there some good reason why << is not already
defined for Hash?

The reason is probably that your << appends a complete collection (a
hash) to the hash while usually it appends just a single element (see
for example Array#<< and IO#<<). While I think about it, String#<<
appends the same type (String) to a String…

Kind regards

robert

I like Michael’s solution.

The {}'s are not needed, as long as the hash is the only or last
argument to a method.

{:a => 1, :b => 2}.merge(:c => 3, :d => 4)
#=> {:a => 1, :b => 2, :c => 3, :d => 4)

On 6/26/06, Matthew H. [email protected] wrote:

I like Michael’s solution.

The {}'s are not needed, as long as the hash is the only or last
argument to a method.

{:a => 1, :b => 2}.merge(:c => 3, :d => 4)
#=> {:a => 1, :b => 2, :c => 3, :d => 4)

I noticed this:

class Hash
def <<(arg)
self.merge!(arg)
end
end

x = { :a => 1 }

x.<< :f => 1, :g => 1 # works

x << :h => 1, :i => 1 # syntax error

Is there a way to make the above work? I don’t care really since I think
the
following is clearer:
x << { :h => 1, :i => 1 } # my preferred

Cheers,
Simon.

but this screws up the scemantics

“<<” is append… and you cant “append” something in a hash , there is
no way to add anything to the end of a hash since items are inserted
based on hashed index.

On 6/27/06, Simon B. [email protected] wrote:

x.<< :f => 1, :g => 1 # works

x << :h => 1, :i => 1 # syntax error

Is there a way to make the above work? I don’t care really since I think
the
following is clearer:
x << { :h => 1, :i => 1 } # my preferred

No, sorry… as pointed out in another recent thread, overriding the <<
method can change the behaviour but not the syntax of the << operator.

Curses, huh.

;D

Simon B. wrote:

class Hash
def <<(arg)
self.merge!(arg)
end
end

class Hash
alias << merge!
end

cheers

Simon

On 6/29/06, Joel VanderWerf [email protected] wrote:

That doesn’t seem to stop Set#<< :

irb(main):001:0> s = Set[1,2,3]
=> #<Set: {1, 2, 3}>
irb(main):002:0> s << 4
=> #<Set: {1, 2, 3, 4}>

That’s because the semantics make sense in the context of Set. Set acts
like
an unordered list, not like a Hash. There’s certanily some hand-waiving
going on to make << work with the Hash, but as has been shown, that’s
not
too tough. IMO, appending ‘5’ to a list of numbers {1,2,3,4} makes sense
while appending a key/value pair doesn’t.

From the doc: 'Set
http://www.ruby-doc.org/core/classes/Set.htmlimplements a collection
of unordered values with no duplicates. This is a
hybrid of Array http://www.ruby-doc.org/core/classes/Array.html’s
intuitive inter-operation facilities and
Hashhttp://www.ruby-doc.org/core/classes/Hash.html’s
fast lookup."

|| Dean

Roger J. wrote:

but this screws up the scemantics

“<<” is append… and you cant “append” something in a hash , there is
no way to add anything to the end of a hash since items are inserted
based on hashed index.

That doesn’t seem to stop Set#<< :

irb(main):001:0> s = Set[1,2,3]
=> #<Set: {1, 2, 3}>
irb(main):002:0> s << 4
=> #<Set: {1, 2, 3, 4}>

On 6/29/06, Dean S. [email protected] wrote:

On 6/29/06, Joel VanderWerf [email protected] wrote:

That doesn’t seem to stop Set#<< :

irb(main):001:0> s = Set[1,2,3]
=> #<Set: {1, 2, 3}>
irb(main):002:0> s << 4
=> #<Set: {1, 2, 3, 4}>

That’s because the semantics make sense in the context of Set. Set acts like
an unordered list, not like a Hash.

I disagree. Mathematically, a essentially hash is just a set of key,
value pairs. It’s not just a set, due to the requirement that keys
be unique, but it’s close enough. So if you can “append” to a set by
adding a value, why not append to a hash by adding a pair?

IMO, appending ‘5’ to a list of numbers {1,2,3,4} makes sense
while appending a key/value pair doesn’t.

I don’t see any problem with appending a pair to a Hash, as in my mind
it is equivalent to appending a value to a Set. However, I will point
out that the semantics of the proposed Hash#<< and Set#<< are
different. Array#<< and Set#<< each expect a single value; if you give
another Array or Set as the argument, it’s added as a unit, rather
than iterating over the contents. The proposed Hash#<< on the other
hand requires that the argument be a collection of pairs which can
be iterated over. So there is that difference.

I think the utility can overcome that minor semantic difference,
however.

Jacob F.

On 6/29/06, Jacob F. [email protected] wrote:

So if you can “append” to a set by
adding a value, why not append to a hash by adding a pair?

Okay, fair enough.

However, I will point

out that the semantics of the proposed Hash#<< and Set#<< are
different. Array#<< and Set#<< each expect a single value; if you give
another Array or Set as the argument, it’s added as a unit, rather
than iterating over the contents.

I think this is closer to the point I was trying (unsuccessfully) to
make. I
think that having Hash#<< is useful only so long as it complies with the
semantics of what << normally does. As proposed, Hash#<< is really just
Hash#merge! in diguise. There is no reason to make a semantically
ambiguous
definition (which you pointed out above) when you could simply use
#merge!
instead.

You could write Hash#<< to only accept a single key/value pair and be
semantically meaningful, but there are a few problems with this:

  1. As pointed out,

{ :foo => bar } << :a => 1

still doesn’t work. It has to be

{ :foo => bar }.<< :a => 1

which IMO is just ugly.

  1. When someone tries to append a Hash to a Hash with #<< , what
    happens?
    { :foo => bar }.<< { :a => 1, :b => 2} #ERR

You can’t really do this because it still doesn’t make semantic sense.
The
whole hash should get added (not each element), but without a key, you
can’t
add it.

  1. Because of the way a Hash works, you can’t add multiple values for
    the
    same key, and this is how << is supposed to work. When you say

[1,2,3,4] << 4
=> [1,2,3,4,4] #not [1,2,3,4]
The behavior here is what you would expect from something that
“appends,”
while Hash#<< doesn’t do the same.

I’m not saying it’s a terrible, evil, awful thing to have Hash#<<. I
just
think you should think there are a lot of potential negatives,
especially
when you could just as easily say Hash#merge!.

|| Dean

On 6/29/06, Dean S. [email protected] wrote:

  1. Because of the way a Hash works, you can’t add multiple values for the
    same key, and this is how << is supposed to work. When you say

[1,2,3,4] << 4
=> [1,2,3,4,4] #not [1,2,3,4]
The behavior here is what you would expect from something that “appends,”
while Hash#<< doesn’t do the same.

Ah, but this is just how a Set works:

require ‘set’
x = Set[ 1, 2, 3, 4 ]
x << 4
p x

=> #<Set: {1, 2, 3, 4}>, not #<Set: {1, 2, 3, 4, 4}>

And you didn’t seem to have a problem with Set#<< earlier… :wink:

Jacob F.

[email protected] wrote:

incidentally, ‘<<’ is not a pure append operator in ruby

class << self
end

42 << 2

string = <<hdoc
foobar
hdoc

But those aren’t other uses of the << operator. Those are “just” syntax.

On Fri, 30 Jun 2006, Dean S. wrote:

That’s because the semantics make sense in the context of Set. Set acts like
an unordered list, not like a Hash. There’s certanily some hand-waiving
going on to make << work with the Hash, but as has been shown, that’s not
too tough. IMO, appending ‘5’ to a list of numbers {1,2,3,4} makes sense
while appending a key/value pair doesn’t.

imho both appending to set and appending to hash make equal
sense/nonsense as
both containers are unorder and have no ‘end’.

incidentally, ‘<<’ is not a pure append operator in ruby

class << self
end

42 << 2

string = <<hdoc
foobar
hdoc

food for thought.

-a

Le 29 juin 06, à 19:04, [email protected] a écrit :

only
‘append’.

Can’t we see shifting an Integer the same as appending zeroes on one
end of it? Just to play the devil’s advocate…

Guillaume.

On Fri, 30 Jun 2006, Joel VanderWerf wrote:

foobar

hdoc

But those aren’t other uses of the << operator. Those are “just” syntax.

hmmm. you are right in two of three. but Fixnum#<< is definitely a
method.
in any case ruby has precedent for ‘<<’ meaning other things besides
only
‘append’.

cheers.

-a

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs