From: Gregory Seidman Date: 2007-01-02T06:36:24+09:00 Subject: Re: Little Things On Tue, Jan 02, 2007 at 12:04:35AM +0900, Trans wrote: } Dave Thomas wrote: } > I wonder: is it a mistake to think of it as a class at all? Sure, it } > had a 'class' somewhere in its background, but is potentially moved } > on a lot since then. In a way, it's move analogous to a meta-binding, } > as it's the execution environment of an object. So, just to get the } > creative juices flowing, and in the spirit of brainstorming, how about [...] The only way in which a class and a module differ is that you can create an instance of a class. Current Ruby 1.8.5 will not let you call #new on a singleton class, so one could argue that it's more a module than a class, remembering that Class subclasses Module. It is, however, at least a module. It is very important that it can be treated as a module, i.e. responds to various methods defined in Module. I'd claim that #include and #define_method are the two most important of those. } Seems to me that 80% of the time we want to use the "singleton class" } with class_eval. Expressions like "singleton_class.class_eval" are } rather redundant and long winded (IMHO). So maybe another single term } for this, along the lines of what you're saying, would be better. } Looking at Phrogz' wiki page of names I came up with: } } customize do } ... } end } } Then the class could be called the 'customization'. Ie. the above being } equvalent to: } } customization.class_eval do } ... } end If I hadn't had occasion to do significant metaprogramming and was looking at this, I'd agree with you that this is nice. As it is, there are really only four things I do to interact with the singleton class, in order of frequency of use: 1) include a module 2) define a method 3) alias a method 4) remove a method Now, #1 is served by Object#extend and doesn't require explicit access to the singleton class at all. With #2, 99% of the time I use #define_method, and the only time I don't is when I need to define a block-accepting method. (Actually, I use send(:define_method, ...) because #define_method is private. Could we make #define_method public for all singleton classes, please? How about a SingletonClass subclass of Class, or possibly module, that makes it public?) I actually need #3 and #4 vanishingly rarely, and most of the time it makes more sense to do it in a module anyway which can be included with extend. I just realized I forgot attr_accessor and friends, but I'd be inclined to use #send (or #funcall) with that as well. What I'm saying, though, is that if I had #customize and #customization (and #define_method were public for singleton classes), I'd still do something like this (note: contrived example): def setup_hashed_attributes(obj, hash) if attrs = obj.instance_variable_get(:@hashed_attributes) attrs.merge(hash) else obj.instance_variable_set(:@hashed_attributes, hash.dup) end singleton = obj.customization singleton.send(:attr_reader, :hashed_attributes) hash.keys.each { |k| singleton.define_method(k) { @hashed_attributes[k] } singleton.define_method("#{k}=") { |v| @hashed_attributes[k] = v } } end ...rather than the equivalent... def setup_hashed_attributes(obj, hash) if attrs = obj.instance_variable_get(:@hashed_attributes) attrs.merge(hash) else obj.instance_variable_set(:@hashed_attributes, hash.dup) end obj.customize { attr_reader :hashed_attributes hash.keys.each { |k| define_method(k) { @hashed_attributes[k] } define_method("#{k}=") { |v| @hashed_attributes[k] = v } } } end I just like how the first one reads. The first one says, "I am messing with an object's capabilities by poking at its instance variables and adding methods to it." The second one says, "I am reopening a class and adding methods to it after poking at an instance variable." } T. --Greg