473,507 Members | 2,395 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

better lambda support in the future?

I'm wondering why python still has limited lambda support. What's
stopping the developers of python to support more lisp-like lambda function?
Jul 18 '05 #1
31 1606
Lambda functions will become obsolette in the nearest future. This is
the PLAN.

Jul 18 '05 #2
Jason Zheng wrote:
I'm wondering why python still has limited lambda support. What's
stopping the developers of python to support more lisp-like lambda
function?


This comes up every few weeks on the list. If you haven't already,
check the archives in Google for 'anonymous def' or 'anonymous
function'. The usual response to this question is something along the
lines of "if it's good enough to create a function for, it's good enough
to name".

One of the other big reasons for this type of proposal never making it
far is that, so far, no one has found a syntax that everyone (or even
most people) like. You end up with things like:

x = func or lambda x, y:
# body of lambda func
# indented here

or

x = func or lambda x, y:
# body of lambda func
# indented here

or

x = func or lambda x, y {
# body of lamda func indented
# however you want...
}

or any thousand other varieties.

Even if you could settle the syntax issue, once you've decided that you
really do need a true block in an anonymous function, you're not really
saving much space by not declaring it:

def f(*args):
# body line 1
# body line 2
# ...
# body line N
x = func or f

v.s.

x = func or lambda *args:
# body line 1
# body line 2
# ...
# body line N

so, you save a single line, which is only 1 Nth of the size of your
function (where N is the number of lines in your function body). For a
single or double line function, these savings may be more substantial,
but chances are if your function is only one or two lines, it can be
written as an expression anyway (e.g. using LCs or GEs)...
Do check the archives -- there are a lot of discussions on this topic,
but hopefully the brief commentary above will give you something of an
overview.

Steve
Jul 18 '05 #3
Steven Bethard wrote:
Even if you could settle the syntax issue, once you've decided that you really do need a true
block in an anonymous function, you're not really saving much space by not declaring it:

def f(*args):
# body line 1
# body line 2
# ...
# body line N
x = func or f

v.s.

x = func or lambda *args:
# body line 1
# body line 2
# ...
# body line N


you meant:

def x(*args):
# body line 1
# body line 2
# ...
# body line N

v.s.

x = func or lambda *args:
# body line 1
# body line 2
# ...
# body line N

right?

</F>

Jul 18 '05 #4
Fredrik Lundh wrote:
Steven Bethard wrote:

Even if you could settle the syntax issue, once you've decided that you really do need a true
block in an anonymous function, you're not really saving much space by not declaring it:

def f(*args):
# body line 1
# body line 2
# ...
# body line N
x = func or f

v.s.

x = func or lambda *args:
# body line 1
# body line 2
# ...
# body line N

you meant:

def x(*args):
# body line 1
# body line 2
# ...
# body line N

v.s.

x = func or lambda *args:
# body line 1
# body line 2
# ...
# body line N

right?


You're welcome to name the function whatever you want -- notice in my
example that the function is used in the statement:

x = func or f

If you'd prefer the statement to read:

x = func or x

that's also fine. Depends on what exactly 'x' is, and whether or not it
really makes sense for the function I called 'f' to have the same name
as the variable called 'x'. It certainly may, but since I wasn't giving
real code, I didn't want to commit to that.

Perhaps a better example would have been something along the lines of:

dict(a=lambda *args:
# body 1
,
b=lambda *args:
# body 2
,
c=lambda *args:
# body 3
)[s](values)

v.s.

def a_func(*args):
# body 1
def b_func(*args):
# body 2
def c_func(*args):
# body 3
dict(a=a_func, b=b_func, c=c_func)[s](values)

where it's clear that I'm trying to use lambdas where expressions are
required.

I assume that the point you were trying to make is that:

def f(*args):
return expr

is equivalent to

f = lambda *args: expr

?

Steve
Jul 18 '05 #5
True enough, but suppose you want a hash of anonymous functions as
opposed to just a lexical? This is where lambas are nice to have.
Totally agreed about a small use here and there, but they do have some
use in dispatch tables, as they are a lot easier to read sometimes
than very long case statements. Of course, this would require
multi-line lambdas to exist...

--Michael
I assume that the point you were trying to make is that:

def f(*args):
return expr

is equivalent to

f = lambda *args: expr

?

Steve
--
http://mail.python.org/mailman/listinfo/python-list

Jul 18 '05 #6
Steven Bethard wrote:
You're welcome to name the function whatever you want -- notice in my example that the function is
used in the statement:

x = func or f

If you'd prefer the statement to read:

x = func or x

