Static variable; behaviour in ruby?


#1

Any idea how to create or simulate a static variable in ruby?

I want to create a variable to hold state between calls of a method,
but have the state disappear when the method goes out of scope.
I could create it in some external object but then I’d need to query
the scoping rules, and know where i was.

I’m trying to do an instance_eval on a string containing a method such
as
do_this x,y,z {block}
and I want to evaluate the block, or not, as a function of some
state against which x,y,z are compared. The code will be called several
times, but I only want the state intialized the first time the scope
is entered.

And, just to make matters worse, there could be several independent
calls to this method within the scope, each with its own separate
state.

Maybe there’s another way to do this?

    Thank you
    Hugh

#2

On 16/11/05, Hugh S. removed_email_address@domain.invalid wrote:

state against which x,y,z are compared. The code will be called several
Hugh

I advise that you state your basic problem, as this seems to be a
problem with an ugly workaround. You can probably restructure your
problem such that this is no longer needed.

Brian


#3

Hugh S. schrieb:

I want to create a variable to hold state between calls of a method,
but have the state disappear when the method goes out of scope.

and

And, just to make matters worse, there could be several independent
calls to this method within the scope, each with its own separate
state.

Isn’t this a contradiction?

When should the state appear and when should it disappear? What should
be the scope of the state?

Regards,
Pit


#4

Hugh S. wrote:

Any idea how to create or simulate a static variable in ruby?

I completely agree to Brian’s comment.

I want to create a variable to hold state between calls of a method,
but have the state disappear when the method goes out of scope.
I could create it in some external object but then I’d need to query
the scoping rules, and know where i was.

I’m not sure I understand you correctly here. Why don’t you just create
an instance that holds this state plus whatever is needed and implement
your behavior in a method of that class? You can control the number of
scopes by the nuber of created instances.

Also, IMHO Pit has a valid point with his remark about a contradiction.

state.

Maybe there’s another way to do this?

Did you consider using a Thread local stack for this (as I conclude from
your latest posting nesting is possible)?

Kind regards

robert

#5

On Wed, 16 Nov 2005, Robert K. wrote:

I’m not sure I understand you correctly here. Why don’t you just create
an instance that holds this state plus whatever is needed and implement
your behavior in a method of that class? You can control the number of

Because I can’t see how to call it into being correctly. If I need
to know “when this method was called the first time” to do this,
then I need something with the same properties as a static variable,
in order to implement a thing with the same properties as a static
variable.

scopes by the nuber of created instances.

But I need to know when to create them for the string I’m
evaluating, rather than when to call on existing ones in that string.

Also, IMHO Pit has a valid point with his remark about a contradiction.

In ruby you can have several flip-flop expressions in the same
context…

calls to this method within the scope, each with its own separate
state.

Maybe there’s another way to do this?

Did you consider using a Thread local stack for this (as I conclude from
your latest posting nesting is possible)?

There is no concurrency in the thing at the moment, so I’m not sure
how to make use of that. Maybe it is a design pattern I’ve missed.

I’m beginning to think it is nontrivial, and will probably to to use
gawk to avoid sed in this case.

Kind regards

robert
    Thank you,
    Hugh

#6

On Thu, 17 Nov 2005, Hugh S. wrote:

Maybe something like
def my_method x, y, z, &block
state = rand # do something with x, y, z
alias :old_my_method, :my_method
define_method(:my_method)(x,y,z, &block)
lambda{ block[x, y, z] if state < 0.42 }.call
end
end

but the second time my_method is called you’ll clobber old_my_method -
is that
what you want? plus it only works once because the first call to
my_method
will define it in such a way that it never sets of state again - it’s
clobbered by the define_method/lambda bit…

might do the trick, then? The state would get carried around with the
closure in subesequent calls to the same method? Except having sevaral
calls in the same block would be treated the same as severl calls to the
same method, rather than the way sed treats /this/,/that/{ statements}, each
heing independent, runnin for each line of the input.

i really don’t quite get what you are after. but from what i’m reading
it
looks alot like you would be better off doing something like this

class Line
def initialize x, y, z, &statements
@state = rand
@x, @y, @z = x, y, z
@statements = statements
end
def my_method
@statements[@x, @y, @z] if @state < 0.42
end
end

put another way - a static variable can be emulated as an instance
variable of
an object. you can have multiple copies by having multiple instances.
the
initialize methods makes sure it’s only called once.

this might be easier?

-a


#7

On Wed, 16 Nov 2005, Hugh S. wrote:

state against which x,y,z are compared. The code will be called several
times, but I only want the state intialized the first time the scope
is entered.

And, just to make matters worse, there could be several independent
calls to this method within the scope, each with its own separate
state.

harp:~ > cat a.rb
def do_this_factory x, y, z, &block
state = rand # do something with x, y, z
lambda{ block[x, y, z] if state < 0.42 }
end

a = do_this_factory ‘x’,‘y’,‘z’ do |x,y,z| p [x,y,z] end
a.call

harp:~ > ruby a.rb

harp:~ > ruby a.rb

harp:~ > ruby a.rb
[“x”, “y”, “z”]

harp:~ > ruby a.rb

harp:~ > ruby a.rb
[“x”, “y”, “z”]

harp:~ > ruby a.rb
[“x”, “y”, “z”]

Maybe there’s another way to do this?

write it in assembler :wink:

-a


#8

Hugh S. wrote:

the scoping rules, and know where i was.
variable.
context…

calls to this method within the scope, each with its own separate
I’m beginning to think it is nontrivial, and will probably to to use
gawk to avoid sed in this case.

I’m not yet convinced that it’s actually so complicated. Please see my
other posting.

robert

#9

On Wed, 16 Nov 2005, Ara.T.Howard wrote:

On Wed, 16 Nov 2005, Hugh S. wrote:

Any idea how to create or simulate a static variable in ruby?
[…]

harp:~ > ruby a.rb
[“x”, “y”, “z”]
[etc]

Maybe something like
def my_method x, y, z, &block
state = rand # do something with x, y, z
alias :old_my_method, :my_method
define_method(:my_method)(x,y,z, &block)
lambda{ block[x, y, z] if state < 0.42 }.call
end
end

might do the trick, then? The state would get carried around with
the closure in subesequent calls to the same method? Except having
sevaral calls in the same block would be treated the same as severl
calls to the same method, rather than the way sed treats
/this/,/that/{ statements}, each heing independent, runnin for each
line of the input.

Maybe there’s another way to do this?

write it in assembler :wink:

:slight_smile:

    Hugh