On Sat, Mar 22, 2014 at 3:47 PM, Steven D'Aprano <steve+comp.lang.pyt...@pearwood.info> wrote: > Now I'm not sure precisely how Haskell implements this trick, but it > suggests to me that it creates a different closure each time around the > loop of the comprehension. That could end up being very expensive.
It needn't be terribly expensive, if you make a "scope stack" or "scope chain". Imagine, if you will, a system of scopes like this: current_scope = None class Scope: def __init__(self, *a, **kw): self.names = dict(*a, **kw) global current_scope self.parent = current_scope current_scope = self def __getitem__(self, name): try: return self.names[name] except KeyError: if self.parent is None: raise return self.parent[name] def __setitem__(self, name, value): self.names[name] = value def exit_scope(): global current_scope current_scope = current_scope.parent Creating a new scope would be fairly cheap (and a lot more so if this were implemented in C without the object overhead, of course). Lookups would scan up through a series of namespaces, same as they currently do (local, module, builtins), there'd just be more of them. And the compiler could be smart enough to skip creating a scope if there are no assignments. There'd need to be some handling in there for the 'nonlocal' keyword, but my expectation is that 'global' is handled by retaining a reference to the current_scope at module level, and starting the search there for a LOAD_GLOBAL. Each iteration of the loop could begin with Scope() and end with exit_scope(), and there you are, each iteration in its own closable scope. I'm not saying it would be a good thing to do - and it'd be a bad fit for Python, I think, as I said in my other post - but it could be done. ChrisA -- https://mail.python.org/mailman/listinfo/python-list