that's also fine. Depends on what exactly 'x' is, and whether or not it really makes sense for
the function I called 'f' to have the same name as the variable called 'x'. It certainly may, but
since I wasn't giving real code, I didn't want to commit to that.
if you write "def f", "f" is a variable, just like "x". "def" is an assignment
statement.

I'm not sure what "func" is supposed to be in your examples...
I assume that the point you were trying to make is that:

def f(*args):
return expr

is equivalent to

f = lambda *args: expr

?

def f(): .... return 1+2
.... g = lambda: 1 + 2
type(f) <type 'function'> type(g) <type 'function'>
import dis
dis.dis(f) 2 0 LOAD_CONST 1 (1)
3 LOAD_CONST 2 (2)
6 BINARY_ADD
7 RETURN_VALUE dis.dis(g) 1 0 LOAD_CONST 1 (1)
3 LOAD_CONST 2 (2)
6 BINARY_ADD
7 RETURN_VALUE
dir(f) ['__call__', '__class__', '__delattr__', '__dict__', '__doc__', '__get__', '__ge
tattribute__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__r
educe__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', 'func_closure',
'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_na
me'] dir(g) ['__call__', '__class__', '__delattr__', '__dict__', '__doc__', '__get__', '__ge
tattribute__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__r
educe__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', 'func_closure',
'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_na
me']
f.func_name 'f' g.func_name

'<lambda>'

</F>

Jul 18 '05 #7
Fredrik Lundh wrote:
I'm not sure what "func" is supposed to be in your examples...


Just an extra variable used to make sure that the lambda was being used
in a context (i.e. in an expression) where a simple def wouldn't
suffice. If the example is confusing, consider the dict example
instead. It makes it clearer that the lambdas are being used in places
where an expression is required.

Steve
Jul 18 '05 #8
Michael DeHaan wrote:
True enough, but suppose you want a hash of anonymous functions as
opposed to just a lexical?
I've seen at least one reasonable example of this kind of thing:

http://mail.python.org/pipermail/pyt...er/245432.html

Though I haven't yet seen an example that actually required lambdas with
blocks...
Totally agreed about a small use here and there, but they do have some
use in dispatch tables, as they are a lot easier to read sometimes
than very long case statements. Of course, this would require
multi-line lambdas to exist...


Certainly in the example above, I'd be willing to agree that the lambdas
are at least as readable as a buch of def's above would have been. I'm
not sure if multi-line lambdas would be as readable though... It all
depends on what syntax you write them in -- you can see the struggle I
went through in my other message... Where do I put the commas in a
dict? Can't be at the end of the lambda or they turn the last
expression into a tuple... I resorted to putting them on a separate
line, but of course there are other solutions.
If you have a good example of where you'd like to use multi-line
lambdas, in, say, a dispatch table, I'd like to take a look at how you'd
like to write them. I'm not yet convinced that there really is a
readable way to write such things...

Steve
Jul 18 '05 #9
Steven Bethard wrote:
Jason Zheng wrote:
I'm wondering why python still has limited lambda support. What's
stopping the developers of python to support more lisp-like lambda
function?

This comes up every few weeks on the list. If you haven't already,
check the archives in Google for 'anonymous def' or 'anonymous
function'. The usual response to this question is something along the
lines of "if it's good enough to create a function for, it's good enough
to name".


The true beauty of lambda function is not the convenience of creating
functions without naming them. Lambda constructs truly enables
higher-order function. For example, I can create a function A that
returns a function B that does something interesting according to the
arguments that I pass to function A.
Jul 18 '05 #10
Michael DeHaan wrote:
True enough, but suppose you want a hash of anonymous functions as
opposed to just a lexical? This is where lambas are nice to have.
Totally agreed about a small use here and there, but they do have some
use in dispatch tables, as they are a lot easier to read sometimes
than very long case statements.


standard pattern:

dispatch = {}

def handle_a(...):
...
dispatch["a"] = handle_a

def handle_b(...):
...
dispatch["b"] = handle_b

def handle_c(...):
...
dispatch["c"] = handle_c

if you cannot think of a suitable name for a given case, you can
name them all "case". for further encapsulation, you can put this
in a class definition; dispatch will then become a dictionary con-
taining unbound methods. if the case names all happen to be valid
Python literals, you can get rid of the dispatch dictionary, and use
getattr(self, "handle_" + case) to locate the right bound method (or
if speed is important, use dir() to preload a dispatch dictionary with
handlers). etc.

</F>

Jul 18 '05 #11
Jason Zheng wrote:
The true beauty of lambda function is not the convenience of creating
functions without naming them. Lambda constructs truly enables
higher-order function. For example, I can create a function A that
returns a function B that does something interesting according to the
arguments that I pass to function A.


Like this?

def A(*args, **kwds):
def B():
print args, kwds
return B

But you don't need lambdas to do this. In fact, even in your email,
you'll note that you referred to your two functions by name. If you're
naming functions, why not use a def statement?

Steve
Jul 18 '05 #12
Steven Bethard wrote:
I've seen at least one reasonable example of this kind of thing:

http://mail.python.org/pipermail/pyt...er/245432.html


the code he's referring to doesn't seem to use that construct anymore, so
it's not obvious what "dejavu.icontains" etc really is, but assuming they're
strings, the following is a reasonable lambda-free alternative:

class xforms:
def icontains(self, x, y): return x + " Like '%" + y[1:-1] + "%'"
def icontainedby(self, x, y):
# icontainedby body goes here instead of in a separate function
def istartswith(self, x, y): return x + " Like '" + y[1:-1] + "%'"
def iendswith(self, x, y): return x + " Like '%" + y[1:-1] + "'"
def ieq(self, x, y): return x + " = " + y
def now(self): return "Now()"
def today(self): return "DateValue(Now())",
def year(self, x): return "Year(" + x + ")"
def dispatch(self, tag, *args):
return getattr(self, tag)(*args)

here's another "reasonable example", btw:

http://groups-beta.google.com/group/...462b89a490a6ac

this too could be rewritten to use a class (combined with re.sub and
a callback, most likely).

</F>

Jul 18 '05 #13
Jason Zheng wrote:
The true beauty of lambda function is not the convenience of creating
functions without naming them. Lambda constructs truly enables
higher-order function. For example, I can create a function A that
returns a function B that does something interesting according to the
arguments that I pass to function A.


How does that differ from this?
def A(x): .... if x:
.... def B(): return "True"
.... else:
.... def B(): return "False"
.... return B
.... A(1) <function B at 0xa0c65dc> _() 'True' A(0) <function B at 0xa0c65dc> _()

'False'
--
Michael Hoffman
Jul 18 '05 #14
Fredrik Lundh wrote:
Steven Bethard wrote:
I've seen at least one reasonable example of this kind of thing:

http://mail.python.org/pipermail/pyt...er/245432.html


the code he's referring to doesn't seem to use that construct anymore, so
it's not obvious what "dejavu.icontains" etc really is, but assuming they're
strings, the following is a reasonable lambda-free alternative:

class xforms:
def icontains(self, x, y): return x + " Like '%" + y[1:-1] + "%'"
def icontainedby(self, x, y):
# icontainedby body goes here instead of in a separate function
def istartswith(self, x, y): return x + " Like '" + y[1:-1] + "%'"
def iendswith(self, x, y): return x + " Like '%" + y[1:-1] + "'"
def ieq(self, x, y): return x + " = " + y
def now(self): return "Now()"
def today(self): return "DateValue(Now())",
def year(self, x): return "Year(" + x + ")"
def dispatch(self, tag, *args):
return getattr(self, tag)(*args)


This doesn't work if the strings aren't valid Python identifiers (e.g.
"!CONTAINS!"). On the other hand, if they are (and you can be
guaranteed that they will continue to be), then your solution above is
nice, though if you want to fully reproduce the behavior, you probably
also want the method

def __getitem__(self, item):
return getattr(self, item)

Steve
Jul 18 '05 #15

"Jason Zheng" <jz****@jpl.nasa.gov> wrote in message
news:cp**********@nntp1.jpl.nasa.gov...
Steven Bethard wrote:
Jason Zheng wrote:
I'm wondering why python still has limited lambda support. What's
stopping the developers of python to support more lisp-like lambda
function?

They already have: given the fundamental syntax difference between all
expressions and expressions within statements, def statements are at least
the equivalent of lisp lambdas + name binding. When you get an exception
traceback, a unique name is more helpful than the pseudoname <lambda>.
Isolating the definition of a function in a separate statement also makes
it possible to unittest the function.
This comes up every few weeks on the list. If you haven't already,
check the archives in Google for 'anonymous def' or 'anonymous
function'. The usual response to this question is something along the
lines of "if it's good enough to create a function for, it's good enough
to name".

What puzzles me is 1) why some people apparently think anonymity is good --
is it really that hard to name non-trivial functions? and 2) why some
people are so quick to recommend changes to Python before they understand
what they can already do (wth def statements, in this case).
The true beauty of lambda function is not the convenience of creating
functions without naming them. Lambda constructs truly enables
higher-order function.
And so do Python def statements coupled with Python design principles. In
Python at least, the beauty of first-class functions has nothing to do with
'lambda'.
For example, I can create a function A that returns a function B that
does something interesting according to the arguments that I pass to
function A.


