On Sep 28, 4:47 pm, Terry Reedy <[EMAIL PROTECTED]> wrote: > Aaron "Castironpi" Brady wrote: > > On Sep 28, 2:52 am, Steven D'Aprano <[EMAIL PROTECTED] > >> As for why the complicated version works, it may be clearer if you expand > >> it from a one-liner: > > >> # expand: f[ n ]= (lambda n: ( lambda: n ) )( n ) > > >> inner = lambda: n > >> outer = lambda n: inner > >> f[n] = outer(n) > > >> outer(0) => inner with a local scope of n=0 > >> outer(1) => inner with a local scope of n=1 etc. > > For this to work, the 'expansion' has to be mental and not actual. > Which is to say, inner must be a text macro to be substituted back into > outer. > > >> Then, later, when you call inner() it grabs the local scope and returns > >> the number you expected. > > > I must have misunderstood. Here's my run of your code: > > I cannot speak to what Steven meant, but > > >>>> inner = lambda: n > > when inner is actually compiled outside of outer, it is no longer a > closure over outer's 'n' and 'n' will be looked for in globals instead. > > >>>> outer = lambda n: inner > >>>> outer(0) > > <function <lambda> at 0x00A01170> > >>>> a=outer(0) > >>>> b=outer(1) > >>>> a() > > Traceback (most recent call last): > > File "<stdin>", line 1, in <module> > > File "<stdin>", line 1, in <lambda> > > NameError: global name 'n' is not defined > > > Why doesn't 'inner' know it's been used in two different scopes, and > > look up 'n' based on the one it's in? > > That would be dynamic rather than lexical scoping.
I couldn't find how those apply on the wikipedia website. It says: "dynamic scoping can be dangerous and almost no modern languages use it", but it sounded like that was what closures use. Or maybe it was what 'inner' in Steven's example would use. I'm confused. Actually, I'll pick this apart a little bit. See above when I suggested 'late' and 'early' functions which control (or simulate) different bindings. I get the idea that 'late' bound functions would use a dangerous "dynamic scope", but I could be wrong; that's just my impression. > >> inner = lambda: n > >> outer = lambda n: inner > >> f[n] = outer(n) > > >> outer(0) => inner with a local scope of n=0 > >> outer(1) => inner with a local scope of n=1 etc. If you defined these as: inner= late( lambda: n ) outer= lambda n: inner You could get the right results. It's not even clear you need quotes. Perhaps 'late' could carry the definition of 'n' with it when it's returned from 'outer'. In my proposal, it makes a copy of the "localest" namespace, at least all the variables used below it, then returns its argument in an original closure. -- http://mail.python.org/mailman/listinfo/python-list