E
Eric Sunshine
Hello,
About a year and a half ago, I added Ruby scripting support to a
long-running program (a programmer's editor). The program allows interactive
scripting, and it is sometimes the case that the scripting code manipulates
very large, memory-hungry objects. Since the program is long-running and
memory is a limited resource, scripting code needs to clean up after itself
to ensure that the garbage collector can reclaim these large objects. For
instance, the following code (executed at the top-level) is careful to
clean-up after itself:
foo = BigObject.new
... manipulate foo ...
foo = nil # Let garbage collector reclaim BigObject.
Unfortunately, in an interactive scripting environment, it is very easy to
forget to clean up after one's self (i.e. foo = nil), so I wanted a more
automated idiom, yet one which is still convenient in an interactive
environment. In particular, I wanted something which worked like C's { and }
scoping rules. Toward this end, I arrived at the following solution:
module Kernel
def scope
yield
end
end
Now, I can invoke code interactively like this:
scope {
foo = BigObject.new
... manipulate foo ...
}
and I can be sure that foo will be unbound correctly at the end of the scope
(unless, of course, foo already existed outside the scope, in which case it
will remain alive in accordance with Ruby's block-scoping rules). This is a
fairly clean solution which works very much like C's { and } scoping. It is
also simple to use even in an interactive environment, so I am reasonably
happy with it.
Nevertheless, I was wondering if there was a better to achieve this goal;
perhaps a way already supported directly by the language. At the time, I was
working with Ruby 1.6.8. Does 1.8.x provide a better solution? Also, I
understand that there will be some changes to variable scoping within blocks
in a future release of Ruby. Will the new rules break the scheme outlined
above?
-- ES
About a year and a half ago, I added Ruby scripting support to a
long-running program (a programmer's editor). The program allows interactive
scripting, and it is sometimes the case that the scripting code manipulates
very large, memory-hungry objects. Since the program is long-running and
memory is a limited resource, scripting code needs to clean up after itself
to ensure that the garbage collector can reclaim these large objects. For
instance, the following code (executed at the top-level) is careful to
clean-up after itself:
foo = BigObject.new
... manipulate foo ...
foo = nil # Let garbage collector reclaim BigObject.
Unfortunately, in an interactive scripting environment, it is very easy to
forget to clean up after one's self (i.e. foo = nil), so I wanted a more
automated idiom, yet one which is still convenient in an interactive
environment. In particular, I wanted something which worked like C's { and }
scoping rules. Toward this end, I arrived at the following solution:
module Kernel
def scope
yield
end
end
Now, I can invoke code interactively like this:
scope {
foo = BigObject.new
... manipulate foo ...
}
and I can be sure that foo will be unbound correctly at the end of the scope
(unless, of course, foo already existed outside the scope, in which case it
will remain alive in accordance with Ruby's block-scoping rules). This is a
fairly clean solution which works very much like C's { and } scoping. It is
also simple to use even in an interactive environment, so I am reasonably
happy with it.
Nevertheless, I was wondering if there was a better to achieve this goal;
perhaps a way already supported directly by the language. At the time, I was
working with Ruby 1.6.8. Does 1.8.x provide a better solution? Also, I
understand that there will be some changes to variable scoping within blocks
in a future release of Ruby. Will the new rules break the scheme outlined
above?
-- ES