Golly gee. Pythoneers have done this with def for at least a decade, if
not from the very beginning.

Terry J. Reedy

Jul 18 '05 #16
Steven Bethard wrote:
Jason Zheng wrote:
The true beauty of lambda function is not the convenience of creating
functions without naming them. Lambda constructs truly enables
higher-order function. For example, I can create a function A that
returns a function B that does something interesting according to the
arguments that I pass to function A.

But you don't need lambdas to do this. In fact, even in your email,
you'll note that you referred to your two functions by name. If
you're naming functions, why not use a def statement?

It occurs to me that, in a statically compiled language, function
definitions all happen before the program starts, and thus that
definition can't be affected by other variables (i.e. an outer
function's parameters). In such statically compiled language, a lambda
would be very useful simply because it's a *dynamic* function. Of
course, in Python *all* functions are created dynamically, therefore
(unlike most other languages) the majority of the benefits of lambdas
already apply to standard Python functions.

In the couple of years that I've been puzzling over why some people were
so fixated upon lambdas as being essential, this hasn't occurred to me
before. They really provide scant benefit in Python (which is why I was
puzzled by the devotion to them), but they *do* provide a large benefit
in other languages. It is, however, quite easy to miss that this
relative weakness of Python lambdas is a direct consequence of the fact
that a function def is an executable statement rather than a
compilation-time declaration.

