[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Extending an Instance only Once

Gavin Kistner

5/17/2005 4:10:00 AM

I have a method that requires that the arguments passed to it have
been in-mixed with a module. Currently, my code looks like this:

def my_method( the_obj )
the_obj.extend( MyModule ) unless the_obj.inherits_from?
( MyModule )
end

class Object
def selfclass
class << self; self; end
end

# Return true if the instance inherits from the supplied
_class_or_module_.
def inherits_from?( class_or_module )
self.class.ancestors.include?( class_or_module ) or
self.selfclass.ancestors.include?( class_or_module )
end
end


Is there a better way to do that? (I'm testing if the object inherits
from a class which was extended by the module, OR if the instance
itself was already extended.) Does it end up being cheaper/faster to
just always re-extend the instance? (What happens if you extend both
the class and an instance of that class? Does the singleton class
take precedence?)

--
"When I am working on a problem I never think about beauty. I only
think about how to solve the problem. But when I have finished, if
the solution is not beautiful, I know it is wrong."
- R. Buckminster Fuller

20 Answers

dblack

5/17/2005 11:34:00 AM

0

Gavin Kistner

5/17/2005 12:41:00 PM

0

On May 17, 2005, at 5:34 AM, David A. Black wrote:
> Unless I'm missing something, #is_a? would do it.

Nope, apparently it was I who missed something. Thanks :)


> The singleton class takes precedence in the sense that it comes
> earlier in the method lookup path. (I'm assuming that you mean mixing
> the module into the class, not MyClass.extend(MyMod), which would not
> affect the class's instances.)

Indeed, that is what I meant.
module M; end
class Foo; end
class Bar; include M; end
f = Foo.new
b = Bar.new
f.is_a?( M ) #=> true
b.is_a?( M ) #=> true

Yay :)



> Overall, I'm tempted to say that if you're extending a single object
> multiple times with the same module, there's something not quite right
> in the program flow. But I doubt it's going to slow things down very
> much (but I haven't benchmarked it).

Yeah, I could certainly realize _some_ performance gain by ensuring
that the consumer of the class ensures that they pre-mix any
instances which are handed to the method. But I'm going for uber-
friendliness, sort of auto-duck-typing. ("You say you don't quack
like a duck? Here, let me strap this bill onto your head.")

When I get to benchmarking I'll check it out, but I think it should
be fine, since this method is run only a few times during setup, and
not during the cpu-intensive phase.

Peter

5/17/2005 1:01:00 PM

0

Gavin Kistner

5/17/2005 1:46:00 PM

0

On May 17, 2005, at 7:01 AM, Peter wrote:
>> I have a method that requires that the arguments passed to it have
>> been in-mixed with a module. Currently, my code looks like this:
>>
>> def my_method( the_obj )
>> the_obj.extend( MyModule ) unless the_obj.inherits_from?
>> ( MyModule )
>> end
> This does not proof the check is actually done, but in the source
> you can see that check is actually there without doubt.
>
> The same goes for Object#extend because it is implemented as an
> include in the singleton class (or selfclass as some people
> prefer :) which obeys the same rules as includes in regular
> classes. So no need to check this yourself!

Hrm...I see code that looks like that's what's going on inside of
class.c, but apparently it is faster to test myself:


require 'benchmark'
include Benchmark

module M; end
class Bar < Array; end
class Foo < Bar; end

n = 500000
bm(15){ |x|
f = Foo.new
x.report( "Always Extend" ){
n.times{
x.extend( M )
}
}

f = Foo.new
x.report( "Test First" ){
n.times{
x.extend( M ) unless x.is_a?( M )
}
}
}

user system total real
Always Extend 1.610000 0.010000 1.620000 ( 1.983911)
Test First 0.730000 0.000000 0.730000 ( 0.745857)


Is there a flaw with my test above?

peter.vanbroekhoven

5/17/2005 3:46:00 PM

0

> Hrm...I see code that looks like that's what's going on inside of
> class.c, but apparently it is faster to test myself:
>
>
> require 'benchmark'
> include Benchmark
>
> module M; end
> class Bar < Array; end
> class Foo < Bar; end
>
> n = 500000
> bm(15){ |x|
> f = Foo.new
> x.report( "Always Extend" ){
> n.times{
> x.extend( M )
^^^
> }
> }
>
> f = Foo.new
> x.report( "Test First" ){
> n.times{
> x.extend( M ) unless x.is_a?( M )
^^^ ^^^
> }
> }
> }
>
> user system total real
> Always Extend 1.610000 0.010000 1.620000 ( 1.983911)
> Test First 0.730000 0.000000 0.730000 ( 0.745857)
>
>
> Is there a flaw with my test above?

You made a typo in your tests (x should be replaced with f), but it
does not influence the result. The only explanation I have is that the
test used in include is more complicated than the one used in #is_a?
because include doesn't only check the module passed as parameter to
#include, it checks modules included in that module too. I guess even
when there are no such modules, there is still some overhead (it's not
exactly a straightforward algorithm). But unless you really intend to
do 500000 extends in a row, I don't think that is really a problem...
:-)

Peter

Christoph R.

5/17/2005 8:20:00 PM

0

peter.vanbroekhoven@gmail.com schrieb:

>You made a typo in your tests (x should be replaced with f), but it
>does not influence the result. The only explanation I have is that the
>test used in include is more complicated than the one used in #is_a?
>because include doesn't only check the module passed as parameter to
>#include, it checks modules included in that module too. I guess even
>when there are no such modules, there is still some overhead (it's not
>exactly a straightforward algorithm). But unless you really intend to
>do 500000 extends in a row, I don't think that is really a problem...
>:-)
>
>
The explanation is probably simpler - f.extend(M) makes hook calls to
M.extend_object(f) and M.extended(f) - M.extend_object(f) probably
tests if f.is_a?(M) a - this means its 4 method calls, versus 1 call +
1 if statement ...
you'll probably find a much smaller difference calling
M.extend_object(f) only.


