[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



More information about the Python-ideas mailing list