Jeff Shannon
Technician/Programmer
Credit International

Jul 18 '05 #17
Jeff Shannon wrote:
It occurs to me that, in a statically compiled language, function
definitions all happen before the program starts, and thus that
definition can't be affected by other variables (i.e. an outer
function's parameters).


I think you might be confusing static compilation in a language with
lack of first-class functions in a language. OCaml is compiled, but
functions are first class objects, and nested scopes are accessible:

# let f x =
let g y =
x + y
in
g;;
val f : int -> int -> int = <fun>
# f(1);;
- : int -> int = <fun>
# f(1)(2);;
- : int = 3

Note that the type of f is a function that takes an int and returns a
function that takes an int and returns an int. OCaml handles nested
scopes appropriately, and successfully compiles the function f (and
infers the appropriate types). So the issue is not static compilation,
but functions as first class objects.

Of course, many statically compiled languages, e.g. C, C++, Java, do not
provide functions as first class objects, so the confusion is not
unnatural...

Steve
Jul 18 '05 #18
Steven Bethard wrote:
Jeff Shannon wrote:
It occurs to me that, in a statically compiled language, function
definitions all happen before the program starts, and thus that
definition can't be affected by other variables (i.e. an outer
function's parameters).

I think you might be confusing static compilation in a language with
lack of first-class functions in a language.

Hm, possibly. I must confess that my direct knowledge is limited to a
fairly narrow set of languages, and that C and C++ are the only
statically-compiled languages I've used. Still, I'm not sure that it's
just a matter of functions as first-class objects. Would OCaml (or some
other static language) have something that's equivalent to this?

def f(x):
if x < 0:
def g(y):
return y * -1
else:
def g(y):
return y
return g

foo = f(1)

Here, nested scopes are not enough. Only one of these functions is
created, and which one that is depends on the run-time value of the
function parameter. A compiler couldn't know this ahead of time. I
suppose it might be able to do something by compiling both of them,
(though I'm not sure how it'd track two different functions with the
same name in the same namespace...) but that seems a bit questionable to
me...

Jeff Shannon
Technician/Programmer
Credit International

Jul 18 '05 #19
Jeff Shannon <je**@ccvcorp.com> writes:
Steven Bethard wrote:
Hm, possibly. I must confess that my direct knowledge is limited to a
fairly narrow set of languages, and that C and C++ are the only
statically-compiled languages I've used. Still, I'm not sure that
it's just a matter of functions as first-class objects. Would OCaml
(or some other static language) have something that's equivalent to
this?

def f(x):
if x < 0:
def g(y):
return y * -1
else:
def g(y):
return y
return g

foo = f(1)


This is really no different than:

def f(x):
if x < 0:
g = -y
else:
g = y
return g

The only difference is that you're binding the variable g to a y type
instead of a function type. That's what "first class functions"
means. You can treat functions like any other object, assign them to
variables, pass them as parameters, and so on.

