← Back to context

Comment by trealira

17 days ago

Yeah, this is a common source of confusion with closures in Python. Example on Stack Overflow:

https://stackoverflow.com/questions/233673/how-do-lexical-cl...

Doesn't that example also show a kind of laziness?

I say this because the second solution to that question offers the solution of using `i` as a default argument when defining the function. That forces its evaluation and fixes the problem.

  • 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.