# [Python-ideas] For-loop variable scope: simultaneous possession and ingestion of cake

Carl Johnson carl at carlsensei.com
Mon Oct 6 09:53:06 CEST 2008

```On 2008/10/05, at 9:08 pm, Bruce Leban wrote:

> Consider this:
>
> i = 0
> def f():
>     global i
>     i += 1
>     return lambda: immanentize 1
>
> when does immanentize get evaluated? when f is defined or when the
> lambda is evaluated? From what you wrote, it sounds like you think
> it's evaluated when f is defined. OK, so how do I get the equivalent
> of:
>
> def f():
>     global i
>     i += 1
>     lambda i=i: i
>
> using immanentize?

OK, now I see what you're getting at. That makes more sense. The
question is how do we deal with nested scopes with an immanentize in
the innermost scope. Off the top of my head, I think the most sensible
way to do it is that the immanentization happens when the innermost
scope it's in is turned into a real function by the next scope out.
But I may need to do some more thinking about what would happen here:

def f():
xs = []
for i in range(10):
xs.append(lambda: immanentize i)
return xs

Clearly, we want this immanentize to be held off on until f is finally
called. The more I think about it, the more I realize that an
immanentize always needs to be inside of some kind of function
declaration, whether it's a def or a lambda or (maybe) a class (but I
haven't thought about the details of that yet…), and evaluated
just one level "up" from that.

>>> def side_effector():
...     r = random.randint(0, 10)
...     print(r)
...     return r
...
>>> def f():
...     def g():
...         return immanentize side_effector()
...     return (immanentize side_effector()), g
5
>>> a, b = f()
2
>>> a
5
>>> b()
2
>>> b()
2
>>> a, b = f()
3
>>> a
5
>>> b()
3

In which case, for your original example, the immanentization wouldn't
happen until f is called.

>>> i = 0
>>> def f():
...     global i
...     i += 1
...     return lambda: immanentize i
...
>>> f()
<function <lambda> at 0x3a57970>
>>> g = _
>>> f()
<function <lambda> at 0x3a58240>
>>> k = _
>>> k()
2
>>> g()
1

I think that makes sense, right? :/

Does anyone know how Lisp does this? I know that they write '(blah) to
delay evaluation, but what do they do when they want to force
evaluation someplace in the middle of a non-evaluated list?

-- Carl

```