<mike
--
Mike Meyer <mw*@mired.org> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Jul 18 '05 #20
On 2004-12-18, Jeff Shannon <je**@ccvcorp.com> wrote:
Would OCaml (or some
other static language) have something that's equivalent to this?

def f(x):
if x < 0:
def g(y):
return y * -1
else:
def g(y):
return y
return g

foo = f(1)
Sure. You can't change a binding, but you can make it conditional:

let f x =
if x < 0
then let g y = y * -1 in g
else let g y = y in g

Idiomatic OCaml code would use a lambda (fun y -> y * -1), but it
doesn't have to, and that would just confuse the issue.
I suppose it might be able to do something by compiling both of them,
(though I'm not sure how it'd track two different functions with the
same name in the same namespace...) but that seems a bit questionable to
me...


Both languages compile all three functions (f and the two versions of
g) once and choose which g to return at run-time. You can see this in
Python by examining the code object for f:
f.func_code.co_consts

(None, 0, <code object g at 1c8120, file "<stdin>", line 3>,
<code object g at 1cd1a0, file "<stdin>", line 6>)

The last two elements are the variants of g. At run-time, one of them
is loaded, made into a real function, and returned. All defs and
lambdas are compiled only once when the module is loaded even if they
depend on the environment or are referenced dynamically.

You can do this even in C (untested):

typedef int fun(int);
int g1(int y) { return y * -1; }
int g2(int y) { return y; }
fun *f(int x)
{
return x < 0 ? g1 : g2;
}

C doesn't have language support for closures, though, so we end up
manually passing around (fun, arg) if we need free variables, but
there's nothing inherently dynamic about higher-order functions.
Jul 18 '05 #21
On Fri, 17 Dec 2004 22:56:08 +0100, "Fredrik Lundh" <fr*****@pythonware.com> wrote:
Michael DeHaan wrote:
True enough, but suppose you want a hash of anonymous functions as
opposed to just a lexical? This is where lambas are nice to have.
Totally agreed about a small use here and there, but they do have some
use in dispatch tables, as they are a lot easier to read sometimes
than very long case statements.


standard pattern:

dispatch = {}

def handle_a(...):
...
dispatch["a"] = handle_a

def handle_b(...):
...
dispatch["b"] = handle_b

def handle_c(...):
...
dispatch["c"] = handle_c

if you cannot think of a suitable name for a given case, you can
name them all "case". for further encapsulation, you can put this
in a class definition; dispatch will then become a dictionary con-
taining unbound methods. if the case names all happen to be valid
Python literals, you can get rid of the dispatch dictionary, and use
getattr(self, "handle_" + case) to locate the right bound method (or
if speed is important, use dir() to preload a dispatch dictionary with
handlers). etc.

Looks like your standard pattern could be updated:
dispatch = {}

def dispvia(name): ... def _(f, name=name):
... dispatch[name] = f
... return f
... return _
... @dispvia('a') ... def handle_a(): pass
... @dispvia('b') ... def handle_b(): pass
... @dispvia('c') ... def handle_c(): pass
... for t in sorted(dispatch.items()): print '%5s: %r'%t ...
a: <function handle_a at 0x02EE8E9C>
b: <function handle_b at 0x02EE8ED4>
c: <function handle_c at 0x02EE8F0C>

Had to try this experiment:
dispatch = {}
def dispvia(name): ... def _(f, name=name):
... dispatch[name] = f
... return dispatch
... return _
... @dispvia('a') ... def dispatch(): return 'dispatched a'
... @dispvia('b') ... def dispatch(): return 'dispatched b'
... @dispvia('c') ... def dispatch(): return 'dispatched c'
... for t in sorted(dispatch.items()): print '%5s: %r'%t ...
a: <function dispatch at 0x02EE8F44>
b: <function dispatch at 0x02EE8F7C>
c: <function dispatch at 0x02EE8FB4> for k in dispatch: print dispatch[k](), ...
dispatched a dispatched c dispatched b for k in sorted(dispatch): print dispatch[k](),

...
dispatched a dispatched b dispatched c

Hm... this seems like an interesting opening ;-)

Regards,
Bengt Richter
Jul 18 '05 #22

"Dima Dorfman" <di**@trit.invalid> wrote in message
news:sl******************@beaver.trit.org...
Both languages compile all three functions (f and the two versions of
g) once and choose which g to return at run-time.
*If* OCaml or any other 'other' language compiles the two versions of g to
the final and complete functions that get returned (but I don't know if
that is so for OCaml or and other appropriate 'other'), then it does
something different from and less flexible than Python.
You can see this in Python by examining the code object for f:
>>> f.func_code.co_consts
(None, 0, <code object g at 1c8120, file "<stdin>", line 3>,
<code object g at 1cd1a0, file "<stdin>", line 6>)


