[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

Repost: singleton methods vs. class instance vars

Peter Lacey

1/4/2006 5:32:00 PM

Hi,

Please excuse me if this message was already delivered. I'm sending
it again as I suspect something went wrong with my original post
because it didn't get cross-posted to comp.lang.ruby and there were
no replies from a typically very helpful audience.

Pete

Original message:

I'm liberally helping myself to some of the ActiveRecord code. In
this code there are a handful of class methods that dynamically
create singleton methods to override the base methods. A simplified
version follows:

class SingletonBase
class << self
def table_name
reset_table_name
end

def reset_table_name
puts "reset_table_name called"
name = self.name
sing = class << self; self; end
sing.class_eval "def table_name; #{name.inspect}; end"
name
end
end
end

(I hope that simplifying the code didn't remove anything of importance.)

In this code the first time SingletonBase#table_name is called it
calls SingletonBase#reset_table_name. reset_table_name in turn
creates a singleton class and adds a method that overrides table_name
to return what was just calculated.

Fine.

But my question is, is there any reason to prefer this method over
using class instance variables, which seem a little clearer and
simpler? Ala:

class InstanceBase
class << self
def table_name
@table_name || reset_table_name
end

def reset_table_name
puts "reset_table_name called"
@table_name = self.name
end
end
end

If both of these classes are exercised as follows, the results are
comparable:

class Sub_SingletonBase1 < SingletonBase
p table_name
p table_name
end

class Sub_SingletonBase2 < SingletonBase
p table_name
p table_name
end

class Sub_InstanceBase1 < InstanceBase
p table_name
p table_name
end

class Sub_InstanceBase2 < InstanceBase
p table_name
p table_name
end

Output:

reset_table_name called
"Sub_SingletonBase1"
"Sub_SingletonBase1"

reset_table_name called
"Sub_SingletonBase2"
"Sub_SingletonBase2"

reset_table_name called
"Sub_InstanceBase1"
"Sub_InstanceBase1"

reset_table_name called
"Sub_InstanceBase2"
"Sub_InstanceBase2"

Note that there are class methods in ActiveRecord that _do_ use class
instance variables, but not all. In particular for setting/getting
table_name, primary_key, inheritance_column, and sequence_name,
basically everything that can be set by the user. So, what benefit
is derived from using virtual/meta/singleton/eigen-classes over class
instance variables?

Regards,
Pete




44 Answers

konsu

1/4/2006 8:21:00 PM

0

hello,

apparently ruby as most other languages has more than one way to
express the same thing. i myself see no advantage of the code in active
record that you posted and your code. except for the active record code
is faster than yours because it does not check any variables at all
when evaluating the table_name method.

konstantin

ptkwt

1/4/2006 8:28:00 PM

0

In article <1136406073.177747.137450@g43g2000cwa.googlegroups.com>,
ako... <akonsu@gmail.com> wrote:
>hello,
>
>apparently ruby as most other languages has more than one way to
>express the same thing. i myself see no advantage of the code in active
>record that you posted and your code. except for the active record code
>is faster than yours because it does not check any variables at all
>when evaluating the table_name method.
>

I'm not so sure it's faster; it uses a class_eval.

Phil

Peter Lacey

1/4/2006 9:32:00 PM

0

On Jan 4, 2006, at 3:47 PM, Phil Tomson wrote:

> I'm not so sure it's faster; it uses a class_eval.

There's a comment in the actual active record code that notes that
class_eval is used over define_method to get around a memory leak in
fcgi.

But to Ako's point, it seems to me that there has to be some
important difference between the singleton approach and the class
instance var approach for several reasons:

1. DHH and the other active record coders and reviewers know what
they're doing, and I suspect this seemingly convoluted code wouldn't
have survived for very long if it was simply "another way of doing it."

2. I'm very new to Ruby, and I don't know what I'm doing. :-)

3. The active record code _does_ use class instance vars in other
places, so this looks very intentional.

Any other thoughts?

Regards,
Pete



Ross Bamford

1/4/2006 10:09:00 PM

0

On Wed, 04 Jan 2006 21:32:25 -0000, Peter Lacey
<placey@wanderingbarque.com> wrote:

> On Jan 4, 2006, at 3:47 PM, Phil Tomson wrote:
>
>> I'm not so sure it's faster; it uses a class_eval.
>
> There's a comment in the actual active record code that notes that
> class_eval is used over define_method to get around a memory leak in
> fcgi.
>
> But to Ako's point, it seems to me that there has to be some important
> difference between the singleton approach and the class instance var
> approach for several reasons:
>
> 1. DHH and the other active record coders and reviewers know what
> they're doing, and I suspect this seemingly convoluted code wouldn't
> have survived for very long if it was simply "another way of doing it."
>
> 2. I'm very new to Ruby, and I don't know what I'm doing. :-)
>
> 3. The active record code _does_ use class instance vars in other
> places, so this looks very intentional.
>

Seems to me the technique is about one-time creation of attribute
accessors that, instead of looking like:

def name
"name"
end

Which, when called multiple times, may be faster than equivalent instance
variable lookups. My *guess* is that this is probably a bit quicker with
symbols and maybe strings (which is what this seems to be using - notice
the 'inspect' too) than going for an instance var.

?

--
Ross Bamford - rosco@roscopeco.remove.co.uk

Ross Bamford

1/4/2006 10:10:00 PM

0

Ahem, sorry.

On Wed, 04 Jan 2006 22:09:09 -0000, I forgot to write:

>
> Seems to me the technique is about one-time creation of attribute
> accessors that, instead of looking like:
>

def name
@name
end

look like this:

> def name
> "name"
> end
>
> Which, when called multiple times, may be faster than equivalent
> instance variable lookups. My *guess* is that this is probably a bit
> quicker with symbols and maybe strings (which is what this seems to be
> using - notice the 'inspect' too) than going for an instance var.
>
> ?
>

--
Ross Bamford - rosco@roscopeco.remove.co.uk

Peter Lacey

1/4/2006 10:44:00 PM

0

>> On Jan 4, 2006, at 5:18 PM, Ross Bamford wrote:
>> Which, when called multiple times, may be faster than equivalent
>> instance variable lookups.

Maybe, but that's a lot of optimization for a little problem. These
four active record methods (table_name, primary_key, etc.) can't be
called so often that it becomes necessary to avoid the cost of
dereferencing a variable.

There's an article by _why the lucky stiff_ (http://
whytheluckystiff.net/articles/seeingMetaclassesClearly.html) that
gets tantalizingly close to answering this question, but not close
enough. At least not for me. _why, are you lurking? Any input?

I dunno, maybe I'm looking for something that's not there, but I'd
love to keep the discussion going for a bit, if I may.

Pete


ptkwt

1/4/2006 11:30:00 PM

0

In article <0B6DAD2D-A02E-4D6E-82F9-2DB8D78A685F@wanderingbarque.com>,
Peter Lacey <placey@wanderingbarque.com> wrote:
>On Jan 4, 2006, at 3:47 PM, Phil Tomson wrote:
>
>> I'm not so sure it's faster; it uses a class_eval.

ooops, I see that the class_eval is only called once so maybe it's correct
that that version is faster overall.

>
>There's a comment in the actual active record code that notes that
>class_eval is used over define_method to get around a memory leak in
>fcgi.
>
>But to Ako's point, it seems to me that there has to be some
>important difference between the singleton approach and the class
>instance var approach for several reasons:
>
>1. DHH and the other active record coders and reviewers know what
>they're doing, and I suspect this seemingly convoluted code wouldn't
>have survived for very long if it was simply "another way of doing it."
>

>3. The active record code _does_ use class instance vars in other
>places, so this looks very intentional.

I wouldn't be so sure... I suspect that DHH's (and the other Rails
contributors) Ruby skills and understanding have increased over time
and maybe if they were writing the code from scratch now they would use the
class instance variable method as opposed to the class_eval method. I know
that I've got a lot of Ruby code out there that I wrote early on that I would
write very differently now... Sometimes code survives because it works.

>2. I'm very new to Ruby, and I don't know what I'm doing. :-)
>
>3. The active record code _does_ use class instance vars in other
>places, so this looks very intentional.

Like I said above, it's possible that the class instance var meme came later
in the development history of Rails and that they started using it after it
became known to them. Only DHH can say for sure ;-)


