473,574 Members | 2,981 Online

# "Updating" lambda functions

Hi,

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:

return lambda x: fu(x) + 17

def mul_3 (fu):
return lambda x: fu(x) * 3

fu = lambda x: x
...
...
fu = mul_3(fu)

That works, but it strikes me as unclean and ugly.
Is there a better way to do it?

Best regards
Oliver

--
Oliver Fromme, Konrad-Celtis-Str. 72, 81369 Munich, Germany

``All that we see or seem is just a dream within a dream.''
(E. A. Poe)
Jul 18 '05 #1
53 3637
On Thu, 16 Sep 2004 14:07:20 +0000, Oliver Fromme wrote:
I need to "update" a lambda function, like this:

That says you need to use classes, not lambda functions.
Jul 18 '05 #2
"Oliver Fromme" <ol**@haluter.f romme.com> wrote in message
news:2q******** *****@uni-berlin.de...

| That works, but it strikes me as unclean and ugly.
| Is there a better way to do it?

I don't like it either. Consider this:
composition = lambda f,g: lambda x: f(g(x))
mul_3 = lambda x: 3*x
fu = lambda x:x
fu(3) 3 fu = composition(add _17,fu)
fu(3) 20 fu = composition(mul _3,fu)
fu(3)

60
Jul 18 '05 #3
On 16 Sep 2004 14:07:20 GMT, Oliver Fromme <ol**@haluter.f romme.com> wrote:
Hi,

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:

return lambda x: fu(x) + 17

def mul_3 (fu):
return lambda x: fu(x) * 3

fu = lambda x: x
...
...
fu = mul_3(fu)

That works, but it strikes me as unclean and ugly.
Is there a better way to do it?

Best regards
Oliver

--
Oliver Fromme, Konrad-Celtis-Str. 72, 81369 Munich, Germany

``All that we see or seem is just a dream within a dream.''
(E. A. Poe)

You could exploit the way functions become bound methods, e.g.,
fu = lambda x: x
fu = (lambda f,x: f(x) + 17).__get__(fu)
fu = (lambda f,x: f(x) * 3).__get__(fu)
fu(1) 54 fu(0) 51 fu(-15) 6 fu(-16) 3 fu(1,2) Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: <lambda>() takes exactly 2 arguments (3 given) fu <bound method ?.<lambda> of <bound method ?.<lambda> of <function <lambda> at 0x008FD8B0>>>

or, you could make a magic function-composing object with magic composing properties,
exploiting the method-making mechanism in a different way, e.g.,
class FC(object): ... def __setattr__(sel f, name, f):
... if not hasattr(self, name): self.__dict__[name] = [f]
... else: self.__dict__[name].append(f)
... def __getattribute_ _(self, name):
... if name == '__dict__': return object.__getatt ribute__(self, '__dict__')
... return type(self).__di ct__['_xfuns'].__get__(
... object.__getatt ribute__(self,n ame))
... def _xfuns(flist, x):
... for f in flist: x = f(x)
... return x
... fc = FC()
fc.fu = lambda x: x
fc.fu = lambda x: x + 17
fc.fu = lambda x: x * 3
fc.fu(1) 54 fc.fu(0) 51 fc.fu(-15) 6 fc.fu(1,2) Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: _xfuns() takes exactly 2 arguments (3 given) fc.bar = lambda x: x*3
fc.bar = lambda x: x+10
fc.bar(0) 10 fc.bar(2) 16 fc.fu(-18)

-3

All just to explore python's features, not to recommend specific uses ;-)

Regards,
Bengt Richter
Jul 18 '05 #4

"Oliver Fromme" <ol**@haluter.f romme.com> wrote in message
news:2q******** *****@uni-berlin.de...
fu = lambda x: x
fu = lambda x: fu(x) + 17

etc

I am curious if there is any reason other that habit carried over from
other languages to not write the above as

def fu(x): return x
def fu(x): return fu(x) + 17
etc

Granted, the latter takes 2 more keystrokes, but the resulting object gets
a proper .name attribute. And, of course, the def form is required for a
multiline body anyway.

(Note: I am not asking about the use of lambda *within* an expression or as
a return value, but only the immediate name-binding of the supposedly
anonymous function where one does not want anonymity.)

Terry J. Reedy

Jul 18 '05 #5
"Terry Reedy" <tj*****@udel.e du> wrote in message
news:ma******** *************** *************** @python.org...

| I am curious if there is any reason other that habit carried over from
| other languages to not write the above as
|
| def fu(x): return x
| def fu(x): return fu(x) + 17
| etc

In my interpreter (IDLE 1.0 on Windows 98) it causes an infinite regress.
Jul 18 '05 #6
Elaine Jackson <elainejackson7 355 <at> home.com> writes:

