I am not entirely sure what you mean, but adding or removing methods from Ruby classes is extremely simple and there are a number of hooks in place that allow you to play with the class definition on inheritance. But here is another example of the power of Ruby metaprogramming. The example is sort of nuts, but something similar is actually used in the Camping microwebframework.
Blah = {
:foo => proc { puts "foo" },
:bar => proc { puts "bar" },
:baz => proc { puts "baz" }
}
def Monkey(method)
klass = Class.new
klass.class_eval do
define_method :shout do
Blah[method].call
end
end
return klass
end
class Chimp < Monkey(:foo)
end
class Gorilla < Monkey(:bar)
end
a = Chimp.new
a.shout # => "foo"
b = Gorilla.new
b.shout # => "bar"
Blah[:foo] = proc { puts "I have changed" }
a.shout # => "I have changed"
Well, except the example you've given isn't really "metaprogramming" in the sense I'm trying to get at. Here's a Python translation which shows why:
def Monkey(word):
class _Monkey(object):
def shout(self):
print word
return _Monkey
class Chimp(Monkey("foo")):
pass
class Gorilla(Monkey("bar")):
pass
c = Chimp()
c.shout() # prints "foo"
g = Gorilla()
g.shout() # prints "bar"
In other words, the Ruby code you've provided is basically a class factory taking advantage of closures. The Python example shows that a bit more clearly.
What I'm looking for is something equivalent to Python's "metaclass" declaration, which lets you completely control the way the class object is created. I've been told by fairly knowledgeable Rubyists that there isn't really an equivalent, and that after-the-fact monkeypatching or factory solutions like yours are the only way to come at the problem in Ruby.
Ruby doesn't have metaclasses, this is true. It won't let you subclass 'class'.
However it will let you subclass 'Module', which is the superclass of Class, and you can use this to achieve similar ends if not quite as elegantly.
The way class methods work wrt to inheritance is a bit different in ruby though, and gives you quite a lot of power to provide special behaviours to subclasses via class methods which can be called in the subclass class definition. The kind of "we provide a DSL for you to use in your class definitions to configure the subclass" tricks which (IIRC) tend to require metaclasses in python, don't require them in ruby.
There is also an 'inherited' class method callback on Class, which you can use to run code whenever a new class inherits from your class. And this can be used to achieve a lot of things that pythonistas might use metaclasses for.
On the whole I think anything possible in one language is possible in the other when it comes to metaprogramming, it's just a matter of how you go about it and how elegant it feels.
Anyway, this setup is in no way different to ruby's super
super("foo")
super("bar")
I really fail to see the point here. What is different?
I simply do not see what the python example shows "a bit more clearly" here. I dont even get where "word" comes from.
Besides, "monkeypatching" is a deragotary term invented by pythonistas who do not understand Ruby or think that by adding complexity you can feel "meta" programming so clearly. In my opinion the metaprogramming demanding people are wanking hippos that continually feel a need to add needless and useless complexity on top of problems and in situations where there simply should not be any of that.
Both ruby and python are way to complicated. Can you believe this? At the same time, both are a LOT more elegant than languages like perl or php. Perl 6 still has not managed to get rid of the useless ; at line ends. They managed to eliminate () around if's.
Wow. I am soooo impressed. In 100 more years Perl 7 will be THE best language arrr!!!
But it is a shame that there are not more good languagesl ike ruby or python, because in fact there simply are not that many good languages existing anyway. It takes so much effort to grow a language....
And yes - both ruby and python are very good languages. The fact that there are idiots using the language who have a loud mouth badmouthing either of these two decent languages is annoying, but one can not do much about it.
For everyone else I recommend reading the "why it does not matter" blog. It really summarizes a lot of why ruby and python fill a very similar ecosystem, behaving like rivals who continually try to point out how incredibly stupid the other language is.
Grow up. Use what you prefer, and end this stupid war.
>> def Monkey(word):
>> class _Monkey(object):
>> def shout(self):
>> print word
>> return _Monkey
Note that Monkey is a function that takes a parameter word. So every invocation of Monkey creates a class that will always .shout() the parameter word.
> Anyway, this setup is in no way different to ruby's super
> super("foo") super("bar")
No.
>> class Chimp(Monkey("foo")):
>> pass
>> class Gorilla(Monkey("bar")):
>> pass
You'll note that these two class definitions create a class Chimp that's descended from a class like _SomeMonkeyThatSaysFoo, and a class Gorilla that's descended from a class like _SomeMonkeyThatSaysBar.
That is what the parent poster has challenged anyone to reproduce in Ruby.
> Grow up. Use what you prefer, and end this stupid war.
Programming language wars are at least as old as the Internet, so the admonition to "Grow up" hold no water in this case.
I could quite reasonably parody your closing statement as: "Grow up. So who cares whether a hammer or celery makes a better tool? Just leave us alone, hammer-users."