[Python-ideas] Explicit variable capture list

Stefan Krah skrah.temporarily at gmail.com
Sat Jan 23 07:57:36 EST 2016


Nick Coghlan <ncoghlan at ...> writes:
> On 23 January 2016 at 14:50, Andrew Barnert via Python-ideas
> <python-ideas at ...> wrote:
> > What the thread is ultimately looking for is a solution to the "closures
> > capturing loop variables" problem. This problem has been in the official
> > programming FAQ[1] for decades, as "Why do lambdas defined in a loop with
> > different values all return the same result"?
> >
> >     powers = [lambda x: x**i for i in range(10)]
> >
> > This gives you ten functions that all return x**9, which is probably not
> > what you wanted.
> >
> > The reason this is a problem is that Python uses "late binding", which in
> > this context means that each of those functions is a closure that captures
> > the variable i in a way that looks up the value of i at call time. All ten
> > functions capture the same variable, and when you later call them, that
> > variable's value is 9.

I've never liked the use of "late binding" in this context. The
behavior is totally standard for closures that use mutable values.

Here's OCaml, using refs (mutable reference cells) instead of
the regular immutable values.  BTW, no one would write OCaml
like in the following example, it's just for clarity):


let i = ref 0.0;;
# val i : float ref = {contents = 0.}


let rpow = ref [];;
# val rpow : '_a list ref = {contents = []}


while (!i < 10.0) do
  rpow := (fun x -> x**(!i)) :: !rpow;
  i := !i +. 1.0
done;;
- : unit = ()


let powers = List.rev !rpow;;

val powers : (float -> float) list =
  [<fun>; <fun>; <fun>; <fun>; <fun>; <fun>; <fun>; <fun>; <fun>; <fun>]
List.map (fun f -> f 10.0) powers;;
- : float list =
[10000000000.; 10000000000.; 10000000000.; 10000000000.; 10000000000.;
 10000000000.; 10000000000.; 10000000000.; 10000000000.; 10000000000.]
#


You see that "i" is a reference cell, i.e. it's compiled to a C struct
and lookups are just a pointer dereference.


Conceptually Python's dictionaries are really just the same as reference
cells, except they hold more than one value.


So, to me the entire question is more one of immutable vs. mutable
rather than late vs. early binding.


Stefan Krah


































More information about the Python-ideas mailing list