It is important that these are code objects, not function objects.
The last two elements are the variants of g. At run-time, one of them
is loaded, made into a real function, and returned. All defs and
lambdas are compiled only once when the module is loaded even if they
depend on the environment or are referenced dynamically.


This is a CPython optimization which, I believe, is not part of the
language def itself -- but any sensible computer implementation should do
something like it.

The final wrapping of the code object by a function object must be done at
runtime because the defaulf arg evaluation and enclosing variable capture
happen on each call of the outer function and because each call therefore
returns a different function object -- though each uses the same code
object (or, in the case discussed, one of the same two code objects).

Terry J. Reedy

Jul 18 '05 #23

"Bengt Richter" <bo**@oz.net> wrote in message
news:41****************@news.oz.net...
Looks like your standard pattern could be updated:
dispatch = {}

def dispvia(name): ... def _(f, name=name):
... dispatch[name] = f
... return f
... return _
... @dispvia('a') ... def handle_a(): pass
... @dispvia('b') ... def handle_b(): pass
... @dispvia('c') ... def handle_c(): pass
... for t in sorted(dispatch.items()): print '%5s: %r'%t

...
a: <function handle_a at 0x02EE8E9C>
b: <function handle_b at 0x02EE8ED4>
c: <function handle_c at 0x02EE8F0C>


To avoid the redundancy of 'a' and '_a', etc, how about (untested):

def dispvia(f):
dispatch[f.__name__.split('_')[1]] = f
return f

