--- "David A. Black" <dblack / wobblini.net> wrote: > Hi -- > > On Wed, 17 Aug 2005, Lyndon Samson wrote: > > > I'd say prototype means no classes, that is create an > Object from another ( > > Including Object ) and munge it at will, add/remove/change > behaviour or > > variables. > > > > I wonder if Ruby2 really needs classes? They seem to be > de-emphasised in the > > Ruby world ( the one eyed duck is king ) and the other use > for class like > > concept is interfaces which there seems to be alot of > hostility towards. > > Duck typing co-exists peacefully with the existence of > classes -- or > at least it can. The biggest problem I've seen over the > years in the > matter of understanding Ruby's particular class/prototype > blend is the > "class == type" fallacy. Using the term "type" by itself instead of something else helps perpetuate this fallacy. Object#type is a synonym of Object#class. > There are two common consequences > of this > misunderstanding. First, it leads to the creation of new > ways of > referring to type (like "duck type", which is redundant and > superfluous). Your definition of "type" is quite different from the definition I gave of "duck type". Your definition of the "type" of an object is the "sum of all of its capabilities" - i.e. ALL of the methods it responds to. I think that definition is about as relevant to ruby and duck-typing as class is. This definition of "type" is close to a java "interface", but is more restrictive because it represents the entire behavior of an object where an interface may be just a subset. From your definition of "type", an object only has one "type" for any given state of that object. The definition I gave of "duck type" allows an object to have many "duck types" at a time. It all depends on who is using the object. Each usage of an object may have a different view of what the "duck type" is. My definition of "duck type" really refers to the usage of an object not the object itself. The most common usage would be as a method argument, but it could also be applied to variables, using return values from methods, etc. I think the broadest definition I could give would be that a "duck type" of a given usage of an object is described by what capabilities are used of that object in that context. This includes what methods that object needs to respond to, the arity of those methods, the "duck type" of the arguments for those methods, and the "duck type" of what is returned from those methods. Take a look at the original definition of duck-typing given by Dave Thomas. Here is the example he gave: | When I write | | fred << "dog" | | in Ruby, I don't care whether fred is a String, a File, or an | Array In this context, the "duck type" of fred is something that reponds to <<(aString). By your definition of "type" being "the sum of all of its capabilities", you'd have to pick what "type" fred is - String-like, File-like, or Array-like. If you said that fred was something File/IO-like you could use an IO, File, or StringIO for fred, but not a String or Array because they don't have the same capabilities. The downside of typing your arguments using this "duck type" definition is that you have to pick what methods you want to use up front and document what you are using (or may use). If you later want to change the implementation to use other methods, you'll need to change the docs and possibly break callers using objects under the original duck-type. With the "type" definition you have, this downside doesn't exist. A method has much more freedom of choice. For example, in the above, you could change it to fred.write("dog") later down the road if you limited fred to be anything IO-like. So, if you want to give maximum freedom of choice to the caller, you should describe your arguments with duck-types and if you want to give maximum freedom of choice to the method implementor, you should describe your arguments with David's definition of "type". > Second, and sort of the opposite, it leads to > the > impression that there's something arcane, wizardly, "evil", > and/or > just plain bad about modifying objects during runtime so that > their > type is not the same as the type they started out with. The biggest problem I have with being able to add/remove/modify methods of an object (using a meta class or directly in the object's class) is the future of optimization in Ruby. Adding methods may not cause too much of an issue, but modifying them sure could. For example: i = 0 i += 1 In this case, Ruby could recognize that i is always a Fixnum (or a Bignum depending on how smart it is). If it knew exactly what "+" was for a Fixnum, it would be able to in-line that C call (in this hypothetical Ruby compiler). Unfortunately, "+" could be anything since it can change at run-time. To me, this is an extreme case of methods that mutate the object. If one thinks #reverse! is bad compared to #reverse (which I don't) because it mutates the object rather than returning a new one, being able to modify the methods of an object (or objects if for a whole class) should seem hideous. Personally, I don't think adding methods are too bad, but being able to remove or modify methods doesn't seem like a good idea or serve much use. I'd rather see a new object be created that have these methods removed/modified instead. ____________________________________________________ Start your day with Yahoo! - make it your home page http://www.yahoo.com/r/hs