Hi --

On Mon, 20 Jan 2003, Tom Payne wrote:

> dblack / candle.superlink.net wrote in message news:<Pine.LNX.4.44.0301181254230.23130-100000 / candle.superlink.net>...
> > Almost :-)  See <http://www.ruby-talk.org/6663>.  I seem to evade
> > naming any of the variants just "to_h" (they're to_h_raw, to_h_ikeys),
> > etc.  I'm inclined to think "to_h" would be what I called "to_h_raw",
> > i.e.:  [1,2,3,4].to_h => { 1 => 2, 3 => 4 }, but I'm not sure.
>
> I think of Arrays as mapping integers >= 0 to values, and of Hashes of
> mapping arbitrary keys to values. So, for me, the POLS for Array.to_h
> would be to produce a Hash that maps the same keys as the array to the
> same values, i.e [:a, :b].to_h => {0 => :a, 1 => b}.
>
> Your to_h ([1,2,3,4].to_h => { 1 => 2, 3 => 4 }) might be more
> familiar to a PERL programmer. IIRC, in PERL hashes can be written
> [key0, value0, key1, value1, ...], but I might be wrong.

(s/PERL/Perl/ :-)  Yes, there's something like that in Perl, but I'm
thinking more about what's familiar to a Ruby programmer:

  Hash[1,2,3,4]  # => { 1 => 2, 3 => 4 }

and taking that as the model for the simplest case of creating a hash
from a list (literal or array-derived).  It's possible to argue that,
since we already have the above, we don't need Array#to_h to emulate
it.  I suppose I like the sort of organic quality of a to_h that does
what Hash[*arr] does, and then variants that build on that simplest
construct.

I don't think POLS is a big issue here.  Since there are several
versions of this in circulation already, whoever uses them pretty much
has to be willing to read the code and/or documentation anyway :-)

> N.B. Your implementation of to_h_raw from
> <http://www.ruby-talk.org/6663>:
> should really be in the Array class, not the Enumerable module,
> because it uses the shift method: Arrays have this, but Enumerables
> don't.

Whoops.  Glitches from 60000 messages ago come back to haunt
me.... :-)

> An implementation using each (provided by Enumerable):
>
> module Enumerable
>   def to_h_raw(default = nil)
>     result = Hash.new(default)
>     key = nil
>     index = 0
>     each do |element|
>       case index % 2
>       when 0 then key = element
>       when 1 then result[key] = element
>       end
>       index += 1
>     end
>     result[key] = nil if index % 2 == 1
>     result
>   end
> end
>
> [1, 2, 3, 4].to_h_raw => {1=>2, 3=>4}
> [1, 2, 3, 4, 5].to_h_raw => {5=>nil, 1=>2, 3=>4}

You can trim this down a bit.  Accessing an uninitialized array
element will give you nil, so you don't have to test for that.  Here's
a version on the very-short-and-probably-inefficient end of the scale
-- there's probably a nice middle ground somewhere :-)

  module Enumerable
    def to_h_raw(default=nil)
      Hash[*(if (size % 2).zero? then to_a else to_a + [default] end)]
    end
  end

  p [1, 2, 3, 4].to_h_raw     # => {1=>2, 3=>4}
  p [1, 2, 3, 4, 5].to_h_raw  # => {5=>nil, 1=>2, 3=>4}

  h = [1,2,3].to_h_raw(10)
  p h[3]                      # => 10


David

-- 
David Alan Black
home: dblack / candle.superlink.net
work: blackdav / shu.edu
Web:  http://pirate.shu.edu/~blackdav