Lexically scoped variables

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
 
G

Gregory Millam

Received: Sat, 20 Dec 2003 06:47:53 +0900
And said:
scope {
foo = BigObject.new
... manipulate foo ...
}

Take an idea from File?

BigObject.new do |foo|
... manipulate foo ...
end
 
E

Eric Sunshine

Received: Sat, 20 Dec 2003 06:47:53 +0900

Take an idea from File?
BigObject.new do |foo|
... manipulate foo ...
end

Thanks, but this proposal is very special-case, whereas I'm looking for a
general purpose solution for automatic clean-up of variables in a
long-running interactive environment, much like my scope{} solution provides,
or { and } blocks in C. In my example, BigObject was used merely to
illustrate that the user might be working with memory hungry objects in
various ways.

-- ES
 
G

Gregory Millam

Received: Sun, 21 Dec 2003 09:59:56 +0900
And said:
Thanks, but this proposal is very special-case, whereas I'm looking for a
general purpose solution for automatic clean-up of variables in a
long-running interactive environment, much like my scope{} solution provides,
or { and } blocks in C. In my example, BigObject was used merely to
illustrate that the user might be working with memory hungry objects in
various ways.

--
if true
foo = BigObject.new
.. manipulate foo
end
puts foo # doesn't exist
--
def scope
yield if block_given?
end
--
scope {
foo = BigObject.new
.. manipulate foo
}
puts foo # doesn't exist
--

Of course, if you do
foo = ""
scope {
foo = ..
}
p foo # What you assigned to it within scope.
Just don't initialize 'foo' outside of the scope.
 
E

Eric Sunshine

if true
foo = BigObject.new
.. manipulate foo
end
puts foo # doesn't exist

This is incorrect. In Ruby, the binding of 'foo' continues to exist after
the 'if' statement.
def scope
yield if block_given?
end
--
scope {
foo = BigObject.new
.. manipulate foo
}
puts foo # doesn't exist
Of course, if you do
foo = ""
scope {
foo = ..
}
p foo # What you assigned to it within scope.
Just don't initialize 'foo' outside of the scope.

I'm not sure what you are trying to say here. This is simply a re-iteration
of everything I said in my original email.

-- ES
 
G

gabriele renzi

il Sat, 20 Dec 2003 06:47:53 +0900, Eric Sunshine
<[email protected]> ha scritto::


Nevertheless, I was wondering if there was a better to achieve this goal;

not that I'm aware of..
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?

well, they should, cause block local variables should be in the |var|
section.
But I think there is still hope to avoid this ;)
 
R

Robert Klemme

Eric Sunshine said:
Thanks, but this proposal is very special-case, whereas I'm looking for a
general purpose solution for automatic clean-up of variables in a
long-running interactive environment, much like my scope{} solution provides,
or { and } blocks in C. In my example, BigObject was used merely to
illustrate that the user might be working with memory hungry objects in
various ways.

How about:

Object.new.instance_eval do
reclaimed = "foo"
p reclaimed

@reclaimed_too = "bar"
p @reclaimed_too
end

# error
p reclaimed
# nil
p @reclaimed_too

robert
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top