12 Mar, 2010, Deimos wrote in the 1st comment:
Votes: 0
creature = Creature.new()
creature.extend( Vampiric )
# some time passes
creature.remove( Vampiric ) # doesn't work - how do I do it?

I've sifted through a lot of docs, but I can't find a way to do this, or if it's even possible.
12 Mar, 2010, Runter wrote in the 2nd comment:
Votes: 0
Deimos said:
creature = Creature.new()
creature.extend( Vampiric )
# some time passes
creature.remove( Vampiric ) # doesn't work - how do I do it?

I've sifted through a lot of docs, but I can't find a way to do this, or if it's even possible.


There is no remove facility in Object. I'm not even sure if this is possible short of reconstructing Creature. Maybe the undef keyword? But this seems to be like a hack anyways. I dunno. This isn't have I've seen extend used in the past. :p It's always been for throw away purposes.
12 Mar, 2010, David Haley wrote in the 3rd comment:
Votes: 0
Why are you trying to do this? (Assuming that this is an ok sort of 'why' and not a bad sort of 'why'. And no, that's not sarcastic. I just don't want to waste your or, well, frankly my time.)
12 Mar, 2010, Deimos wrote in the 4th comment:
Votes: 0
Runter said:
There is no remove facility in Object. I'm not even sure if this is possible short of reconstructing Creature. Maybe the undef keyword? But this seems to be like a hack anyways. I dunno. This isn't have I've seen extend used in the past. :p It's always been for throw away purposes.

Not how you've seen it used in the past? How else do you mixin dynamically? This is the only way I've come across in my reading. Keep in mind that I'm a complete newbie to the language.

And yeah, my alternative was to recreate creature sans the Vampiric module. I just didn't want to resort to that without finding out whether there was a better/easier way of doing it.

BTW, this isn't for implementation or anything, I'm just using familiar concepts to learn my way around the language right now.
12 Mar, 2010, David Haley wrote in the 5th comment:
Votes: 0
I'm not sure if you chose to ignore my question, but I'll add this as additional information to why I asked it. You are asking if there is a "better/easier way of doing it". It would be helpful to know what you are trying to do and why in order to answer the question of how to do it better. If you do not wish to discuss this, it would be polite to inform me so that again no time is wasted.
12 Mar, 2010, Deimos wrote in the 6th comment:
Votes: 0
David Haley said:
I'm not sure if you chose to ignore my question, but I'll add this as additional information to why I asked it. You are asking if there is a "better/easier way of doing it". It would be helpful to know what you are trying to do and why in order to answer the question of how to do it better. If you do not wish to discuss this, it would be polite to inform me so that again no time is wasted.

I did choose to ignore it, because you seem to want to critique my choice of design or something. Had I wanted opinions on whether my design could be improved I would have posted in the coding & design forum. I'm posting in the Ruby forum because I don't care about design. I'm simply using familiar concepts and skeleton classes to help me learn the language syntax, constructs, and capabilities.
12 Mar, 2010, Runter wrote in the 7th comment:
Votes: 0
Deimos said:
Runter said:
There is no remove facility in Object. I'm not even sure if this is possible short of reconstructing Creature. Maybe the undef keyword? But this seems to be like a hack anyways. I dunno. This isn't have I've seen extend used in the past. :p It's always been for throw away purposes.

Not how you've seen it used in the past? How else do you mixin dynamically? This is the only way I've come across in my reading. Keep in mind that I'm a complete newbie to the language.

And yeah, my alternative was to recreate creature sans the Vampiric module. I just didn't want to resort to that without finding out whether there was a better/easier way of doing it.

BTW, this isn't for implementation or anything, I'm just using familiar concepts to learn my way around the language right now.


Well, extend is used to grant a specific instance of a class functionality. Typically I've seen this used for throw away purposes. I.e., giving an object a property on the fly and disposing of the object, not affecting the perhaps countless other objects of the same type.

