Static variables in Ruby

Hi everybody,
Is any way to define static variables over function? As class static
variables there is possible to define a static class variable as
@@name_of_var. But I’m not sure if Ruby let define such variables in
functions (like in C/C++)

Thanks in advance,
MT

On 7/24/07, Marcin T. [email protected] wrote:

There are three kinds of variables in Ruby
local
@@class_var
@instance_var

My tip, do not use @@class_var, use @inst_var on the correct level

Here goes the classic example of a “static” (forget this expression;)
variable counting instances.
I will use an instance variable of the class (commonly called class
instance variables) for that

549/49 > cat class-inst.rb && ruby class-inst.rb

class A
@count = 0
class << self
attr_accessor :count
end
def initialize val
@a = val
self.class.count += 1
end
end

a=A.new 42
b=A.new 43

p a
p b
p A.count
#<A:0xb7db6764 @a=42>
#<A:0xb7db66b0 @a=43>
2
HTH
Robert

2007/7/24, Marcin T. [email protected]:

Hi everybody,
Is any way to define static variables over function? As class static
variables there is possible to define a static class variable as
@@name_of_var. But I’m not sure if Ruby let define such variables in
functions (like in C/C++)

If you mean static variables that are visible in a single method only,
then no, there is no way to do it. You should probably rethink your
design if it relies on such archaic features of other programming
languages. :slight_smile:

Kind regards

robert

On 2007-07-24, Robert K. [email protected] wrote:

If you mean static variables that are visible in a single method
only, then no, there is no way to do it.

cough

class Foo
count = 0
define_method(:foo) { count += 1 }
end
x = Foo.new
3.times { puts x.foo }

==>
1
2
3

Regards,

Jeremy H.

Hi –

On Tue, 24 Jul 2007, Jeremy H. wrote:

end
x = Foo.new
3.times { puts x.foo }

==>
1
2
3

“Static” is a misleading term, though. It’s just a local variable
that happens to get wrapped in a closure. In general, I don’t think
Ruby and the word “static” mix very well :slight_smile: Constants are sort of
statically scoped, but that’s about it.

David

On 2007-07-24, [email protected] [email protected] wrote:

define_method(:foo) { count += 1 }
end

“Static” is a misleading term, though. It’s just a local variable
that happens to get wrapped in a closure.

True, but it is still “visible in a single method only”, which AIUI
Robert K. claimed was undoable. Even though Ruby doesn’t have
truely static variables, it can create something that behaves very
like (a common use case of) them. That’s all I’m claiming.

Regards,

Jeremy H.

On 7/24/07, Jeremy H. [email protected] wrote:

end
Jeremy H.

closure based properties, what a nice idea :wink:
Terribly slow BTW :frowning:

Robert

On 7/24/07, Bertram S. [email protected] wrote:

@@class_var
@instance_var

Further

$global
LOL completely forgot them, thx.

which I use almost never (except $1, $> etc.).
exactly

Robert

On 2007-07-24, Robert D. [email protected] wrote:

On 7/24/07, Jeremy H. [email protected] wrote:

class Foo
count = 0
define_method(:foo) { count += 1 }
end

Terribly slow BTW :frowning:

Why is that? Are all methods created by define_method slow? Or is it
something particular to the way I’m using it here? I’m really getting
into metaprogramming with define_method so I’d like to learn about the
pitfalls.

Regards,

Jeremy H.

On 7/24/07, Jeremy H. [email protected] wrote:

Why is that? Are all methods created by define_method slow? Or is it
something particular to the way I’m using it here? I’m really getting
into metaprogramming with define_method so I’d like to learn about the
pitfalls.

Regards,

Jeremy H.

I believe Robert developed a library for using closure based
properties a short while back. Something to do with a breed of dog or
something :slight_smile: Cool stuff. But he found it to be slow if I remember
correctly.

Todd

On 7/24/07, Jeremy H. [email protected] wrote:

Why is that? Are all methods created by define_method slow? Or is it
something particular to the way I’m using it here? I’m really getting
into metaprogramming with define_method so I’d like to learn about the
pitfalls.

Regards,

Jeremy H.

No it is the lookup, if you are interested I can send you my
benchmarks, without any twists it was 4 to 5 times slower than ivar
lookup and with twists like read_only, write_once, rw_locks it quickly
climbed to a factor worse than 10 :frowning:
Robert

On 7/24/07, Todd B. [email protected] wrote:

properties a short while back. Something to do with a breed of dog or
something :slight_smile: Cool stuff. But he found it to be slow if I remember
correctly.
Thx, properties are broken, but thx anyway :slight_smile:

