On Mar 2, 2007, at 10:25 AM, Leslie Viljoen wrote:
> Otherwise, why restrict the user of your method this way?

The entire context is that of object construction and how best to
'parse' an argument list.  I'm trying to focus on this very
specific context (which is closely associated with DSL designs)
and not the instance method situation where you've already got
a constructed object.

I'll go back to my simple example:

	Array.new 3
	Array.new [1,2]

Do you really think that Array.new(3) should result in
[1, 1], by viewing the number 3 as an array of bits?  Or
alternatively should Array.new([1,2]) fail because it
doesn't make sense to allocate [1,2] entries?

Array.new must 'parse' its argument list and act
accordingly. The interface to Array could be:

	Array.new( 3 )
	Array.new_from_arrayish_obj( [1,2] )

so as to avoid the overloading problem but I don't
particularly think this is an improvement.  Array#new
already uses a form of duck typing:

h = {1,2,3,4}
def h.to_ary; to_a; end

a = Array.new h
puts a      # [[1,2],[3,4]]

Array#new doesn't even check to see if something is an instance
of Array but instead tries #to_ary.  If it fails then Array trys
#to_int, and if that doesn't work reports an exception.

My original question was how best to do this with hash-like objects.
David Black suggested #to_hash, which makes a lot of sense but it
might result in slurping up a huge data structure into an in-memory
hash when all you really want to do is look things up by keys.

Based on this thread discussion, it doesn't seem there is an
'obvious' answer for all (or most) situations.
There are a variety of tradeoffs between using #to_hash, trying #[] or
#fetch, testing for #has_key?, or even simply iterating with #each.  All
of those seem marginally better than using #kind_of?(Hash).

Gary Wright