Full Closures - when do they close?

Robert Withers withers at vnet.net
Mon Jan 31 16:03:03 UTC 2000


Jesse Welton wrote:
> 
> Robert Withers wrote:
> >
> > > Another point.  Jesse Welton already pointed out that objects are not copied
> > > by closures.  If two closures refer to same object through their variables,
> > > changes made using one closure will be visible through another.  it is
> > > important that not only objects are not copied, the bindings are not copied
> > > as well.  Two closures created within the same environment see the same
> > > bindings, so changes done to a variable of that environment from one closure
> > > are visible from another.  For example:
> > >
> > >   | cell |
> > >   ^Array
> > >     with: [:arg | cell := arg]
> > >     with: [cell]
> >
> > -- ??? Really??   This surprises me.  I thought that a closure would
> > have it's own binding seperate from any other binding.  This is
> > different that two bindings holding the same reference and changing the
> > internal state of that reference.  Aren't you saying that two bindings
> > pointing to the same reference and one changes the reference, then the
> > other binding will also have  a changed reference?
> 
> Yes, this is exactly right.  This is necessary to allow (among other
> things) assignments to propagate upwards.  Consider:
> 
>     | sum |
>     sum := 0.
>     1 to: self length do: [ :i | sum := sum + self at: i ].
>     ^sum
> 
> In order from something like this to work, "sum" must name the same
> reference both within and without the block.

ugh!  This of course makes sense from a usability standpoint but that
takes me back to:

Method
  | answer |
  answer := Array new: 5.
  1 to: 5 do:
    [:i |
    answer at: i put: [:arg | arg * i]].
  ^answer

Since we are 2 levels deep, each time through the loop we have a
different binding for i, so each inner block gets a seperate binding. 
If this was:

Method
  | answer i |
  answer := Array new: 5.
  i := 1.
  answer at: i put: [:arg | arg * i]].
  i := 2.
  answer at: i put: [:arg | arg * i]].
  i := 3.
  answer at: i put: [:arg | arg * i]].
  i := 4.
  answer at: i put: [:arg | arg * i]].
  i := 5.
  answer at: i put: [:arg | arg * i]].
  ^answer

Then all five blocks would have i = 5.  Is it so?

-Rob

> -Jesse

-- 
--------------------------------------------------
Smalltalking by choice.  Isn't it nice to have one!





More information about the Squeak-dev mailing list