"Updating" lambda functions
Robert Brewer
fumanchu at amor.org
Thu Sep 16 17:19:36 CEST 2004
Oliver Fromme wrote:
> I'm trying to write a Python function that parses
> an expression and builds a function tree from it
> (recursively).
>
> During parsing, lambda functions for the the terms
> and sub-expressions are constructed on the fly.
> Now my problem is lazy evaluation. Or at least I
> think it is. :-)
>
> I need to "update" a lambda function, like this:
>
> fu = lambda x: x
> ...
> fu = lambda x: fu(x) + 17
> ...
> fu = lambda x: fu(x) * 3
>
> Of course that doesn't work, because fu is resolved
> when the lambda is called, not when it's defined, so
> I'll run into an endless recursion.
>
> My current solution is to define a helper function
> which passes the lambda through its argument:
>
> def add_17 (fu):
> return lambda x: fu(x) + 17
>
> def mul_3 (fu):
> return lambda x: fu(x) * 3
>
> fu = lambda x: x
> ...
> fu = add_17(fu)
> ...
> fu = mul_3(fu)
>
> That works, but it strikes me as unclean and ugly.
> Is there a better way to do it?
Two approaches, both using bytecode hacks, so they are CPython-specific:
One, if all your use cases are simple, wrap the lambda in an object,
then override __mul__ and __add__, etcetera, for that object. Then
write:
>>> fu = Expression(lambda x: x)
>>> fu2 = fu + 17
>>> fu2
Expression(lambda x: x + 17)
>>> fu3 = fu2 * 3
>>> fu3
Expression(lambda x: (x + 17) * 3)
See my http://www.aminus.org/rbre/python/logic.py for an example of
wrapping lambdas. I override __add__ there to 'logical and' two
expressions together, so that fu + fu2 => fu and fu2.
Two, bind early. See
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/277940. That
solution only binds globals, but you can extend it to handle function
calls. Then special-case expr() inside the lambda, replacing it with the
existing expression. See my
http://www.aminus.org/rbre/python/codewalk.py for some examples of
binding more, earlier.
>>> fu = Expression(lambda x: x)
>>> fu2 = Expression(lambda x: expr(fu) + 17)
>>> fu2
Expression(lambda x: x + 17)
>>> fu3 = Expression(lambda x: expr(fu2) * 3)
>>> fu3
Expression(lambda x: (x + 17) * 3)
Robert Brewer
MIS
Amor Ministries
fumanchu at amor.org
More information about the Python-list
mailing list