2007/7/24, Jeremy H. [email protected]:

count = 0
define_method(:foo) { count += 1 }
end

“Static” is a misleading term, though. It’s just a local variable
that happens to get wrapped in a closure.

True, but it is still “visible in a single method only”, which AIUI
Robert K. claimed was undoable. Even though Ruby doesn’t have
truely static variables, it can create something that behaves very
like (a common use case of) them. That’s all I’m claiming.

Well, in Ruby there is usually a workaround. But there is no real
built in static method variables feature. So we’re both correct in a
way. :slight_smile:

Also, I did not want to encourage people to use this pattern because I
believe it’s not good. Here’s why: if you have a design complex
enough make separation of your instance state by method necessary then
you should break up functionality into more classes to keep it
manageable.

Kind regards

robert

On 2007-07-24, Robert K. [email protected] wrote:

… if you have a design complex enough make separation of your
instance state by method necessary then you should break up
functionality into more classes to keep it manageable.

Fair enough. In fact that often happens to me; I implement something
in a clever way at first, then when it’s time to clean up and refactor
I see that I was being too clever and rewrite it much more
straightforwardly. I guess that means I’m clever, but meta-stupid
(for being too clever), but meta-meta-clever (for noticing when I’m
being meta-stupid). I think I’ll quit there while I’m ahead! :slight_smile:

Regards,

Jeremy H.

Hi,

Am Dienstag, 24. Jul 2007, 18:03:15 +0900 schrieb Robert D.:

On 7/24/07, Marcin T. [email protected] wrote:

Is any way to define static variables over function? As class static
variables there is possible to define a static class variable as
@@name_of_var. But I’m not sure if Ruby let define such variables in
functions (like in C/C++)
There are three kinds of variables in Ruby
local
@@class_var
@instance_var

Further

$global

which I use almost never (except $1, $> etc.).

My tip, do not use @@class_var, use @inst_var on the correct level

class A
@count = 0
class << self
attr_accessor :count
end
end

So do I.

Bertram

Nobuyoshi N. wrote:

(0..0).instance_eval{x,@x = @x,x}
x

end
3.times{|i|p foo(i)} #=> nil, 1, 2

The literal object can be Float, Regexp or Bignum, but Range
would be faster a bit.

Interesting. That is because Float, Regexp, and Bignum are instantiated
per scope, right?

Sometimes a little abstraction leakage can be useful!

Hi,

At Tue, 24 Jul 2007 17:40:57 +0900,
Marcin T. wrote in [ruby-talk:261483]:

Is any way to define static variables over function? As class static
variables there is possible to define a static class variable as
@@name_of_var. But I’m not sure if Ruby let define such variables in
functions (like in C/C++)

def foo(x)
(0…0).instance_eval{x,@x = @x,x}
x
end
3.times{|i|p foo(i)} #=> nil, 1, 2

The literal object can be Float, Regexp or Bignum, but Range
would be faster a bit.

On 7/24/07, Joel VanderWerf [email protected] wrote:

def foo(x)
per scope, right?

Sometimes a little abstraction leakage can be useful!


vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

I did not believe this,and why should I?
But it seems to be true :wink:
def foo(x)
(0…0).instance_eval{x,@x = @x,x}
x
end

3.times{ |i| puts foo(i) }
(0…0).instance_eval{@x=42}
3.times{ |i| puts foo(i) }

Run this for a pleasant surprise :slight_smile:

Robert

Hi,

At Wed, 25 Jul 2007 06:59:46 +0900,
Joel VanderWerf wrote in [ruby-talk:261627]:

Interesting. That is because Float, Regexp, and Bignum are instantiated
per scope, right?

Yes, per node in accurate.

Sometimes a little abstraction leakage can be useful!

Note that it works with the current MRI. I won’t be surprised
if it never work with JRuby, Rubinius, IronRuby, etc.

2007/7/25, Robert D. [email protected]:

Interesting. That is because Float, Regexp, and Bignum are instantiated
def foo(x)
(0…0).instance_eval{x,@x = @x,x}
x
end

3.times{ |i| puts foo(i) }
(0…0).instance_eval{@x=42}
3.times{ |i| puts foo(i) }

Run this for a pleasant surprise :slight_smile:

The reason why it works is this:

def f; (0…0).object_id end
=> nil
5.times {p f}
69868270
69868270
69868270
69868270
69868270
=> 5

The Ruby interpreter optimizes this when both ends are constant.

def g(a)(0…a).object_id end
=> nil
5.times {p g(1)}
69627090
69626930
69626820
69626680
69626560
=> 5

Kind regards

robert