[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Special Hash Constructors

Robert Klemme

2/6/2009 5:05:00 PM


Hi there,

we frequently do

ha = Hash.new {|h,k| h[k] = []}

so we can later do

ha[any_key] << anything

Since the idiom is so common, what does everybody think of putting it
into the standard library:

def Hash.with_arrays
new {|h,k| h[k] = []}
end

While we're at it, we might as well add

def Hash.with_hashes
new {|h,k| h[k] = Hash.new(&h.default_proc)}
end

Kind regards

robert
23 Answers

Christopher Dicely

2/6/2009 5:44:00 PM

0

On Fri, Feb 6, 2009 at 9:09 AM, Robert Klemme
<shortcutter@googlemail.com> wrote:
>
> Hi there,
>
> we frequently do
>
> ha = Hash.new {|h,k| h[k] = []}
>
> so we can later do
>
> ha[any_key] << anything
>
> Since the idiom is so common, what does everybody think of putting it into
> the standard library:
>
> def Hash.with_arrays
> new {|h,k| h[k] = []}
> end
>
> While we're at it, we might as well add
>
> def Hash.with_hashes
> new {|h,k| h[k] = Hash.new(&h.default_proc)}
> end
>
> Kind regards
>
> robert

Rather than making class methods on Hash to create special hashes like
this, why not make subclasses, so you can attach specialized instance
methods that make sense only for these kinds of hashes. For instance,
for the Hash-of-Hashes form, you might want a method that "rotates"
the Hash into a new Hash-of-Hashes like this:

def rotate
res = HashOfHashes.new
each { |ok, ov| ov.each { |ik, iv| res[ik][ok] = iv } }
res
end

Julian Leviston

2/7/2009 12:39:00 AM

0

Wow I like that. This is what I end up doing:

ha = {}
(ha[any_key] ||= []) << anything

J

On 07/02/2009, at 4:09 AM, Robert Klemme wrote:

>
> Hi there,
>
> we frequently do
>
> ha = Hash.new {|h,k| h[k] = []}
>
> so we can later do
>
> ha[any_key] << anything
>
> Since the idiom is so common, what does everybody think of putting
> it into the standard library:
>
> def Hash.with_arrays
> new {|h,k| h[k] = []}
> end
>
> While we're at it, we might as well add
>
> def Hash.with_hashes
> new {|h,k| h[k] = Hash.new(&h.default_proc)}
> end
>
> Kind regards
>
> robert
>


Simon Krahnke

2/7/2009 4:30:00 AM

0

* Robert Klemme <shortcutter@googlemail.com> (18:05) schrieb:

> ha = Hash.new {|h,k| h[k] = []}

> Since the idiom is so common, what does everybody think of putting it
> into the standard library:

Why not

def Hash.with(default=nil)
new { | h, k | h[k] = default.dup }
end

> While we're at it, we might as well add
>
> def Hash.with_hashes
> new {|h,k| h[k] = Hash.new(&h.default_proc)}
> end

I'm too tired for that. Does that create Hash with a default proc that
is the same as the one you specify right there?

mfg, simon .... l

ThoML

2/7/2009 6:16:00 AM

0

> def Hash.with(default=3Dnil)
> =A0 new { | h, k | h[k] =3D default.dup }
> end

Not so good:

> h =3D Hash.with(0)
> h[1]
TypeError: can't dup Fixnum

I personally would appreciate a special constructor for Arrays.

Jesús Gabriel y Galán

2/7/2009 10:10:00 AM

0

On Sat, Feb 7, 2009 at 5:34 AM, Simon Krahnke <overlord@gmx.li> wrote:
> * Robert Klemme <shortcutter@googlemail.com> (18:05) schrieb:

>> def Hash.with_hashes
>> new {|h,k| h[k] = Hash.new(&h.default_proc)}
>> end
>
> I'm too tired for that. Does that create Hash with a default proc that
> is the same as the one you specify right there?

Yes, it achieves having infinitely nested hashes:

irb(main):001:0> def Hash.with_hashes
irb(main):002:1> new {|h,k| h[k] = Hash.new(&h.default_proc)}
irb(main):003:1> end
=> nil
irb(main):004:0> h = Hash.with_hashes
=> {}
irb(main):005:0> h[1][2][3] = true
=> true
irb(main):006:0> h
=> {1=>{2=>{3=>true}}}

I agree that it would be nice to have them in the standard library,
but maybe Hash.of_hashes and Hash.of_arrays would be better names?

Jesus.

Robert Klemme

2/7/2009 10:24:00 AM

0

On 07.02.2009 11:09, Jesús Gabriel y Galán wrote:
> On Sat, Feb 7, 2009 at 5:34 AM, Simon Krahnke <overlord@gmx.li> wrote:

> I agree that it would be nice to have them in the standard library,
> but maybe Hash.of_hashes and Hash.of_arrays would be better names?

Yes, probably. I'm not religious about the names. My point was simply
that this is so often used that we might want to have it in the standard
library.

Cheers

robert

Trans

2/7/2009 10:26:00 AM

0



On Feb 6, 12:09=A0pm, Robert Klemme <shortcut...@googlemail.com> wrote:
> Hi there,
>
> we frequently do
>
> ha =3D Hash.new {|h,k| h[k] =3D []}
>
> so we can later do
>
> ha[any_key] << anything
>
> Since the idiom is so common, what does everybody think of putting it
> into the standard library:
>
> def Hash.with_arrays
> =A0 =A0new {|h,k| h[k] =3D []}
> end
>
> While we're at it, we might as well add
>
> def Hash.with_hashes
> =A0 =A0new {|h,k| h[k] =3D Hash.new(&h.default_proc)}
> end

I've been using the name #autonew for this last one.

Also @Tom Link

def Hash.with(default=3Dnil)
begin
new { | h, k | h[k] =3D default.dup }
rescue TypeError
new(default) # same as { | h, k | h[k] =3D default }
end
end

T.

ThoML

2/7/2009 10:45:00 AM

0

> =A0 def Hash.with(default=3Dnil)
> =A0 =A0 begin

I think we have to insert a check for "dupability" here:

default.dup
> =A0 =A0 =A0 new { | h, k | h[k] =3D default.dup }
...

This method isn't capable of emulating the with_hashes method proposed
by Robert K though, is it?

Robert Klemme

2/7/2009 1:14:00 PM

0

On 07.02.2009 11:26, Trans wrote:
>
> On Feb 6, 12:09 pm, Robert Klemme <shortcut...@googlemail.com> wrote:
>> Hi there,
>>
>> we frequently do
>>
>> ha = Hash.new {|h,k| h[k] = []}
>>
>> so we can later do
>>
>> ha[any_key] << anything
>>
>> Since the idiom is so common, what does everybody think of putting it
>> into the standard library:
>>
>> def Hash.with_arrays
>> new {|h,k| h[k] = []}
>> end
>>
>> While we're at it, we might as well add
>>
>> def Hash.with_hashes
>> new {|h,k| h[k] = Hash.new(&h.default_proc)}
>> end
>
> I've been using the name #autonew for this last one.
>
> Also @Tom Link
>
> def Hash.with(default=nil)
> begin
> new { | h, k | h[k] = default.dup }
> rescue TypeError
> new(default) # same as { | h, k | h[k] = default }
> end
> end

Where's the point of the rescue clause? The error will show up much
later, i.e. after the method has returned.

Also, as Tom pointed out, this is not the same as what I proposed - not
even similar.

Regards

robert

Pit Capitain

2/7/2009 3:37:00 PM

0

2009/2/7 Tom Link <micathom@gmail.com>:
> Not so good:
> TypeError: can't dup Fixnum

I often use

class Hash
def self.new_with
new { |h, k| h[k] = yield }
end
end

Hash.new_with { [] }

which works with Arrays and Fixnums, though it isn't needed for the latter.

Regards,
Pit