why the lucky stiff wrote:
figured out a better way to dispatch methods. Hey, let’s let them try.
I was looking over the Kernel methods, thinking about which one’s are
vital and and/or meta in nature. And really it seems like almost all of
them are, which probably accounts for why they are in Kernel to begin
with. They are (v1.8.4):
["==", “===”, “=~”, “id”, “send”, “class”, “clone”, “display”,
“dup”, “eql?”, “equal?”, “extend”, “freeze”, “frozen?”, “hash”, “id”,
“inspect”, “instance_eval”, “instance_of?”, “instance_variable_get”,
“instance_variable_set”, “instance_variables”, “is_a?”, “kind_of?”,
“method”, “methods”, “nil?”, “object_id”, “private_methods”,
“protected_methods”, “public_methods”, “respond_to?”, “send”,
“singleton_methods”, “taint”, “tainted?”, “to_a”, “to_s”, “type”,
“untaint”]
Looking through these, it really becomes hard to say what should stay
and what should go in forming a near empty class. And given their
nature one might be inclined to think that most of these should be
external to the object anyway. I mean, should the class really have the
“right” to override #object_id?
After thinking about this further. I started to wonder if maybe the
foo notation could be a special syntax Ruby would always take as a
method call bound to Kernel, analogous to:
def method_missing( meth, args, &blk )
if md = /^__(.)__$/.match( meth.to_s )
Kernel.instance_method( md[1] ).bind(self).call(*args, &blk)
end
super
end
This example implmentation still allows them to be overridden. Whether
that should be so is debatible, though _why makes a good point. If you
think you can make a better quack than go for it.
Also interesting, If you look as Ruby 1.9 specs you’ll see there is now
a BasicObject that lies behind Object and Kernel. These are the methods
it isolates:
[ “send”, “funcall”, “id”, “==”, “send”, “respond_to?”,
“equal?”, “object_id”]
I’m all for the idea of a BasicObject b/c it will make OpenStruct and
classes of that ilk more standardized and robust. But I was wondering
what if you wanted to make a subclass of BasicObject but there were one
or perhaps a few other Kernel methods you needed to include. Say for
instance you needed #instance_variables. How would you be able to
include that since Kernel is not even in the class hiearchy? Maybe it
isn’t that important, but it doesn’t seem like it should be out the
question.
Of course, we take another step back we see that all of this crops up
b/c the OpenStruct pattern is just too damn nice not use, even though
Hash will usually work just as well. But who wants to do
foo[:a][:b][:c] when they can do foo.a.b.c? Moreover an OpenStruct can
quack like any duck; a hash can’t. But then the little edge problems
arise, b/c an OpenStruct pattern is generally used for something that
can have completely arbitarty keys. And that’s when the Kernel methods
can get in the way, not to mention any other internal methods you might
would like the class to have. So you clear out most of then methods
with BasicObject or BlankSlate or what have you and then some one elses
lib croaks b/c it can’t #dup you object or whatever. Yeah, it can get
nasty.
Okay, I’m starting to rattle on, but one last thought occurs to me:
might the whole issue go away if private and public methods could have
their own separate namespaces? The public method would still be
available privately, but if a specifcally private method of the same
name were defined it would be used when called without a receiver,
rather than the public one. The even for an OpenStruct one could
generally ensure the proper response from vital methods by using
#funcall.
T.