|
7 | 7 | from functools import wraps |
8 | 8 |
|
9 | 9 | from unpythonic.misc import immediate |
10 | | -from unpythonic._let_support import env |
| 10 | +from unpythonic._let_support import env as _env |
11 | 11 |
|
12 | 12 | def let(body, **bindings): |
13 | 13 | """``let`` expression. |
@@ -128,11 +128,12 @@ def letrec(body, **bindings): |
128 | 128 |
|
129 | 129 | def _let(mode, body, **bindings): |
130 | 130 | assert mode in ("let", "letrec") |
131 | | - e = env(**bindings) |
| 131 | + env = _env(**bindings) |
132 | 132 | if mode == "letrec": # supply the environment instance to the letrec bindings. |
133 | | - for k in e: |
134 | | - e[k] = e[k](e) |
135 | | - return body(e) |
| 133 | + for k in env: |
| 134 | + env[k] = env[k](env) |
| 135 | + # decorators need just the final env; else run body now |
| 136 | + return env if body is None else body(env) |
136 | 137 |
|
137 | 138 | # decorator factory: almost as fun as macros? |
138 | 139 | def dlet(**bindings): |
@@ -173,10 +174,7 @@ def deco(body): |
173 | 174 | # evaluate env when the function def runs! |
174 | 175 | # (so that any mutations to its state are preserved |
175 | 176 | # between calls to the decorated function) |
176 | | - e = env(**bindings) |
177 | | - if mode == "letrec": # supply the environment instance to the letrec bindings. |
178 | | - for k in e: |
179 | | - e[k] = e[k](e) |
| 177 | + e = _let(mode, body=None, **bindings) |
180 | 178 | @wraps(body) |
181 | 179 | def decorated(*args, **kwargs): |
182 | 180 | kwargs_with_env = kwargs.copy() |
@@ -232,7 +230,7 @@ def see(x): |
232 | 230 |
|
233 | 231 | # context manager only |
234 | 232 | def f3(lst): |
235 | | - with env(seen = set()) as myenv: |
| 233 | + with _env(seen = set()) as myenv: |
236 | 234 | return [myenv.seen.add(x) or x for x in lst if x not in myenv.seen] |
237 | 235 | # myenv still lives due to Python's scoping rules. |
238 | 236 | # This is why we provide a separate let construct |
|
0 commit comments