Guido van Rossum:
-- but it's more efficient, since calling yield doesn't create a frame.
Neither should a thunk.
The other problem with thunks is that once we think of them as the anonymous functions they are, we're pretty much forced to say that a return statement in a thunk returns from the thunk rather than from the containing function.
Why should a thunk be a function? We already have first class functions. What we're missing is a way to pass around a suite.
def foo(a): if a > 4: b = a c = process(a) # thunk line 1 print a # thunk line 2 return # thunk line 3 else: a.something()
We don't have a good way to package up "c = process(a); print a; return"
The return should exit the whole function, not just (part of) the if clause.
I'd like to reconsider a thunk implementation. It would be a lot simpler, doing just what is required without any jiggery pokery with exceptions and break/continue/return statements. It would be easy to explain what it does and why it's useful.
I don't know. In order to obtain the required local variable sharing between the thunk and the containing function I believe that every local variable used or set in the thunk would have to become a 'cell' (our mechanism for sharing variables between nested scopes).
Cells only work if you have a complete set of names at compile-time. Your own resource-example added "item" to the namespace inside a block. If you don't know which blocks could be used with a pattern, cells are out.
That said, the compiler code is already two-pass. Once to find names, and another time to resolve them. This just means that for thunks (and functions that call them) the adjustment will be to LOAD_NAME instead of getting a LOAD_FAST index.