To mix-in modules you use include. Ruby doesn't provide for multiple inheritance, per se. These apply to all instances of a class, though. It appears what you are trying to do is make a player become a vampire without necessarily defining that mixin'd class. In my opinion, you should mix in all possibilities and build their interfaces. Regardless if the player is a vampire or not atm if the chance is there go ahead and bake in the interface which may not be accessible. This can give you a clear way of how multiple interfaces should mesh together anyways. (Assuming you have more than vampire state you'd like to mix-in.)
12 Mar, 2010, David Haley wrote in the 8th comment:
Votes: 0
I have little interest in critiquing your design other than to explore improvements for everybody to learn from (including myself). To this goal I am trying to answer the question (that you later posed yourself) of whether some task can be solved in a better/easier way. If that means a critique of your design to you, well, I guess so, but I'm not sure how else to provide a better way without saying that the current way is, well, not the better one. In any case, it's very difficult to answer your question without knowing why we're doing this. Anyhow, I'll stop here unless you want to discuss things, because you seem to be taking offense. :shrug:
12 Mar, 2010, Deimos wrote in the 9th comment:
Votes: 0
Runter said:
Well, extend is used to grant a specific instance of a class functionality. Typically I've seen this used for throw away purposes. I.e., giving an object a property on the fly and disposing of the object, not affecting the perhaps countless other objects of the same type.

To mix-in modules you use include. Ruby doesn't provide for multiple inheritance, per se. These apply to all instances of a class, though. It appears what you are trying to do is make a player become a vampire without necessarily defining that mixin'd class. In my opinion, you should mix in all possibilities and build their interfaces. Regardless if the player is a vampire or not atm if the chance is there go ahead and bake in the interface which may not be accessible. This can give you a clear way of how multiple interfaces should mesh together anyways. (Assuming you have more than vampire state you'd like to mix-in.)

Yeah, I wasn't trying to use it for multiple inheritance here, though. Temporary afflictions don't lend themselves well to inheritance at all, because it's a "has a" rather than an "is a" relationship. I just ran across the extend functionality in some docs and thought it would be cool if you could just extend an object with something like a vampiric module, rather than compositioning an instance into the creature in some kind of "afflictions" collection.
12 Mar, 2010, Runter wrote in the 10th comment:
Votes: 0
Yeah, that's kinda the thing though. It's very similar to multiple inheritance to use module mix-ins. In fact..
module Cat
def mew; "Mew!"; end
end

module Lion
def roar; "Roar!"; end
end

class LionCat < Lion;
include Cat
def RoarMew; "Roarmew!"; end
end

kitty = LionCat.new
kitty.roar # => "Roar!"
kitty.mew # => "Mew!"
kitty.RoarMew # => "Roarmew!"
kitty.ancestors.inspect # Lion and Cat are both shown as ancestors.
12 Mar, 2010, Tyche wrote in the 11th comment:
Votes: 0
Deimos said:
creature = Creature.new()
creature.extend( Vampiric )
# some time passes
creature.remove( Vampiric ) # doesn't work - how do I do it?

I've sifted through a lot of docs, but I can't find a way to do this, or if it's even possible.


No… well yes.

require 'inline'

class Object
inline(:C) do |builder|
builder.c <<-EOC
void unextend(VALUE module) {
VALUE klass = rb_singleton_class(self);
VALUE prev_klass = Qnil;
while (klass) {
if (klass == module || RCLASS(klass)->m_tbl == RCLASS(module)->m_tbl) {
RCLASS(prev_klass)->super = RCLASS(klass)->super;
rb_clear_cache();
return;
}
prev_klass = klass;
klass = RCLASS(klass)->super;
}
}
EOC
end
end

module Vampiric
def bite
puts "chomp"
end
end

class Creature
end

a = Creature.new
begin
a.bite
rescue
puts "no bite"
end
a.extend Vampiric
a.bite
a.unextend Vampiric
begin
a.bite
rescue
puts "no bite"
end


I have no clue why there is no unextend. Maybe it's dangerous.

When you extend an object with a module you create a virtual metaclass and then the module becomes a proxy class just above that metaclass in the inheritance chain.

a = Creature.new

a <— Creature <— Object

a.extend Vampiric

a <— `a (metaclass) <— Vampiric (proxy) <— Creature <— Object

a.unextend Vampiric

a <— `a (metaclass) <— Creature <— Object
12 Mar, 2010, Deimos wrote in the 12th comment:
Votes: 0
Hmm, thanks Tyche. I think it's a shame that Ruby hasn't implemented this functionality yet. It seems that I'm not the only one who went looking for it. If what the one guy says is true, the arguments against it at the implementor's meeting were performance-related (blargh).

Anyway, thanks for your help guys.
12 Mar, 2010, Runter wrote in the 13th comment:
Votes: 0
That code doesn't work for 1.9.x.

For a pure ruby solution you could do something like:

module One;  def roar; p "Roar!"; end; end
class Two; end

c = Two.new.extend(One).roar
c = c.dup

begin
c.roar
rescue
p "Fail."
end



Could probably wrap it some way around a method in Object to add unextend to everything.
12 Mar, 2010, Tyche wrote in the 14th comment:
Votes: 0
Deimos said:
Hmm, thanks Tyche. I think it's a shame that Ruby hasn't implemented this functionality yet. It seems that I'm not the only one who went looking for it. If what the one guy says is true, the arguments against it at the implementor's meeting were performance-related (blargh).

Anyway, thanks for your help guys.


I see their routine is better as it handles..
class A
include B
end

And also returns True or False depending on whether it worked or not.

The one I posted only handled..

class<<obj
include B
end
which is equivalent to..
obj.extend B

Of course the latter is the temporary per object behavior one is interested in.

Now it doesn't really matter whether Ruby implements it in the MRI core or not.
That's why people write extensions. ;-)
12 Mar, 2010, David Haley wrote in the 15th comment:
Votes: 0
Generally when languages don't implement functionality (after having thought about it) it's because it's considered that the costs outweigh the gains. For example, this is why many languages no longer support multiple inheritance. So, when somebody shows up asking "how do I do this with multiple inheritance", the response is "you shouldn't be using multiple inheritance". :smile:

An example that comes to mind is people asking for a function to determine the size of a table (map) in Lua. The Lua authors point out that it introduces costs in terms of implementation, and most of the time you don't want to know the size of the table but rather simply if it's empty or not. Personally, I'm quite happy when language implementers think about the performance consequences of adding features only useful for questionable designs or of goals that can be easily achieved otherwise.
12 Mar, 2010, Runter wrote in the 16th comment:
Votes: 0
Oh, I found a gem that implements this behavior.

>sudo gem install un 
Successfully installed un-1.0.1
1 gem installed
Installing ri documentation for un-1.0.1…
Updating class cache with 1689 classes…
Installing RDoc documentation for un-1.0.1…


require 'un'

module One; def roar; p "Roar!"; end; end
class Two; end

c = Two.new.extend(One).roar
c.unextend(One)

begin
c.roar
rescue
p "Fail."
end


This implements include/uninclude as well as extend/unextend. It's 1.9.x compliant as well.

Quote
ruby testunextend2.rb
"Roar!"
"Fail."
12 Mar, 2010, Deimos wrote in the 17th comment:
Votes: 0
@Runter:
I read about that solution, too, but it would seem to break if you extended the object with more than one module, and only wanted to remove one of them.

Edit: Err… I was referring to your previous post about dup, not the gem-related post. Incidentally, that gem looks to be exactly what I was looking for, thanks!
13 Mar, 2010, Tyche wrote in the 18th comment:
Votes: 0
David Haley said:
Generally when languages don't implement functionality (after having thought about it) it's because it's considered that the costs outweigh the gains.


False.

David Haley said:
For example, this is why many languages no longer support multiple inheritance.


False.

David Haley said:
So, when somebody shows up asking "how do I do this with multiple inheritance", the response is "you shouldn't be using multiple inheritance". :smile:


False.

David Haley said:
…snipped LUA babble…


Don't care.

There's ample space and opportunity in other fora here to parade your stupid hobby horses, debate your off-topic comments, ignorant premises and false assumptions.
13 Mar, 2010, David Haley wrote in the 19th comment:
Votes: 0
Thanks for backing up your words of wisdom with well thought-out and accurate justification, as always, my grumpy ol' pal.

Amusingly enough, the Lua bit is actually one of the most common criticisms levied against the language. So it's hardly parading a hobby horse. But then again, had you stopped to actually think about anything or (gasp) learn what you were talking about, you'd have noted that.

Ah well.

EDIT: btw I'd be extremely curious to hear your justification of multiple inheritance, and why all these new languages that explicitly chose to not support it should in fact support it.
I'd also be curious to hear what other reasons language developers use when deciding to not include a feature. Maybe they think it'd make people grumpy.
13 Mar, 2010, tphegley wrote in the 20th comment:
Votes: 0
I think his point is that if someone is asking a ruby question, a lua answer isn't really wanted. I know your 'snippet lua babble' wasn't really an answer rather a musing, but oh well.

You often talk about Lua in the Ruby forums, hence his grumpiness, among other things.
0.0/23