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

···

--
Posted via http://www.ruby-forum.com/.

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

···

On 7/24/07, Marcin Tyman <m.tyman@interia.pl> wrote:

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
--
Posted via http://www.ruby-forum.com/\.

--
I always knew that one day Smalltalk would replace Java.
I just didn't know it would be called Ruby
-- Kent Beck

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

···

2007/7/24, Marcin Tyman <m.tyman@interia.pl>:

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++)

Hi,

At Tue, 24 Jul 2007 17:40:57 +0900,
Marcin Tyman 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.

···

--
Nobu Nakada

*cough*

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

==>
1
2
3

Regards,

Jeremy Henty

···

On 2007-07-24, Robert Klemme <shortcutter@googlemail.com> wrote:

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

Hi,

>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

···

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

On 7/24/07, Marcin Tyman <m.tyman@interia.pl> wrote:

--
Bertram Scharpf
Stuttgart, Deutschland/Germany
http://www.bertram-scharpf.de

Nobuyoshi Nakada wrote:

Hi,

At Tue, 24 Jul 2007 17:40:57 +0900,
Marcin Tyman 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.

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

Sometimes a little abstraction leakage can be useful!

···

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

Hi --

···

On Tue, 24 Jul 2007, Jeremy Henty wrote:

On 2007-07-24, Robert Klemme <shortcutter@googlemail.com> 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

"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

--
* Books:
   RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242\)
   RUBY FOR RAILS (http://www.manning.com/black\)
* Ruby/Rails training
     & consulting: Ruby Power and Light, LLC (http://www.rubypal.com)

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

Robert

···

On 7/24/07, Jeremy Henty <onepoint@starurchin.org> wrote:

On 2007-07-24, Robert Klemme <shortcutter@googlemail.com> 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 Henty

--
I always knew that one day Smalltalk would replace Java.
I just didn't know it would be called Ruby
-- Kent Beck

Hi,

> >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

LOL completely forgot them, thx.

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

exactly
<snip>
Robert

···

On 7/24/07, Bertram Scharpf <lists@bertram-scharpf.de> wrote:

Am Dienstag, 24. Jul 2007, 18:03:15 +0900 schrieb Robert Dober:
> On 7/24/07, Marcin Tyman <m.tyman@interia.pl> wrote:

--
I always knew that one day Smalltalk would replace Java.
I just didn't know it would be called Ruby
-- Kent Beck

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.

···

--
Nobu Nakada

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

···

On 7/24/07, Joel VanderWerf <vjoel@path.berkeley.edu> wrote:

Nobuyoshi Nakada wrote:
> Hi,
>
> At Tue, 24 Jul 2007 17:40:57 +0900,
> Marcin Tyman 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.
>

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

Sometimes a little abstraction leakage can be useful!

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

--
I always knew that one day Smalltalk would replace Java.
I just didn't know it would be called Ruby
-- Kent Beck

True, but it is still "visible in a single method only", which AIUI
Robert Klemme 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 Henty

···

On 2007-07-24, dblack@wobblini.net <dblack@wobblini.net> wrote:

On Tue, 24 Jul 2007, Jeremy Henty wrote:

On 2007-07-24, Robert Klemme <shortcutter@googlemail.com> wrote:

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

class Foo
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.

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 Henty

···

On 2007-07-24, Robert Dober <robert.dober@gmail.com> wrote:

On 7/24/07, Jeremy Henty <onepoint@starurchin.org> wrote:

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

Terribly slow BTW :frowning:

> Nobuyoshi Nakada wrote:
> > Hi,
> >
> > At Tue, 24 Jul 2007 17:40:57 +0900,
> > Marcin Tyman 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.
> >
>
> Interesting. That is because Float, Regexp, and Bignum are instantiated
> 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:

The reason why it works is this:

def f; (0..0).object_id end

=> nil

5.times {p f}

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

···

2007/7/25, Robert Dober <robert.dober@gmail.com>:

On 7/24/07, Joel VanderWerf <vjoel@path.berkeley.edu> wrote:

Hi --

···

On Wed, 25 Jul 2007, Robert Dober wrote:

On 7/24/07, Joel VanderWerf <vjoel@path.berkeley.edu> wrote:

Nobuyoshi Nakada wrote:
> Hi,
>
> At Tue, 24 Jul 2007 17:40:57 +0900,
> Marcin Tyman 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.
>

Interesting. That is because Float, Regexp, and Bignum are instantiated
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:

I get the same result with or without the line between the two times
calls. Are you seeing it output 42?

David

--
* Books:
   RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242\)
   RUBY FOR RAILS (http://www.manning.com/black\)
* Ruby/Rails training
     & consulting: Ruby Power and Light, LLC (http://www.rubypal.com)

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 Henty <onepoint@starurchin.org> wrote:

On 2007-07-24, Robert Dober <robert.dober@gmail.com> wrote:
> On 7/24/07, Jeremy Henty <onepoint@starurchin.org> 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 Henty

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, Jeremy Henty <onepoint@starurchin.org> wrote:

On 2007-07-24, Robert Dober <robert.dober@gmail.com> wrote:
> On 7/24/07, Jeremy Henty <onepoint@starurchin.org> 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 Henty

--
I always knew that one day Smalltalk would replace Java.
I just didn't know it would be called Ruby
-- Kent Beck

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

···

2007/7/24, Jeremy Henty <onepoint@starurchin.org>:

On 2007-07-24, dblack@wobblini.net <dblack@wobblini.net> wrote:
>
> On Tue, 24 Jul 2007, Jeremy Henty wrote:
>
>> On 2007-07-24, Robert Klemme <shortcutter@googlemail.com> wrote:
>>
>>> If you mean static variables that are visible in a single method
>>> only, then no, there is no way to do it.
>>
>> class Foo
>> 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 Klemme 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.

> > Nobuyoshi Nakada wrote:
> > > Hi,
> > >
> > > At Tue, 24 Jul 2007 17:40:57 +0900,
> > > Marcin Tyman 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.
> > >
> >
> > Interesting. That is because Float, Regexp, and Bignum are instantiated
> > 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:

The reason why it works is this:

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

Actually this is a reason why it should *not* work
def f; (0..0).object_id end
2.times{ p f }
p (0..0).object_id
Nevertheless it does because of the scope local optimization if I
understood Joël correctly.

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

Hmm as we are exploring it, let us see if it works for all constants,
somehow I doubt it...
Fixnum ranges work, Bignum ranges do not
646/146 > cat rang_oid.rb && ruby rang_oid.rb
#!/usr/local/bin/ruby
# vim: sw=2 sts=2 ft=ruby expandtab tw=0:

def f; "08%x" % (1..1073741823).object_id end
def b; "08%x" % (1..1073741824).object_id end

puts "f"
3.times{ puts f }
puts "b"
3.times{ puts b }
f
08..fdbeb46ae
b
08..fdbeb4366
08..fdbeb4334
08..fdbeb4302

So for bignums the values will not be kept.

Robert

···

On 7/25/07, Robert Klemme <shortcutter@googlemail.com> wrote:

2007/7/25, Robert Dober <robert.dober@gmail.com>:
> On 7/24/07, Joel VanderWerf <vjoel@path.berkeley.edu> wrote:

--
I always knew that one day Smalltalk would replace Java.
I just didn't know it would be called Ruby
-- Kent Beck