Was this what you're looking for (the one based on rcoder's lament on
twitter)?
-- Markus
class A
def foo
"okay!"
end
end
module B
def foo
"not " + super
end
end
module C
def foo
"really " + super
end
end
class X < A
include B
include C
end
class Object
def eigenclass
class << self; self; end
end
end
class Class
def wrap_methods &_
include Module.new &_
end
end
class Person
wrap_methods {
def hello
"Hello"
end
}
end
flanders = Person.new
p flanders.hello # => "Hello"
Person.wrap_methods {
def hello
"#{super}-diddly"
end
}
p flanders.hello
puts (x1 = X.new).foo
X.wrap_methods { def foo;"Who says it's #{super.gsub(/!/,'?')}";end }
X.wrap_methods { def foo;"#{super}\nPersonally, I think it's kind of
cool.";end }
puts X.new.foo
puts x1.foo
x2 = X.new
x2.eigenclass.wrap_methods { def foo;"Ha! #{super.length}"; end }
puts X.new.foo
puts x2.foo
--
You received this message because you are subscribed to the Google Groups "pdxruby" group.
To post to this group, send email to pdx...@googlegroups.com.
To unsubscribe from this group, send email to pdxruby+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/pdxruby?hl=en.
I have to admit, now that I understand this pattern, I find myself
being tempted to use it all over the place. Thankfully, I mostly
refrain from doing so, and when an instance sneaks by, my colleagues
catch in in code review.
It's seriously clever, in a way that I a) enjoy playing with, and b)
don't really like seeing in production code. (Don't even get me
started on method definitions in the eigenclass, or we'll be stuck in
this thread all day.)
--
Lennon Day-Reynolds <rco...@gmail.com>
http://rcoder.net/
The funny thing is, it wasn't originally considered "seriously clever",
it was just the way ruby worked. The functionality was there
specifically to be used in this way and the community (much smaller at
the time, and largely native Japanese speakers) just accepted it as
such.
Then came the rails hordes and, assuming there wasn't a way to do this
already, they invented the myriad alias chain games which for most use
cases appear (to me) to be overly clever reinventions of a preexisting
wheel.
Alias chain games feel like (again, to me) like having variables called
a_1, a_2, a_3, etc. when what you really want is an array, or
product_name, product_quantity, product_price, etc. when you really want
a class. It's simulating a data structure (an array, a class or a
module) by playing with names.
So I guess it's all relative to what you're used to, or at least to what
you're expecting. :)
-- Markus
:A
Look at it this way instead:
class A
def foo
'Really'
end
end
module B
def foo
super + ' just'
end
end
module C
def foo
super + ' fine.'
end
end
class X < A
include B
include C
end
X.new.foo
#=> "Really just fine."
:A
Don't get me wrong: the mechanism makes perfect sense given the
constraints of single-inheritance and the desire to inject additional
functionality via mixins.
In practice, it results in de facto multiple inheritance, with all the
power and problems that entails. Hence my presentation of it as a
"code smell" that has to solve a really critical problem to avoid
getting refactored out of the code. Like any inherited implementation,
it usually has a compositional alternative that, while potentially
more verbose, is also much more clear and less order-dependent.
Truthfully, I really, really love all these little corners and
low-level details of Ruby; it's a big part of what attracted me to the
language 10 years ago, and I will vigorously defend the existence of
such features in the language. That doesn't mean, however, that I want
to see them heavily leveraged in application code in a production
context.
tl;dr:
me: You kids get off my lawn with your eigenclasses and implicit
inheritance chain!
you: Look out, ol' Mr. @rcoder is getting grumpy again...
I'm pretty sure I've never used that pattern in practice, I've never had cause to. So maybe its something that should be avoided in favor of other alternatives.
The real truth of that matter is that if everything looks like a nail, you probably need more tools.
:A
To be fair, multiple inheritance in languages/styles that don't handle
it well. In Haskel you can derive Show, Eq, Ord, etc. till the cows
come home and no one raises an eyebrow.
> Truthfully, I really, really love all these little corners and
> low-level details of Ruby; it's a big part of what attracted me to the
> language 10 years ago, and I will vigorously defend the existence of
> such features in the language. That doesn't mean, however, that I want
> to see them heavily leveraged in application code in a production
> context.
So do you object to the unstructured forms (e.g. alias method chains)
just as strongly? :)
-- M
P.S. By the way, I don't know if I ever thanked you for the original
tweet which inspired the hangman that launched this thread, but I will
now: thank you. It's proved very productive for my purposes (getting
people to think more deeply about the semantics of ruby while having
fun).
True, though Show, Eq, Ord, et. al. don't actually stomp on each
other's method namespaces.
>> Truthfully, I really, really love all these little corners and
>> low-level details of Ruby; it's a big part of what attracted me to the
>> language 10 years ago, and I will vigorously defend the existence of
>> such features in the language. That doesn't mean, however, that I want
>> to see them heavily leveraged in application code in a production
>> context.
>
> So do you object to the unstructured forms (e.g. alias method chains)
> just as strongly? :)
More so. Core language features are at least guaranteed to be
available in any runtime context. I hate seeing ActiveSupport-isms
sneak into non-Rails code.
> P.S. By the way, I don't know if I ever thanked you for the original
> tweet which inspired the hangman that launched this thread, but I will
> now: thank you. It's proved very productive for my purposes (getting
> people to think more deeply about the semantics of ruby while having
> fun).
You're quite welcome. I've always been a fan of the hangman puzzles.