# Hash \<\<

**URL:** <https://rubytalk.org/t/hash/14307>\
**Category:** ruby-talk\
**Created:** [20 October 2004 14:04 UTC](https://rubytalk.org/t/hash/14307 "2004-10-20T14:04:03Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![Matt\_Maycock](https://avatars.discourse-cdn.com/v4/letter/m/e9a140/32.png) [@Matt\_Maycock](https://rubytalk.org/u/Matt_Maycock)\
**Post date:** [20 October 2004 14:04 UTC](https://rubytalk.org/t/hash/14307/1 "2004-10-20T14:04:03Z")

</div>

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:

&nbsp;&nbsp;h = {}  
&nbsp;&nbsp;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  
&nbsp;&nbsp;def \<\<(k)  
&nbsp;&nbsp;&nbsp;&nbsp;if @shift\_value.nil? then  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@shift\_value = Object.new.singleton\_def(:key) {k}  
&nbsp;&nbsp;&nbsp;&nbsp;else  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;key, @shift\_value = @shift\_value.key, nil  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self[key] = k  
&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;self  
&nbsp;&nbsp;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.
> 
> --  
> There's no word in the English language for what you do to a dead  
> thing to make it stop chasing you.

---

<div class="post-metadata">

**Author:** ![James\_Edward\_Gray\_II](https://avatars.discourse-cdn.com/v4/letter/j/ea5d25/32.png) [@James\_Edward\_Gray\_II](https://rubytalk.org/u/James_Edward_Gray_II)\
**Post date:** [20 October 2004 14:17 UTC](https://rubytalk.org/t/hash/14307/2 "2004-10-20T14:17:35Z")

</div>

Why use this over:

h.update(:a =\> :b, :c =\> :d, :e =\> :f)

?

James Edward Gray II

> **···**
>
> On Oct 20, 2004, at 9:04 AM, Matt Maycock wrote:
> 
> > 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:
> > 
> > &nbsp;&nbsp;h = {}  
> > &nbsp;&nbsp;h.update(:a =\> :b).update(:c =\> :d).update(:e =\> :f)

---

<div class="post-metadata">

**Author:** ![Brian\_Candler](https://avatars.discourse-cdn.com/v4/letter/b/5f9b8f/32.png) [@Brian\_Candler](https://rubytalk.org/u/Brian_Candler)\
**Post date:** [20 October 2004 14:32 UTC](https://rubytalk.org/t/hash/14307/3 "2004-10-20T14:32:28Z")

</div>

> ---usage---  
> h = {}  
> h \<\< :language \<\< :ruby \<\< :creator \<\< :matz \<\< :users \<\< :"comp.lang.ruby"  
> p h  
> ---result---  
> {:language=\>:ruby, :creator=\>:matz, :users=\>:"comp.lang.ruby"}  
> -------------

Ugh. Toggling internal state like that will leave you in mutex hell if  
you're trying to write thread-safe code.

I suppose I wouldn't object to:

&nbsp;&nbsp;class Hash  
&nbsp;&nbsp;&nbsp;&nbsp;def \<\<(kv)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self[kv[0]] = kv[1]  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self  
&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;end

&nbsp;&nbsp;h \<\< [:language,:ruby] \<\< [:creator,:matz] \<\< [:users,:"comp.lang.ruby"]

but I've never felt the need.

Regards,

Brian.

---

<div class="post-metadata">

**Author:** ![Robert](https://avatars.discourse-cdn.com/v4/letter/r/e95f7d/32.png) [@Robert](https://rubytalk.org/u/Robert)\
**Post date:** [20 October 2004 14:34 UTC](https://rubytalk.org/t/hash/14307/4 "2004-10-20T14:34:18Z")

</div>

"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:
> 
> &nbsp;&nbsp;h = {}  
> &nbsp;&nbsp;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  
> &nbsp;&nbsp;def \<\<(k)  
> &nbsp;&nbsp;&nbsp;&nbsp;if @shift\_value.nil? then  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@shift\_value = Object.new.singleton\_def(:key) {k}  
> &nbsp;&nbsp;&nbsp;&nbsp;else  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;key, @shift\_value = @shift\_value.key, nil  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self[key] = k  
> &nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;self  
> &nbsp;&nbsp;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  
&nbsp;&nbsp;def \<\<(pair)  
&nbsp;&nbsp;&nbsp;&nbsp;self[pair[0] ]= pair[1]  
&nbsp;&nbsp;&nbsp;&nbsp;self  
&nbsp;&nbsp;end  
end

h = {}  
h \<\< [:key, :val] \<\< [:key2, :val2]

Opt 2.

class HashAdder \< Struct.new(:hash, :key)  
&nbsp;&nbsp;def \<\<(val)  
&nbsp;&nbsp;&nbsp;&nbsp;self.hash[self.key] = val  
&nbsp;&nbsp;&nbsp;&nbsp;self.hash  
&nbsp;&nbsp;end  
end

class Hash  
&nbsp;&nbsp;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

&nbsp;&nbsp;&nbsp;&nbsp;robert

---

<div class="post-metadata">

**Author:** ![Florian\_Gross](https://avatars.discourse-cdn.com/v4/letter/f/e9a140/32.png) [@Florian\_Gross](https://rubytalk.org/u/Florian_Gross)\
**Post date:** [20 October 2004 19:39 UTC](https://rubytalk.org/t/hash/14307/5 "2004-10-20T19:39:17Z")

</div>

Matt Maycock wrote:

> 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.

I'm not sure, but maybe KeyedList could help here. It is a Hash that has list-style insert operations:

> Struct.new("Hero", :name, :reason)
> 
> # Create a KeyedList which will be keyed by the names  
> # of its heroic elements.  
> list = KeyedList.new { |hero| hero.name }  
> # Adds elements to the KeyedList.  
> list \<\< Struct::Hero.new("Yukihiro Matsumoto", "Ruby")  
> list \<\< Struct::Hero.new("Larry Wall", "Enhanced regular expressions")  
> list \<\< Struct::Hero.new("Randal Schwartz", "Schwartzian transform")  
> &nbsp;&nbsp;&nbsp;list.size # =\> 3  
> list["Yukihiro Matsumoto"].reason # =\> "Ruby"

It is both available as a Gem and from RPA.

Regards,  
Florian Gross

---

<div class="post-metadata">

**Author:** ![Markus](https://avatars.discourse-cdn.com/v4/letter/m/b782af/32.png) [@Markus](https://rubytalk.org/u/Markus)\
**Post date:** [25 October 2004 04:46 UTC](https://rubytalk.org/t/hash/14307/6 "2004-10-25T04:46:57Z")

</div>

I know I'm late to the party here, but would you be happy with:

&nbsp;&nbsp;&nbsp;&nbsp;class Hash  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alias \<\< update  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end

with which you could write:

&nbsp;&nbsp;h \<\< {:a =\> :b} \<\< {:c =\> :d} \<\< {:e =\> :f}

&nbsp;&nbsp;&nbsp;-- Markus

P.S. I still maintain the canonical refutation of your sig is "hug."

> **···**
>
> On Wed, 2004-10-20 at 07:04, Matt Maycock wrote:
> 
> > 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:
> > 
> > &nbsp;&nbsp;h = {}  
> > &nbsp;&nbsp;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  
> > &nbsp;&nbsp;def \<\<(k)  
> > &nbsp;&nbsp;&nbsp;&nbsp;if @shift\_value.nil? then  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@shift\_value = Object.new.singleton\_def(:key) {k}  
> > &nbsp;&nbsp;&nbsp;&nbsp;else  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;key, @shift\_value = @shift\_value.key, nil  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self[key] = k  
> > &nbsp;&nbsp;&nbsp;&nbsp;end  
> > &nbsp;&nbsp;&nbsp;&nbsp;self  
> > &nbsp;&nbsp;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.

---

<div class="post-metadata">

**Author:** ![Matt\_Maycock](https://avatars.discourse-cdn.com/v4/letter/m/e9a140/32.png) [@Matt\_Maycock](https://rubytalk.org/u/Matt_Maycock)\
**Post date:** [20 October 2004 14:22 UTC](https://rubytalk.org/t/hash/14307/7 "2004-10-20T14:22:13Z")

</div>

I really just wanted to show the chaining thing - but there may be  
other methods in between that give issues with doing it all at once.

~Me!

> **···**
>
> On Wed, 20 Oct 2004 23:17:35 +0900, James Edward Gray II \<james@grayproductions.net\> wrote:
> 
> > On Oct 20, 2004, at 9:04 AM, Matt Maycock wrote:
> > 
> > \> 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)
> > 
> > Why use this over:
> > 
> > h.update(:a =\> :b, :c =\> :d, :e =\> :f)
> > 
> > ?
> > 
> > James Edward Gray II
> 
> --  
> There's no word in the English language for what you do to a dead  
> thing to make it stop chasing you.

---

<div class="post-metadata">

**Author:** ![Matt\_Maycock](https://avatars.discourse-cdn.com/v4/letter/m/e9a140/32.png) [@Matt\_Maycock](https://rubytalk.org/u/Matt_Maycock)\
**Post date:** [25 October 2004 14:54 UTC](https://rubytalk.org/t/hash/14307/8 "2004-10-25T14:54:29Z")

</div>

> P.S. I still maintain the canonical refutation of your sig is "hug."

The undead would still be chasing you - just with a mixed drink... 🙂

> **···**
>
> --  
> There's no word in the English language for what you do to a dead  
> thing to make it stop chasing you.

---

<div class="post-metadata">

**Author:** ![Matt\_Maycock](https://avatars.discourse-cdn.com/v4/letter/m/e9a140/32.png) [@Matt\_Maycock](https://rubytalk.org/u/Matt_Maycock)\
**Post date:** [20 October 2004 14:26 UTC](https://rubytalk.org/t/hash/14307/9 "2004-10-20T14:26:02Z")

</div>

[double post]

of course, mine isn't much better if you're doing

hash.update(...).foo.meow.update(...)

as opposed to

((hash \<\< ... \<\<).foo.meow \<\< ...)...

so maybe it is a bad idea... 🙂

My main use is in cases with:  
a = enum.inject(Hash.new) {|h, f|  
&nbsp;&nbsp;h.update(k(f) =\> v(f))  
}

for some odd reason,  
&nbsp;&nbsp;a = enum.inject(Hash.new) {|h, f|  
&nbsp;&nbsp;&nbsp;&nbsp;h \<\< k(f) \<\< v(f)  
&nbsp;&nbsp;}  
just `feels' better to me.

> **···**
>
> On Wed, 20 Oct 2004 10:22:10 -0400, Matt Maycock \<ummaycoc@gmail.com\> wrote:
> 
> > I really just wanted to show the chaining thing - but there may be  
> > other methods in between that give issues with doing it all at once.
> > 
> > ~Me!
> > 
> > On Wed, 20 Oct 2004 23:17:35 +0900, James Edward Gray II \> \<james@grayproductions.net\> wrote:  
> > \> On Oct 20, 2004, at 9:04 AM, Matt Maycock wrote:  
> > \>  
> > \> \> 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)  
> > \>  
> > \> Why use this over:  
> > \>  
> > \> h.update(:a =\> :b, :c =\> :d, :e =\> :f)  
> > \>  
> > \> ?  
> > \>  
> > \> James Edward Gray II  
> > \>  
> > \>
> > 
> > --  
> > There's no word in the English language for what you do to a dead  
> > thing to make it stop chasing you.
> 
> --  
> There's no word in the English language for what you do to a dead  
> thing to make it stop chasing you.

---

<div class="post-metadata">

**Author:** ![Brian\_Candler](https://avatars.discourse-cdn.com/v4/letter/b/5f9b8f/32.png) [@Brian\_Candler](https://rubytalk.org/u/Brian_Candler)\
**Post date:** [20 October 2004 14:35 UTC](https://rubytalk.org/t/hash/14307/10 "2004-10-20T14:35:25Z")

</div>

> for some odd reason,  
> &nbsp;&nbsp;a = enum.inject(Hash.new) {|h, f|  
> &nbsp;&nbsp;&nbsp;&nbsp;h \<\< k(f) \<\< v(f)  
> &nbsp;&nbsp;}  
> just `feels' better to me.

Feels better than

&nbsp;&nbsp;&nbsp;&nbsp;h[k(f)] = v(f)

?

---

<div class="post-metadata">

**Author:** ![Matt\_Maycock](https://avatars.discourse-cdn.com/v4/letter/m/e9a140/32.png) [@Matt\_Maycock](https://rubytalk.org/u/Matt_Maycock)\
**Post date:** [20 October 2004 15:00 UTC](https://rubytalk.org/t/hash/14307/11 "2004-10-20T15:00:35Z")

</div>

You'd have to make that  
&nbsp;&nbsp;a = enum.inject(Hash.new) {|h, f|  
&nbsp;&nbsp;&nbsp;&nbsp;h[k(f)] = v(f)  
&nbsp;&nbsp;&nbsp;&nbsp;h  
&nbsp;&nbsp;}  
-- my general desire is to have code be a single expression when I  
write code. just the way I work 🙂

~Me!

> **···**
>
> On Wed, 20 Oct 2004 23:35:25 +0900, Brian Candler \<b.candler@pobox.com\> wrote:
> 
> > \> for some odd reason,  
> > \> a = enum.inject(Hash.new) {|h, f|  
> > \> h \<\< k(f) \<\< v(f)  
> > \> }  
> > \> just `feels' better to me.
> > 
> > Feels better than
> > 
> > &nbsp;&nbsp;&nbsp;&nbsp;h[k(f)] = v(f)
> > 
> > ?
> 
> --  
> There's no word in the English language for what you do to a dead  
> thing to make it stop chasing you.