? (Don't have 2.4 loaded yet)

Terry J. Reedy

Jul 18 '05 #24
Terry Reedy wrote:
To avoid the redundancy of 'a' and '_a', etc, how about (untested):

def dispvia(f):
dispatch[f.__name__.split('_')[1]] = f
return f


A similar idea:

Py> class DispatchTable(dict):
.... def __init__(self, prefix=""):
.... self._prefix = prefix
.... self._ignored = len(prefix)
.... def registerAs(self, name):
.... def _ (f):
.... self[name] = f
.... return f
.... return _
.... def register(self, f):
.... name = f.__name__
.... _ignored = self._ignored
.... if name[:_ignored] == self._prefix:
.... name = name[_ignored:]
.... self[name] = f
.... return f
....
Py> dispatcher = DispatchTable("handle_")
Py> @dispatcher.register
.... def handle_a(): pass
....
Py> @dispatcher.register
.... def b(): pass
....
Py> @dispatcher.registerAs("c")
.... def f(): pass
....
Py> for t in sorted(dispatcher.items()): print '%5s: %r'%t
....
a: <function handle_a at 0x009D8930>
b: <function b at 0x009D85B0>
c: <function f at 0x009D8830>

--
Nick Coghlan | nc******@email.com | Brisbane, Australia
---------------------------------------------------------------
http://boredomandlaziness.skystorm.net
Jul 18 '05 #25
On 2004-12-18, Terry Reedy <tj*****@udel.edu> wrote:

"Dima Dorfman" <di**@trit.invalid> wrote in message
news:sl******************@beaver.trit.org...
Both languages compile all three functions (f and the two versions of
g) once and choose which g to return at run-time.


*If* OCaml or any other 'other' language compiles the two versions of g to
the final and complete functions that get returned (but I don't know if
that is so for OCaml or and other appropriate 'other'), then it does
something different from and less flexible than Python.


Sorry, I glossed over the details to convey the general idea. In
OCaml, as in Python, the code is compiled once but the closure is made
at run-time.

# f 3 == f 3;;
- : bool = false

where "==" is the physical equality operator like Python's "is".
Jul 18 '05 #26
On Sat, 18 Dec 2004 03:05:08 -0500, "Terry Reedy" <tj*****@udel.edu> wrote:

"Bengt Richter" <bo**@oz.net> wrote in message
news:41****************@news.oz.net...
Looks like your standard pattern could be updated:
>>> dispatch = {}
>>>
>>> def dispvia(name):

... def _(f, name=name):
... dispatch[name] = f
... return f
... return _
...
>>> @dispvia('a')

... def handle_a(): pass
...
>>> @dispvia('b')

... def handle_b(): pass
...
>>> @dispvia('c')

... def handle_c(): pass
...
>>> for t in sorted(dispatch.items()): print '%5s: %r'%t

...
a: <function handle_a at 0x02EE8E9C>
b: <function handle_b at 0x02EE8ED4>
c: <function handle_c at 0x02EE8F0C>


To avoid the redundancy of 'a' and '_a', etc, how about (untested):

def dispvia(f):
dispatch[f.__name__.split('_')[1]] = f
return f

? (Don't have 2.4 loaded yet)


That should work. Didn't want to retype ;-) I just wanted to get
to the experiment following -- did you notice that it takes the assignment
name from each "def dispatch ...", but it is actually re-assigning the returned dispatch
*dict* as the value, not a modified function? So no function was bound to any local name at
any time. Kind of faking the lambda thing, and allowing non-identifier keys if desired. E.g.,
dispatch = {}
def dispvia(name): ... def _(f, name=name):
... f.__name__ = repr(repr(name))
... dispatch[name] = f
... return dispatch
... return _
... for k in xrange(3): ... @dispvia(k)
... def dispatch(key=k): return key
... for t in sorted(dispatch.items()): print '%5r: %r' % t ...
0: <function '0' at 0x02EE8DBC>
1: <function '1' at 0x02EE8DF4>
2: <function '2' at 0x02EE8E2C> for t in sorted(dispatch.items()): print '%r() => %r' % (t[1], t[1]()) ...
<function '0' at 0x02EE8DBC>() => 0
<function '1' at 0x02EE8DF4>() => 1
<function '2' at 0x02EE8E2C>() => 2

Sort of the effect of
dispatch2 = dict((k,lambda key=k:key) for k in xrange(3))
for t in sorted(dispatch2.items()): print '%20r:%r'%t ...
0:<function <lambda> at 0x02EE8FB4>
1:<function <lambda> at 0x02EF402C>
2:<function <lambda> at 0x02EF409C>

Oops, well it's not so pretty if you want to rename the lambdas in the same expression:
dispatch2 = dict((k, setattr(f, '__name__', repr(repr(k)))or f) for k,f in ((k,lambda key=k:key) for k in xrange(3)))
for t in sorted(dispatch2.items()): print '%20r:%r'%t ...
0:<function '0' at 0x02EE8FB4>
1:<function '1' at 0x02EF402C>
2:<function '2' at 0x02EF4064> for t in sorted(dispatch.items()): print '%r() => %r' % (t[1], t[1]())

...
<function '0' at 0x02EE8DBC>() => 0
<function '1' at 0x02EE8DF4>() => 1
<function '2' at 0x02EE8E2C>() => 2

;-/

Regards,
Bengt Richter
Jul 18 '05 #27

"Bengt Richter" <bo**@oz.net> wrote in message
news:41****************@news.oz.net...
On Sat, 18 Dec 2004 03:05:08 -0500, "Terry Reedy" <tj*****@udel.edu>
wrote:
To avoid the redundancy of 'a' and '_a', etc, how about (untested):

def dispvia(f):
dispatch[f.__name__.split('_')[1]] = f
return f
That should work. Didn't want to retype ;-) I just wanted to get
to the experiment following -- did you notice that it takes the
assignment
name from each "def dispatch ...", but it is actually re-assigning the
returned dispatch
*dict* as the value, not a modified function?


Yes, I noticed that your second version of dispvia, which I snipped,
returned dispatch instead of the nested function named _. But I did not
quite think thru the import of so doing.

I think one or more of these recipies might at least be worthy of the
cookbook site so they can be easily referenced in response to future
postings.

Terry J. Reedy

Jul 18 '05 #28
Jason Zheng wrote:
I'm wondering why python still has limited lambda support. What's
stopping the developers of python to support more lisp-like lambda
function?


See boo and its support for closures: http://boo.codehaus.org/
http://boo.codehaus.org/Closures

It works with "def" or "do", or single-line closures use {}.

x = def:
print "hello"

A closure with parameters:

c = def(x1 as int, x2 as string):
print x1, x2

Single line closures use {}

c = {print("hello")}

Single line with parameters

c = {item as string | print(item)}
#Passing closures to a method as a parameter:

def mymethod(c as callable):
c()

x = mymethod( {print("hello")} )

#passing a multi-line closure as a parameter:

x = mymethod() do():
print "hello"

#Adding a closure to an event handler:

button.Click += def ():
print("${button} was clicked!")
Jul 18 '05 #29
On Sat, 18 Dec 2004 14:39:54 -0500, "Terry Reedy" <tj*****@udel.edu> wrote:

"Bengt Richter" <bo**@oz.net> wrote in message
news:41****************@news.oz.net...
On Sat, 18 Dec 2004 03:05:08 -0500, "Terry Reedy" <tj*****@udel.edu>
wrote:
To avoid the redundancy of 'a' and '_a', etc, how about (untested):

def dispvia(f):
dispatch[f.__name__.split('_')[1]] = f
return f
That should work. Didn't want to retype ;-) I just wanted to get
to the experiment following -- did you notice that it takes the
assignment
name from each "def dispatch ...", but it is actually re-assigning the
returned dispatch
*dict* as the value, not a modified function?


Yes, I noticed that your second version of dispvia, which I snipped,
returned dispatch instead of the nested function named _. But I did not

That's actually not the right "instead" ;-) I.e., the function _ returns
dispatch instead of the function passed to _it_ for deco-modification.
quite think thru the import of so doing.

I think one or more of these recipies might at least be worthy of the
cookbook site so they can be easily referenced in response to future
postings.

It is a little sneaky though, so it might not be prudent to promote
without a little more experimentation? I just like to explore ;-)

Regards,
Bengt Richter
Jul 18 '05 #30
Bengt Richter wrote:
It is a little sneaky though, so it might not be prudent to promote
without a little more experimentation? I just like to explore ;-)


