On Sun, 2003-05-18 at 05:08, MikkelFJ wrote:
> 
> "Jim Weirich" <jweirich / one.net> wrote in message
> news:1053238069.6843.15.camel / traken...
> > On Sun, 2003-05-18 at 00:47, vinita Papur wrote:
> > > A quick question.  How can one discern when an object goes out of scope?
> > > I'd like to do something like this:
> >
> > Objects don't have scope.  Variables do.  (a subtle distinction)
> 
> > Use a block to manage resources.  Like this ...
> 
> Still, it would actually be nice to have a feature in Ruby that would
> trigger a finalizer when the variable goes out of scope. There are problems
> becuase there could be more references at the time of finalization, but this
> could also  be the case with cleanup using structs. I.e. closing a file
> doesn't guarantee there are no more references to the file.

Just because a variable goes out of scope doesn't mean that its object
is no longer used.  That's the whole reason we garbage collection in the
first place, so the programmer no longer needs to worry about what
references what.

For example, in the following code, variable :a goes out of scope, but
the array it is attached to is returned as the value of the function. 
Finalizing :a at the end of returning would be a bad idea.

  def returning
    a = ["var a"]
  end
  
  array = returning
  p array     # => ["var a"]

Even if you could account for return values, and values being squirreled
away inside of other structures, sometimes its hard to determine when a
variable actually goes out of scope.  For example ...

  def closing
    b = ["var b"]
    [ proc { b }, proc{|v| b = v} ]
  end
  
  get, set = closing
  p get.call     #=> ["var b"]
  set.call(10)
  p get.call     #=> 10

The scope containing variable :b is captured by the closures returned
from 'closing'.  Later in the main program, the get closure is called
and we see that the value for b is ["var b"].  Then we call the set
closure and change the binding for variable b.  Now the get closure
returns the new binding.

So a scope can continue to live, even after the method defining the
scope has exited.  This is just weird to people brought up in the
Pascal/C/Algol like languages. 

One final example of scope weirdness.  You could argue that we could
detect when closures are created and handle that as a special case,
since closures have to be created right there in the scope.  However,
there is another time when scope is captured, and it doesn't have to
happen in the lexical scope of the function.

  def continuing
    c = ["var c"]
    cc = silly
    puts "C = #{c}"
    cc
  end
  
  def silly
    callcc {|cc| cc}
  end
  
  cvar = continuing    # => C = ["var c"]
  cvar.call(proc{})    # => C = ["var c"]

Here method 'continuing' returns the value of 'silly', after printing
the value of variable :c.  Silly actually returns a continuation object,
although there is no way to know that from examining the text of
'continuing'.  Outside, in the main program, we call the continuation,
which restarts the 'continuing' method at the point silly was called and
prints the value of variable :c again.

All these things put together make it difficult to do a finalization
when a function exits.  Ain't dynamic languages wonderful :-)

-- 
-- Jim Weirich     jweirich / one.net    http://jimweirich.umlcoop.net
---------------------------------------------------------------------
"Beware of bugs in the above code; I have only proved it correct, 
not tried it." -- Donald Knuth (in a memo to Peter van Emde Boas)