[Python-ideas] Alternative to PEP 532: delayed evaluation of expressions
Brendan Barnwell
brenbarn at brenbarn.net
Mon Nov 7 01:13:18 EST 2016
On 2016-11-06 21:46, Steven D'Aprano wrote:
> I sometimes think that such unevaluated expressions (which I usually
> call "thunks") would be cool to have. But in more realistic moments I
> think that they're a solution looking for a problem to solve.
>
> If your PEP suggests a problem that they will solve, I'm interested.
>
> But note that we already have two ways of generating thunk-like objects:
> functions and compiled byte-code.
>
> thunk = lambda: a + b - c
> thunk()
>
> thunk = compile('a + b - c', '', 'single')
> eval(thunk)
>
> Both are very heavyweight: the overhead of function call syntax is
> significant, and the keyword "lambda" is a lot of typing just to delay
> evaluation of an expression. compile(...) is even worse.
I sometimes want these too. But note that both the solutions you
propose are quite a ways from a true "unevaluated expression".
The big problem with an ordinary lambda (or def) is that you cannot
explicitly control where it will decide to look for its free variables.
If it uses a local variable from an enclosing namespace, it will
always look for it in that namespace, so you can't "patch in" a value by
setting a global variable. If it uses a variable that isn't local to
any enclosing namespace, it will always look for it in the global
namespace, so you can't patch in a value by setting a local variable in
the context where you're calling the function.
You can get around this in a def by, for instance, using global to mark
all variables global, and then using eval to pass in a custom global
namespace. But that is a lot of boilerplate. What I want (when I want
this) is a way to create a function that will allow the injection of
values for *any* variables, regardless of whether the function
originally thought they were local, nonlocal (i.e., local to some
enclosing scope) or global. The way it is now, the status of a
function's variables is inextricably linked to the syntactic context
where it was defined. This is a good thing most of the time, but it's
not what you want if you want to define an expression that should later
be evaluated in some other context.
I consider the compile-based solution a nonstarter, because it puts the
code in a string. With the code in a string, you are blocked from using
syntax highlighting or any other handy editor features.
--
Brendan Barnwell
"Do not follow where the path may lead. Go, instead, where there is no
path, and leave a trail."
--author unknown
More information about the Python-ideas
mailing list