I don't think even the py-dev discussions of this settled on whether such tricks
were "very cool" or "downright evil".

They're probably less evil than sys._getframe hacks, though :)

Cheers,
Nick.

--
Nick Coghlan | nc******@email.com | Brisbane, Australia
---------------------------------------------------------------
http://boredomandlaziness.skystorm.net
Jul 18 '05 #31
Op 2004-12-17, Terry Reedy schreef <tj*****@udel.edu>:

"Jason Zheng" <jz****@jpl.nasa.gov> wrote in message
news:cp**********@nntp1.jpl.nasa.gov...
Steven Bethard wrote:
Jason Zheng wrote:

I'm wondering why python still has limited lambda support. What's
stopping the developers of python to support more lisp-like lambda
function?
They already have: given the fundamental syntax difference between all
expressions and expressions within statements, def statements are at least
the equivalent of lisp lambdas + name binding. When you get an exception
traceback, a unique name is more helpful than the pseudoname <lambda>.
Isolating the definition of a function in a separate statement also makes
it possible to unittest the function.
This comes up every few weeks on the list. If you haven't already,
check the archives in Google for 'anonymous def' or 'anonymous
function'. The usual response to this question is something along the
lines of "if it's good enough to create a function for, it's good enough
to name".


What puzzles me is 1) why some people apparently think anonymity is good --
is it really that hard to name non-trivial functions?


Do you name every object, number, string ... before you use it.
If not it seems you don't object to anonymity.

And yes it sometimes is hard. Of course you can just name it f1, f2 etc,
but that is no improvement over anonymity and sometimes the best you
can do is describe what the function does, but the code does that
better.

--
Antoon Pardon
Jul 18 '05 #32

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

Similar topics

220
18803
by: Brandon J. Van Every | last post by:
What's better about Ruby than Python? I'm sure there's something. What is it? This is not a troll. I'm language shopping and I want people's answers. I don't know beans about Ruby or have...
4
1700
by: Michael Foord | last post by:
I'm starting to read through the developer works article on Functional Programming - http://www-106.ibm.com/developerworks/library/l-prog.html It starts by giving some basic examples using...
181
8600
by: Tom Anderson | last post by:
Comrades, During our current discussion of the fate of functional constructs in python, someone brought up Guido's bull on the matter: http://www.artima.com/weblogs/viewpost.jsp?thread=98196 ...
267
10507
by: Xah Lee | last post by:
Python, Lambda, and Guido van Rossum Xah Lee, 2006-05-05 In this post, i'd like to deconstruct one of Guido's recent blog about lambda in Python. In Guido's blog written in 2006-02-10 at...
5
2141
by: Octal | last post by:
How does the lambda library actually works. How does it know how to evaluate _1, how does it recognize _1 as a placeholder, how does it then calculate _1+_2, or _1+2 etc. The source files seem a...
26
2684
by: brenocon | last post by:
Hi all -- Compared to the Python I know and love, Ruby isn't quite the same. However, it has at least one terrific feature: "blocks". Whereas in Python a "block" is just several lines of...
4
3138
by: Jerzie.Klenchier | last post by:
Hi all, I'm having some difficulty in getting the following piece of code to compile: #include <iostream> #include <deque> #include <algorithm> #include <boost/tuple/tuple.hpp> #include...
0
7223
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
1
7031
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
7485
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
5623
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
1
5042
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
4702
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
3191
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
3179
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
760
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.