From: Paul Brannan Date: 2002-08-05T22:25:53+09:00 Subject: Re: Assoc Class (Hash Pairs) On Sun, Aug 04, 2002 at 03:05:49AM +0900, Tom Sawyer wrote: > i've been thinking about posting this as an RCR. > > i would really like to see hash pairs (associations) become real > objects. i think it would be a very powerful and useful construct. there > are number of things one could then do. The simpliest obviosuly being: > > x = 'a'=>1 > y = 'b'=>2 > > hash = { x, y } A pair is a real object; it's called an array (with length=2). Extensions often need to create such an object using rb_assoc_new (from array.c): VALUE rb_assoc_new(car, cdr) VALUE car, cdr; { VALUE ary; ary = rb_ary_new2(2); RARRAY(ary)->ptr[0] = car; RARRAY(ary)->ptr[1] = cdr; RARRAY(ary)->len = 2; return ary; } > ordered hashes also become a snap, implemented as arrays of these > associations: > > ordhash = [ x, y ] In Ruby, this is done with an array of arrays: x = ['a', 1] y = ['b', 2] ordhash = [ x, y ] p ordhash.assoc('a')[1] #=> 1 > or, without the above x and y assignments, just > > ordhash = [ 'a'=>1 , 'b'=>2 ] > this association class (Assoc?) would of course mixin the comparable > module. This might be useful. But how would this comparison be done? Would it compare keys or values? Or a combination? > the Assoc class becomes very useful when you start to build more comlex > structures (what i would like to use it for): > > c = [ 'a'=>1, 's' ] > > this is a very simple example, but without the Assoc you'd have to write > this as: > > c = { 'a'=>1, 's'=>nil } I see no reason why Ruby should assume that if 's' has a key but no value associated with it that it should get nil. It would be MUCH more useful to me to have the default be true, instead. I doubt there can be a default that will please everyone. If you create a hash, then elements with no keys get nil by default. So what you have written is not too different from: c = { 'a'=> 1 } p c['s'] #=> nil except that iterating over the above structure produces a different result. > adding a useless nil, or > > c = [ ['a', 1], 's' ] > > whereby you have to use indexes on the association. Here's an option: c = [ ['a', 1], 's' ] d = c.map { |x| Array === x ? x : [ x, nil ] } e = Hash[*d] You can put this into a function somewhere if you want to avoid writing it over and over. > i'm sure there are other uses as well, and i think it may be possible > that such an Assoc class combined with arrays could ultimatly displace > regular hashes altogether. Hashes have O(1) lookups, but are not ordered. An array of assocs has O(n) lookups, but are ordered. Trees make a good compromise (more complex, but ordered with O(log(n)) lookups), which would probably make a better choice. Paul