Phil

Peter Lacey

1/5/2006 1:11:00 AM

0

Final post in this thread. It seems that the consensus is that these
two approaches are equal in terms of their results. Knowing that, it
would appear that I _did_ oversimplify my original post. For the
sake of the question I had distilled the active record code to this:

class SingletonBase
class << self
def table_name
reset_table_name
end

def reset_table_name
puts "reset_table_name called"
name = self.name
sing = class << self; self; end
sing.class_eval "def table_name; #{name.inspect}; end"
name
end
end
end

However, the actual code is more (but not exactly, in the interest of
brevity) like this:

class Base
class << self
def table_name
reset_table_name
end

def reset_table_name
name = self.name
set_table_name name
name
end

def set_table_name( value=nil, &block )
sing = class << self; self; end
if value
sing.class_eval "def #{name}; #{value.to_s.inspect}; end"
else
sing.send :define_method, name, &block
end
end
end
end

It would appear, then, that the singleton class is created solely for
handling the optional block parameter, and not, as I originally
suspected, for some more global reason.

Sorry for the wild goose chase and thank you for your insight.

Pete

On Jan 4, 2006, at 6:52 PM, Phil Tomson wrote:

> In article <0B6DAD2D-A02E-4D6E-82F9-2DB8D78A685F@wanderingbarque.com>,
> Peter Lacey <placey@wanderingbarque.com> wrote:
>> On Jan 4, 2006, at 3:47 PM, Phil Tomson wrote:
>>
>>> I'm not so sure it's faster; it uses a class_eval.
>
> ooops, I see that the class_eval is only called once so maybe it's
> correct
> that that version is faster overall.
>
>>
>> There's a comment in the actual active record code that notes that
>> class_eval is used over define_method to get around a memory leak in
>> fcgi.
>>
>> But to Ako's point, it seems to me that there has to be some
>> important difference between the singleton approach and the class
>> instance var approach for several reasons:
>>
>> 1. DHH and the other active record coders and reviewers know what
>> they're doing, and I suspect this seemingly convoluted code wouldn't
>> have survived for very long if it was simply "another way of doing
>> it."
>>
>
>> 3. The active record code _does_ use class instance vars in other
>> places, so this looks very intentional.
>
> I wouldn't be so sure... I suspect that DHH's (and the other Rails
> contributors) Ruby skills and understanding have increased over time
> and maybe if they were writing the code from scratch now they would
> use the
> class instance variable method as opposed to the class_eval
> method. I know
> that I've got a lot of Ruby code out there that I wrote early on
> that I would
> write very differently now... Sometimes code survives because it
> works.
>
>> 2. I'm very new to Ruby, and I don't know what I'm doing. :-)
>>
>> 3. The active record code _does_ use class instance vars in other
>> places, so this looks very intentional.
>
> Like I said above, it's possible that the class instance var meme
> came later
> in the development history of Rails and that they started using it
> after it
> became known to them. Only DHH can say for sure ;-)
>
>
> Phil
>



3jane.

1/15/2010 2:10:00 AM

0

> > Is it just me, or are these kids scarier than I remember?
> > Disgusted.
>
> It's OK Sweetbac, you don't need to pretend with us.  We're all
> friends here.  We know that you were permanently banned from Marin
> County several years ago after that Unfortunate Incident with the
> cattle prod, mule, whipped cream and undocumented alien at Moylan's
> Brewpub.  So enough with this "I've been cruising through Mill Valley"
> schtick, mmmkay??

Please leave the mule out of this. It really had no say in the
matter.
.

Sweetbac

1/15/2010 5:01:00 PM

0


"Neil X" <neilxk@yahoo.com> wrote in message news:e24587d9-ae8b-4874-abc9-

> It's OK Sweetbac, you don't need to pretend with us.
>
> Peace,
> Neil X.

X you ignorant slut.
Just TRY and order chicken n' waffles in Boston.
Good luck, my freind.
I guess the only thing that might be close is one of
them Irish breakfasts from some pub or something.
Mealy tomatoes...those awful rashers of Irish "bacon"
No thanks.
I'm guessing any restaurant serving african american
cuisine would be fire bombed before the last waffle
hit the griddle..Irish hoodlums not exactly known for
tolerance.