Joe Mason said:
I still don't see the advantage over
def test():
def my_func(x, y):
assert(y == x * 2)
for (x, y) in [(1,2), (2,4), (3,6)]:
my_func(x, y)
In this particular example, there's no advantage to using codeblocks
over functions. However, dynamically scoped blocks would facilitate a
range of things that are difficult to do with functions, particularly
in the metaprogramming arena. If you're trying to write code that
writes code, it's really handy to have blocks that execute in the
current scope instead of in a new one.
If dynamically scoped blocks were added to the language, it would give
metaprogrammers a much cleaner syntax that could replace a lot of
exec, eval, and compile calls, not to mention it would reduce the need
to tinker directly with frames.
.... Speaking of which, it's too bad that Glenn's sys._getframe() hack
doesn't quite work. Can anybody figure a way to inject locals created
these "blocks" back into the calling frame's locals? Illustration of
the problem-
class block:
def __init__(self, f):
self.f = f
def __call__(self):
import sys
exec self.f.func_code in sys._getframe(1).f_locals
def next_fibonacci_term():
fibonacci_sequence.append(fibonacci_sequence[-2] +
fibonacci_sequence[-1])
i = len(fibonacci_sequence) - 1
nft_block = block(next_fibonacci_term)
fibonacci_sequence = [0,1]
[nft_block() for n in range(20)]
print fibonacci_sequence
# [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987,
1597, 2584, 4181, 6765, 10946]
print i
# Traceback (most recent call last):
# File "<stdin>", line 1, in ?
# NameError: name 'i' is not defined
Conclusion-
"exec foo in scope" appears to execute foo in a _copy_ of scope, s.t.
we can modify objects that are contained in the scope, but assignment
won't work.