--- Yukihiro Matsumoto <matz / ruby-lang.org> wrote:
> |In addition to handling defaults in arguments, I think these
> |issues need to be addressed in blocks/lambdas:
> |
> |- all variables in the defining scope of a block/lambda are
> |prevented from being GCed by the block/lambda (because of
> the
> |#binding).  This can easily result in a leaky program if not
> |careful.  I discussed several solutions to this in a
> previous
> |thread.
> 
> I think this issue should _not_ be solved by making new
> lambda-like
> object, but something like making eval a keyword, so that non
> referenced local variable can be erased unless eval is called
> within
> the scope.

I agree.  In addition to eval within the block (or even a
method that calls eval), you also have the issue that sometimes
people (including me) have wanted to call eval with
Proc#binding and want access to variables outside the block.  I
think the majority of the time that is wanted is when the
binding is from the caller, so those variables won't want to be
GCed yet anyways.  One of the solutions I gave was to have all
of the variables not directly referenced in the block be weak
references in Proc#binding, so that GC wouldn't be prevented. 
GCing those unused variables would delete the weak references
in Proc#binding.  I think this solution would maintain the best
compatibility/flexibility and still solve the problem.

> |- a facility for making variables local (regardless of
> whether
> |a variable of the same name exists in the defining scope). 
> |This would also be good to have for a begin-end type block
> (I'd
> |like to have it for making inlined macros where I don't want
> to
> |worry about what variables are already used).  I discussed
> |several solutions for this in another thread.
> 
> In 1.9, you can declare block local variables explicitly, by
> the
> syntax:
> 
>   foo {|a; b, c| ...}   # b and c are block local
> 
> so that
> 
>   b=1
>   5.times{|i;b|
>     b=5         # modifying in-block "b"
>     p [i,b]
>   }
>   p b           # outer "b" remain unchanged

EXCELLENT!

Would you consider having something like a begin/end block
having this ability too?

b=1
begin(b)
  b=5
  p b # => 5
end
p b # => 1

Or maybe if "eval" became a keyword like you mentioned above
and it could also take a block, you could do this instead:

b=1
eval {|;b|
  b=5
  p b # => 5
}
p b # => 1

I'm wanting to avoid the method calls to do this.  If eval was
a keyword (or non-redefinable), the above could accomplish it
because it could be in-lined (like begin-end).

> |Also, I saw some slides for ruby 2 back in 2003 showing that
> |arguments will always be local to the block and other
> variables
> |in the block will be in the same scope as the defining
> scope. 
> |I think always making arguments local is a good thing, but
> |never localizing the other variables will be problematic if
> |another local variable facility is not provided.
> 
> See above.

It doesn't look like arguments are local yet and all variables
inside the block that are not used yet outside are treated
local:

b=1
i=2
5.times { |i;b|
  b=5
  c=6
  p [i,b]
}
p [i,b]  # => [4, 1] # i changed, b not
p c      # undefined local variable or method



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