--- "Ara.T.Howard" <Ara.T.Howard / noaa.gov> wrote:

> On Thu, 29 Sep 2005, Eric Mahurin wrote:
> 
> > --- Martin DeMello <martindemello / yahoo.com> wrote:
> >
> >> Ara.T.Howard <Ara.T.Howard / noaa.gov> wrote:
> >>> On Thu, 29 Sep 2005, David A. Black wrote:
> >>>>
> >>>>  a = 1
> >>>>  method_call {|a| a = 2; b = 3 }
> >>>>  puts a  # 1
> >>>>  puts b  # 3
> >>>
> >>> oh gawd - that's horrible : variables exported from
> method
> >> scope to the global
> >>> (or enclosing perhaps?) one. eeks!
> >>
> >> Blocks exist in the caller's scope, not the method's, so I
> >> don't really
> >> see the problem here.
> >>
> >> martin
> >
> > I like it.  The variable locality is independent of whether
> or
> > not the variable existed in the outside scope (it is
> dependent
> > on that now).  Arguments would be local and other variables
> > would be in the context of what contains the block. 
> Period.
> > With this you could easily create a localize method:
> >
> > def localize(&block)
> >  yield(*Array.new(block.arity)) # arity can't be <0
> > end
> >
> > Then this would localize x and y for you (initialize to
> nil):
> >
> > localize { |x,y| ... }
> 
> but it totally violates structured programming principles -
> methods pollute
> the heap : data from methods (stack) is not freed when the
> method returnes.
> eg:
> 
>    # method which sets up x on the heap
> 
>    method_call { x = 42 }
> 
>    # we cannot free x here - someone may want to print it
> below
> 
>    p x
> 
>    # we cannot free x here - someone may still want to print
> it below
> 
>    p x
> 
>    # when can we free it?
> 
> so all non-local variables would need to live on the heap
> forever.  that'd
> make it pretty easy to run out of memory in any sort of tight
> loop.
> 
> afaikt variables created like that could never be freed
> because there'd be no
> way to know if someone would refer to them, at some point in
> the future, after
> the method or not.  it seems like the only safe way to deal
> with that sort of
> thing is pushing/poping them to/from the stack so they are
> freed on method
> exit.  but maybe i'm missing something obvious here?

You should be able to free x as soon as the enclosing methods
completes, right?

How about this one:

def foo
  a = [1,2,3]
  lambda { x = 42 }
end

f = foo
f.call # => 42
eval("a",f.binding) # => [1,2,3]

When you start passing around blocks/lambdas, you prevent all
of the variables in surrounding scope from being GC'ed because
of the #binding link.  All for the sake of an eval on the
binding.  I think this is a larger issue than the one you are
discussing.  

There are several ways you could treat variables within blocks:

- local if not in surrounding scope (now in 1.8)
- local with no relation to surrounding scope (2.0 args)
- local and intialized to same value in surrounding scope
- same scope as surrounding scope (2.0 other variables)

I think it is hard to pick from these.  You can make an
argument that any of these are useful.  It would be nice to be
able to control this more directly, but this may also reduce
readability.


__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com