---
require 'benchmark'
include Benchmark

module M
class Bar < Array; end
class Foo < Bar; end

n = 500000
bm(15){ |x|
f = Foo.new
x.report( "Test First" ){
n.times{
extend_object( f ) unless f.is_a?( M )
}
}
f = Foo.new
x.report( "Always Extend" ){
n.times{
extend_object( f )
}
}
}
end
---

/Christoph

>Peter
>
>
>
>
>



peter.vanbroekhoven

5/18/2005 12:27:00 AM

0

Christoph wrote:

> The explanation is probably simpler - f.extend(M) makes hook calls
to
> M.extend_object(f) and M.extended(f) - M.extend_object(f) probably
> tests if f.is_a?(M) a - this means its 4 method calls, versus 1 call
+
> 1 if statement ...
> you'll probably find a much smaller difference calling
> M.extend_object(f) only.

You're right, of course. I would have noticed that had I actually taken
a look at the code instead of stating things from memory.

M.extend_object(f) doesn't call f.is_a?(M) though; module inclusion
uses its own specialized check. What surprised me a bit though is that
M.extended(f) is called each time, even when f is already extended with
M and is hence not extended again. We could save an extra method call
there (unless people rely on its being called every time Object#extend
is called) and get it down to 2 calls vs 1 call + 1 if statement.

Peter

Blackheart

9/16/2013 11:26:00 PM

0

On Monday, September 16, 2013 5:17:22 PM UTC-4, mattc wrote:
> rehlow <matt.strehlow> wrote in
>
> news:88b957a0-b8c2-4ce5-b06e-91911b73b8d1@googlegroups.com:
>
>
>
> > On Monday, September 16, 2013 1:29:14 AM UTC-5, mattc wrote:
>
> >> Wannnnnnnttt...
>
> >>
>
> >>
>
> >>
>
> >> http://www.games-workshop.com/gws/catalog/productD...
>
> >>
>
> >> catId=cat440161a&prodId=prod2160196a
>
> >
>
> > The price on this one is so I just won the lottery or else forget
>
> > about it that I don't really care, but looking at some of the other
>
> > 1-clicks I feel they are convincing me to never start another army. I
>
> > look at what I can get for $400 or $500 and think is that it? If I
>
> > knew from the get-go how much it would take to get a really nice sized
>
> > collection I may have never started instead of slowly collecting over
>
> > many years. Oh well, I have plenty of unpainted models as it is.
>
> >
>
> > Later,
>
> > ~Rehlow
>
>

I already have like 6 companies worth of Space Marine infantry...

>
>
>
> Yeah.
>
> I'm rapidly approaching a milestone birthday and was thinking of picking up
>
> a new army to mark the occasion.
>
>

Do it, but be smart about it...

