Sean O'Dell wrote: > That's just a confidence issue. I don't care if the object coming in is > broken. I'm not concerned about catching objects which are implemented > improperly; that's actually very rare. If an object had a signature that > said "I am a hash-like object" that would be fine for me. Duck typing and > checking respond_to? are completely inadequate, and it seems like people > argue those points because Ruby offers nothing else and so what are you going > to advocate? It's those two or rolling your own interface identification > system, which I think is cheesy; that sort of functionality should come from > the framework. Okay, I'm trying to sum up this thread as well as test whether my understanding of this whole typing issue in Ruby is more or less correct. --- 1. Ruby _has_ types. It's called classes. In fact, all OO languages which have a class concept (as opposed to some classless OO languages like Self, I think) implement types through classes. All object belong to a certain class. That class is the object's type. 2. However, Ruby does _not_ do type checking for you. This means, method declaration is not like this: def meth(a -> Hash, b -> Array); ...; end Instead it's only like this: def meth(a, b); ...; end And if you want to do type checking, you'll have to code it yourself: def meth(a, b) raise ArgumentError unless a.class == Hash raise ArgumentError unless b.class == Array ... end 3. Ruby also does not tag a variable with type. This means, you don't declare variable's type like this: var a -> Hash var b = Array Instead, you just assign a value to a variable: a = {} b = [] and you can change a variable's value (and thus type) anytime you want by reassigning it. #2 and #3 are perhaps what people miss when they move from C++/Java to Python/Ruby. I don't know whether Ruby will ever have #2 and #3. 4. Static type checking (or static typing?) is #2 and #3, done at compile time. This is what C++ and Java do. Ruby, of course, does not have type checking, much less static type checking. 5. "Duck typing" is basically no typing at all. Due to #2 and #3, we can just pass around any kind of value (object) to any method, and the method will just use that object as it wants. If the method needs to get something out of the object (i.e. "make it quack") then the method will just try to do 'obj.quack'. If the object fails to quack, then it's not the right kind of object. 6. Object#respond_to? is not really related to typing (as in #2 and #3). Its primary usage is to avoid 'obj.quack' to raise NoMethodError, i.e. by checking first whether obj has a quack method. 7. Aside from classes as types, some OO languages (like Java and Perl 6) also have interfaces/protocols as another sort of type checking. Ruby does not have it, and I don't know whether it ever will. The choice is currently to implement your own interface mechanism. Probably by creating an Interface class and its subclasses (and thus creating the interface hierarchy) and then tagging objects with these interfaces, e.g. adding an 'implements' method to an object which will return a list of interface classes that object implements. --- So to do type checking, either: a) use classes, and use Object#kind_of? and Object#class for type checking (as in #2). b) implement an interface mechanism (as in #7). Sean seems to choose b), but reading the other posts, he also seems to be able to control the generation of the incoming objects. Then why not consider a) too? Instead of saying "hey, anything but a hash-like object here is an error" then why not require every incoming object to be a subclass of Hash and say, "raise ArgumentError unless obj.kind_of? Hash". Ruby allows an object (like an empty hash) to be extended with methods, so you can easily wrap object inside a hash and still be able to do type checking with the simple kind_of?(Hash). -- dave