← Back to context

Comment by trealira

19 days ago

It's just a name shadowing.

Copying the code they wrote:

  for i in xrange(3):
      def func(x, i=i): # the *value* of i is copied in func() environment
          return x * i
      flist.append(func)

That could also be written "def func(x, foo=i): return x * foo". It's just copying i's value to another variable. In the next line, i's value is still 1, 2, or 3, so when the function is called during the next line of the body of the loop, the value held by i is bound to foo.

It's not evaluating a thunk representing i, which is how lazy variables are evaluated in Haskell.

Ok, I had a better look at the code and I realised that it doesn't follow the rule I was talking about, namely having the function only work on values it receives as inputs.

I think that's why I don't use closures, because they read values from the environment. Their only use case (that comes to mind) can be solved with partial application, which is safer.

Oh, and I wasn't using laziness in the Haskell sense, but more in the general sense of deferring evaluation.