>
> Worked out what I wanted, priced it up and was basically gutted by the
>
> cost.
>
>
>
> I'm now caught between buying it and forever knowing I spent THAT much on
>
> figures in one go, or cutting back, or not buying at all and always knowing
>
> I didn't get myself what I wanted.
>
>

Here's an idea. Take the money for that... Set it aside into something that draws some interest. Get a unit. Put it together, paint it etc. Make it look good. Only when that unit is done do you dip into that money you set aside to get the next unit. Get it off the second hand market if you can (but don't buy anything that's shit you know?), get it from a discounter. Whatever. What have you done? You've given yourself the gift that keeps on giving.

>
>
>
> Oh, and I have my ex trying to get her hand back into my wallet, so if I do
>
> buy myself the army, it will have to be concealed from any of the people
>
> linking her and I.

Dude... she's your ex. You should have absolutely no fucks to give about the bitch.

Matt C

9/17/2013 9:28:00 PM

0

Blackheart <blackheart666_2000@yahoo.com> wrote in
news:d4f92a4e-c5cc-46af-b41d-a43de4760e37@googlegroups.com:

> On Monday, September 16, 2013 5:17:22 PM UTC-4, mattc wrote:
>> rehlow <matt.strehlow> wrote in
>>
>> news:88b957a0-b8c2-4ce5-b06e-91911b73b8d1@googlegroups.com:
>>
>>
>>
>> > On Monday, September 16, 2013 1:29:14 AM UTC-5, mattc wrote:
>>
>> >> Wannnnnnnttt...
>>
>> >>
>>
>> >>
>>
>> >>
>>
>> >> http://www.games-workshop.com/gws/catalog/productD...
>>
>> >>
>>
>> >> catId=cat440161a&prodId=prod2160196a
>>
>> >
>>
>> > The price on this one is so I just won the lottery or else forget
>>
>> > about it that I don't really care, but looking at some of the other
>>
>> > 1-clicks I feel they are convincing me to never start another army.
>> > I
>>
>> > look at what I can get for $400 or $500 and think is that it? If I
>>
>> > knew from the get-go how much it would take to get a really nice
>> > sized
>>
>> > collection I may have never started instead of slowly collecting
>> > over
>>
>> > many years. Oh well, I have plenty of unpainted models as it is.
>>
>> >
>>
>> > Later,
>>
>> > ~Rehlow
>>
>>
>
> I already have like 6 companies worth of Space Marine infantry...
>
>>
>>
>>
>> Yeah.
>>
>> I'm rapidly approaching a milestone birthday and was thinking of
>> picking
> up
>>
>> a new army to mark the occasion.
>>
>>
>
> Do it, but be smart about it...
>
>>
>> Worked out what I wanted, priced it up and was basically gutted by
>> the
>>
>> cost.
>>
>>
>>
>> I'm now caught between buying it and forever knowing I spent THAT
>> much on
>
>>
>> figures in one go, or cutting back, or not buying at all and always
>> knowi
> ng
>>
>> I didn't get myself what I wanted.
>>
>>
>
> Here's an idea. Take the money for that... Set it aside into something
> that draws some interest. Get a unit. Put it together, paint it etc.
> Make it look good. Only when that unit is done do you dip into that
> money you set aside to get the next unit. Get it off the second hand
> market if you can (but don't buy anything that's shit you know?), get
> it from a discounter. Whatever. What have you done? You've given
> yourself the gift that keeps on giving.
>
>>
>>
>>
>> Oh, and I have my ex trying to get her hand back into my wallet, so
>> if I
> do
>>
>> buy myself the army, it will have to be concealed from any of the
>> people
>
>>
>> linking her and I.
>
> Dude... she's your ex. You should have absolutely no fucks to give
> about the bitch.


I've already got a WoC Khornate army. The current thinking is add a
Nurgle army.

I've got a lot of FB and 40K, and quite a bit of it has some kind of
meaning for me - even if it's just "oh, yeah, I bought that / those
when..."

If I do it, it'll be a one-hit job: all at the same time.
It's getting close to the end of the year and I if I don't take my
holiday days I lose them at New Year's. I've booked off the week before
and the week after my birthday. The temptation is to order the figures
to arrive well before then and have a go at a building and painting
project over those 2 weeks.


Insane Ranter

9/19/2013 12:31:00 AM

0

Do they offer a payment plan?