Lexically scoped variables

Discussion in 'Ruby' started by Eric Sunshine, Dec 19, 2003.

  1. 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
    Eric Sunshine, Dec 19, 2003
    #1
    1. Advertising

  2. Received: Sat, 20 Dec 2003 06:47:53 +0900
    And lo Eric wrote:

    > scope {
    > foo = BigObject.new
    > ... manipulate foo ...
    > }


    Take an idea from File?

    BigObject.new do |foo|
    ... manipulate foo ...
    end
    Gregory Millam, Dec 19, 2003
    #2
    1. Advertising

  3. On Sat, 20 Dec 2003 07:06:20 +0900, Gregory Millam wrote:
    > Received: Sat, 20 Dec 2003 06:47:53 +0900
    > And lo Eric wrote:
    > > scope {
    > > foo = BigObject.new
    > > ... manipulate foo ...
    > > }

    > 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
    Eric Sunshine, Dec 21, 2003
    #3
  4. Received: Sun, 21 Dec 2003 09:59:56 +0900
    And lo Eric wrote:

    > 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.
    Gregory Millam, Dec 21, 2003
    #4
  5. On Sun, 21 Dec 2003 10:06:36 +0900, Gregory Millam wrote:
    > 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
    Eric Sunshine, Dec 21, 2003
    #5
  6. il Sat, 20 Dec 2003 06:47:53 +0900, Eric Sunshine
    <> 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 ;)
    gabriele renzi, Dec 21, 2003
    #6
  7. "Eric Sunshine" <> schrieb im Newsbeitrag
    news:...
    > On Sat, 20 Dec 2003 07:06:20 +0900, Gregory Millam wrote:
    > > Received: Sat, 20 Dec 2003 06:47:53 +0900
    > > And lo Eric wrote:
    > > > scope {
    > > > foo = BigObject.new
    > > > ... manipulate foo ...
    > > > }

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


    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
    Robert Klemme, Dec 26, 2003
    #7
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Gavin Sherlock
    Replies:
    1
    Views:
    98
    Uri Guttman
    Dec 10, 2003
  2. Alex Hart
    Replies:
    0
    Views:
    87
    Alex Hart
    Jan 24, 2005
  3. Alex Hart
    Replies:
    1
    Views:
    100
    Anno Siegel
    Jan 24, 2005
  4. Derek Basch
    Replies:
    6
    Views:
    173
    Michele Dondi
    May 29, 2006
  5. Peter Michaux
    Replies:
    1
    Views:
    92
    Peter Michaux
    Jun 1, 2007
Loading...

Share This Page