"Terry Reedy" <tjreedy <at> udel.edu> wrote in message
news:mailman.34 28.1095385637.5 135.python-list <at> python.org...

| I am curious if there is any reason other that habit carried over from
| other languages to not write the above as
|
| def fu(x): return x
| def fu(x): return fu(x) + 17
| etc

In my interpreter (IDLE 1.0 on Windows 98) it causes an infinite regress.

Yes, it will, exactly as the lambda version would have. (And all the
solutions suggested to you for the lambda form are equally applicable to the
def form.) The question is why use the lambda form when you *do* want to bind
your function to a name? Basically,

f = lambda args: body

is equivalent to

def f(args): body

except that the def body is a set of statements (so you have to use 'return'),
and the lambda body is a single expression.

Not that it's coming any time soon, but Python 3000 is supposed to remove
lambda functions, so when you really *do* want to bind a function to a name
(like in your case here), it would probably be a good habit to get into to use

Steve

Jul 18 '05 #7
On Fri, 17 Sep 2004 07:46:12 +0000 (UTC), Steven Bethard <st************ @gmail.com> wrote:
Elaine Jackson <elainejackson7 355 <at> home.com> writes:

"Terry Reedy" <tjreedy <at> udel.edu> wrote in message
news:mailman.34 28.1095385637.5 135.python-list <at> python.org...

| I am curious if there is any reason other that habit carried over from
| other languages to not write the above as
|
| def fu(x): return x
| def fu(x): return fu(x) + 17
| etc

In my interpreter (IDLE 1.0 on Windows 98) it causes an infinite regress.
Yes, it will, exactly as the lambda version would have. (And all the
solutions suggested to you for the lambda form are equally applicable to the
def form.) The question is why use the lambda form when you *do* want to bind
your function to a name? Basically,

f = lambda args: body

is equivalent to

def f(args): body

except that the def body is a set of statements (so you have to use 'return'),
and the lambda body is a single expression.

Yes, but

obj.f = lambda args: body

is possible without an intermediate local binding of f that might clobber a previous f, as in

def f(args): body
obj.f = f
del f # if you want to clean up. But better save the old f in that case?

I'd rather use lambda.

Not that it's coming any time soon, but Python 3000 is supposed to remove
lambda functions, so when you really *do* want to bind a function to a name
(like in your case here), it would probably be a good habit to get into to use

Well, if lambda is removed (or not ;-), I hope an anonymous def expression is allowed,
so we can write

obj.f = def(args):
body
or

obj.f = def(args): body

or

obj.f = (
def(args):
body
) # at or to the left of the def column, for final dedent without special ')' processing.
(where def body indentation is referenced from wherever the def is)

Regards,
Bengt Richter
Jul 18 '05 #8
Bengt Richter <bokr <at> oz.net> writes:
On Fri, 17 Sep 2004 07:46:12 +0000 (UTC), I wrote:

f = lambda args: body

is equivalent to

def f(args): body
Yes, but

obj.f = lambda args: body

is possible without an intermediate local binding of f that might clobber a
previous f

Yeah, I probably should have been clear about that. If 'f' is really just a
name (as it was in my example) the two syntaxes I gave are equivalent. If 'f'
really isn't just a name, then you do still want an anonymous function. In
the OP's example though, 'f' really was just a name.
Well, if lambda is removed (or not , I hope an anonymous def expression is
allowed...

Well, it's come up a number of times (one of the more recent is
http://mail.python.org/pipermail/pyt...e/226714.html), but it
doesn't seem like there was any agreement on (a) what it should look like, or
(b) why having such anonymous defs was such a gain over named defs. If you'd
like to champion a PEP about it... ;)

Steve
Jul 18 '05 #9

"Bengt Richter" <bo**@oz.net> wrote in message
news:ci******** *************** **@theriver.com ...
"Terry Reedy" <tjreedy <at> udel.edu> wrote in message
news:mailman.34 28.1095385637.5 135.python-list <at> python.org...

| I am curious if there is any reason other that habit carried over
from
| other languages to not write the above as
|
| def fu(x): return x
| def fu(x): return fu(x) + 17

obj.f = lambda args: body

is possible without an intermediate local binding of f that might clobber
a previous f, as in

def f(args): body
obj.f = f
del f # if you want to clean up. But better save the old f in that
case?

I'd rather use lambda.

Thanks. I had not thought of this variation. Similar would be
seq[n] = lambda <whatever>

Of course, I *might* prefer being able to write

def obj.f(params): <etc> # and
def seq[n](params): <etc>

Since def is effectively a binding statement, name to function object (like
import, name to module), these seem not entirely unreasonable to me.

Terry J. Reedy

Jul 18 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.