From: "David A. Black" Date: 2005-01-16T06:21:35+09:00 Subject: Re: Setting and getting methods and variables Hi -- On Sun, 16 Jan 2005, erlercw@siu.edu wrote: > Object#instance_variable_set > Object#instance_variable_get > Object#methods > Module#define_method > Module#remove_method > Module#undef_method > > and all the other similar methods suffer from being scattered > through several classes and naming inconsistencies. They sort of have to be scattered through different classes; the instance variable ones belong to every object, as do some of the universal *methods ones (methods, private_methods, etc.), whereas things like instance_methods etc. are for class/module reflection. (I'm a big fan of "classes are just objects" philosophy, but they do sometimes need special equipment :-) > #instance_variable_set is not only noun-verb, the opposite of > most method names, set is also different than define. It is different, though. I don't think one speaks of "defining" an instance variable with a particular value, but rather setting it to a value. Similarly I don't think one speaks of "setting" a method. And once a variable is defined, you can set it repeatedly; they're two different operations. > Also, > what's the difference between remove and undef ? It's not easy > to tell on first glance and the help at ruby-doc.org is a bit > misleading. It's OK for more than one glance to be required for a fairly powerful feature -- the Ruby learning curve is still pretty good [i.e., steep or shallow, depending how you interpret the 'learning curve' metaphor] :-) The description ri gives seems pretty thorough. You should let James Britt know what the problems are at ruby-doc. > The main problem is that it seems like a bunch of hackish > workarounds that were added after the language was designed. > Java needs things like utility classes and long, wordy names, > because it was badly designed. Ruby doesn't need to suffer the > same problems. > > I propose a more streamlined way of changing methods and > instance variables on the fly: treat them like hashes. This > doesn't have to affect the inner workings of Ruby, just the > programmer's interface to Ruby. > > For instance, object_or_class.private_instance_methods should > return a reference to the object or class MethodHash. Do you mean module_or_class? In the general case (i.e., non-Module/Class), objects don't have instance_methods methods, since all of their methods are instance methods (including class methods, if you happen to be a Class). > This > will allow easily adding new methods or getting old methods > without obscure incantations. The same kind of things could be > done with instance and class variables (perhaps with a normal > Hash or VariableHash). > > MethodHash#merge would be an easy way to do advanced things > similar to mixing in modules (although the current method of > actually mixing in modules works fine and should be kept). I like hash-like interfaces in general, but I'm just wondering whether this would create a kind of parallel-universe type system (or at least semantics) and actually complicate the situation. I don't know. > MethodHash#delete would be an easy way to do > Object#remove_method; hash[:method] = nil should also work. I > propose leaving two ways to do Object#undef_method: provide > Object#undef_method (or something with a better name like > #forget_method or #block_method) that will set the method in > the MethodHash to false (conceptually, Ruby looks at the > object's methods first, and false would make the point clear to > Ruby and programmers). This will allow people to figure out > how to block a method just by looking at method names and also > allow a somewhat intuitive way of blocking to those who don't > like memorizing method names. A couple of questions about that: 1. What would happen to the current distinction betweeen #remove_method and #undef_method? 2. If the hash value is set to nil or false -- rather than the key/value being deleted entirely -- what would happen here? def obj.x; end obj.methods[:x] = false obj.methods.keys.include?(:x) # true or false? This would make it hard to do certain types of reflection, I think. (It also seems a bit roundabout to have to do a call to #keys just to get a list of the method names, if I'm getting that right.) > MethodHash#keys would do the same thing as the array-returning > methods (that list methods) do now. > > This would make Ruby much less Java-like (verbose and no nice > features like #[] and #[]= outside of arrays). I think there are some intra-Ruby reasons for some of these things. For example, instance_variable_[gs]et, from what I understand, is deliberately somewhat awkward, as a tangible manifestation of the fact that it isn't generally a good idea to pry into other objects' instance variables. This is an example of what I view as the triumph of balance over symmetry -- something I think Matz is brilliant at. David -- David A. Black dblack@wobblini.net