On Mar 1, 2007, at 9:49 PM, dblack / wobblini.net wrote:
> I guess I tend to think in terms of error handling: that is, let
> objects call [], but catch the ones that fail, or the ones that hand
> back nonsense (in the context) values.

Let me make the situation a little more concrete.

I'd like to define a class that accepts the following syntax for
construction:

	A.new
	A.new(1)
	A.new(1,2)
	A.new(3 => 4)
	A.new(1, 3 => 4)
	A.new(1, 2, 3 => 4)

So the arguments to A.new are zero or more objects followed by an
optional hash. I can certainly look for that trailing hash via
(Hash === args.last) but what if I don't want to lock it down to
a Hash?

	tree = RBTree.new
	A.new(1, 2, tree)

I'd like that to work also and I'm sure there are other sorts of
objects that would work just fine (i.e. respond to #fetch/#[], has_key?,
and perhaps is Enumerable). If I use a class based test to discover
if the last argument is an instance of Hash, I'm eliminating those
other possibilities.  I also don't want to use args.last[key] and
catch an exception because that is only useful *after* I've
discovered if an optional final hash-like object has been passed.

I could have different constructors:

	A.new(1)
	A.new_with_hash(1, 1=>2)

but it really isn't as nice, IMHO.

At first I thought I could use respond_to?(:[]) on the last argument,
but as I said in the original post integers and strings will create
a false-positive for a hash-like trailing argument using that test.

Perhaps I'm trying to push the duck-typing too far and should just stick
with testing for Hash but it seems like testing for #fetch gives at  
least
a little more flexibility.

It also seems like it might be nice to encourage a practice of defining
#fetch, #store, and #has_key? for data structures that are 'indexable'.

Gary Wright