Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > Securing a future for anonymous functions in Python

Reply
Thread Tools

Securing a future for anonymous functions in Python

 
 
Nick Coghlan
Guest
Posts: n/a
 
      12-30-2004
GvR has commented that he want to get rid of the lambda keyword for Python 3.0.
Getting rid of lambda seems like a worthy goal, but I'd prefer to see it dropped
in favour of a different syntax, rather than completely losing the ability to
have anonymous functions.

Anyway, I'm looking for feedback on a def-based syntax that came up in a recent
c.l.p discussion:
http://boredomandlaziness.skystorm.n...in-python.html

Cheers,
Nick.

--
Nick Coghlan | http://www.velocityreviews.com/forums/(E-Mail Removed) | Brisbane, Australia
---------------------------------------------------------------
http://boredomandlaziness.skystorm.net
 
Reply With Quote
 
 
 
 
Paul Rubin
Guest
Posts: n/a
 
      12-30-2004
Nick Coghlan <(E-Mail Removed)> writes:
> Anyway, I'm looking for feedback on a def-based syntax that came up in
> a recent c.l.p discussion:


Looks like just an even more contorted version of lambda. It doesn't
fix lambda's main deficiency which is inability to have several
statements in the anonymous function.
 
Reply With Quote
 
 
 
 
Nick Coghlan
Guest
Posts: n/a
 
      12-30-2004
Paul Rubin wrote:
> Nick Coghlan <(E-Mail Removed)> writes:
>
>>Anyway, I'm looking for feedback on a def-based syntax that came up in
>>a recent c.l.p discussion:

>
>
> Looks like just an even more contorted version of lambda. It doesn't
> fix lambda's main deficiency which is inability to have several
> statements in the anonymous function.


Do you consider generator expressions or list comprehensions deficient because
they don't allow several statements in the body of the for loop?

Cheers,
Nick.

--
Nick Coghlan | (E-Mail Removed) | Brisbane, Australia
---------------------------------------------------------------
http://boredomandlaziness.skystorm.net
 
Reply With Quote
 
John Roth
Guest
Posts: n/a
 
      12-30-2004

"Nick Coghlan" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> GvR has commented that he want to get rid of the lambda keyword for Python
> 3.0. Getting rid of lambda seems like a worthy goal, but I'd prefer to see
> it dropped in favour of a different syntax, rather than completely losing
> the ability to have anonymous functions.
>
> Anyway, I'm looking for feedback on a def-based syntax that came up in a
> recent c.l.p discussion:
> http://boredomandlaziness.skystorm.n...in-python.html
>
> Cheers,
> Nick.


I think it's rather baroque, and I agree with Paul Ruben
that it needs multiple statement capability.

The syntax I prefer (and I don't know if it's actually been
suggested before) is to use braces, that is { and }.

In other words, an anonymous function looks like:
{p1, p2, p3 |
stmt1
stmt2
}

There are two reasons for using braces. One is
that it's the common syntax for blocks in a large number
of languages. The other is that it should be relatively
easy to disambiguate from dictionary literals, which are
the only other current use of braces.

The parameter list is optional, as is the bar ending
the list. The reason for the bar instead of a colon
is to help the parser in the case of a single parameter,
which would look like the beginning of a dictionary
literal. If the parser doesn't need the help, then a colon
would be more consistent, hence better.

A second issue is indentation. I'd set the indentation
boundary wherever the _second_ line of the construct
starts, as long as it's to the right of the prior
indentation boundary. The unfortunate part of this, and one of the
major stumbling blocks, is that it might take some
significant reconceptualizing of the lexer and parser,
which currently isn't set up to shift from expression
back to statement mode and then return to expression
mode.

John Roth

> --
> Nick Coghlan | (E-Mail Removed) | Brisbane, Australia
> ---------------------------------------------------------------
> http://boredomandlaziness.skystorm.net


 
Reply With Quote
 
Ian Bicking
Guest
Posts: n/a
 
      12-30-2004
John Roth wrote:
> The syntax I prefer (and I don't know if it's actually been
> suggested before) is to use braces, that is { and }.
>
> In other words, an anonymous function looks like:
> {p1, p2, p3 |
> stmt1
> stmt2
> }


What's the advantage of something like that over the non-anonymous
equivalent:

def some_func(p1, p2, p3):
stmt1
stmt2

I appreciate some of the motivation, but merely avoiding giving
something a name doesn't seem like a laudible goal.

The one motivation I can see for function expressions is
callback-oriented programming, like:

get_web_page(url,
when_retrieved={page |
give_page_to_other_object(munge_page(page))})

The problem with the normal function in this case is the order of
statements is reversed:

def when_retrieved_callback(page):
give_page_to_other_object(munge_page(page))
get_web_page(url, when_retrieved=when_retrieved_callback)

Oh, and you have to type the name twice, which is annoying. For most
other functional programming constructs, list (and not generator)
comprehensions work well enough, and the overhead of naming functions
just isn't that big a deal.

I think this specific use case -- defining callbacks -- should be
addressed, rather than proposing a solution to something that isn't
necessary. Which is to say, no one *needs* anonymous functions; people
may need things which anonymous functions provide, but maybe there's
other ways to provide the same thing. Decorator abuse, for instance

def get_web_page_decorator(url):
def decorator(func):
return get_web_page(url, when_retrieved=func)
return decorator

@get_web_page_decorator(url)
def when_retrieved(page):
give_page_to_other_object(munge_page(page))

Or even (given a partial function as defined in some PEP, the number of
which I don't remember):

@partial(get_web_page, url)
def when_retrieved(page):
give_page_to_other_object(munge_page(page))

It's okay not to like this proposal, I don't think I'm really serious.
But I do think there's other ways to approach this. Function
expressions could get really out of hand, IMHO, and could easily lead to
twenty-line "expressions". That's aesthetically incompatible with
Python source, IMHO.

--
Ian Bicking / (E-Mail Removed) / http://blog.ianbicking.org
 
Reply With Quote
 
Roy Smith
Guest
Posts: n/a
 
      12-30-2004
Ian Bicking <(E-Mail Removed)> wrote:
> I think this specific use case -- defining callbacks -- should be
> addressed, rather than proposing a solution to something that isn't
> necessary. Which is to say, no one *needs* anonymous functions; people
> may need things which anonymous functions provide, but maybe there's
> other ways to provide the same thing. Decorator abuse, for instance


I'm not a big functional programming fan, so it should not come as a
surprise that I don't often use lambda. The one place I do use it is in
unit tests, where assertRaises() requires a callable. If what you're
testing is an expression, you need to wrap it in a lambda.

I suppose you could call this a special case of a callback.
 
Reply With Quote
 
Skip Montanaro
Guest
Posts: n/a
 
      12-30-2004

John> In other words, an anonymous function looks like:
John> {p1, p2, p3 |
John> stmt1
John> stmt2
John> }

John> There are two reasons for using braces. One is that it's the
John> common syntax for blocks in a large number of languages.

Yeah, but it's not how blocks are spelled in Python. As Nick pointed out on
his blog, allowing statements within expressions risks making code more
difficult to read and understand.

People keep trying to make Python something it is not. It is not
fundamentally an expression-only language like Lisp, nor is it an
expression-equals-statement language like C. There are good reasons why
Guido chose the relationship between simple statements, compound statements
and expressions that he did, readability and error avoidance being key.

Skip
 
Reply With Quote
 
Carl Banks
Guest
Posts: n/a
 
      12-30-2004
Nick Coghlan wrote:
> GvR has commented that he want to get rid of the lambda keyword for

Python 3.0.
> Getting rid of lambda seems like a worthy goal, but I'd prefer to see

it dropped
> in favour of a different syntax, rather than completely losing the

ability to
> have anonymous functions.


I shall either coin or reuse a new term here: "premature optimization
of the Python language."

(Please note that the word premature is not intended to be an accurate
description, but irony by analogy, so spare me any semantic
nitpicking.)

In much the same way that programmers often spend a lot of time
optimizing parts of their program that will yield very minor dividends,
while they could have spent that time working on other things that will
pay off a lot, many of the wannabe language designers here are spending
a lot of time on aspects of the language for which any improvement
would only pay small dividends.

I think the worry about anonymous functions is one of the most
widespread cases of "premature optimization of the Python Language."
One could argue about the various benefits of particular choices, maybe
even make a convincing case that one is best in accord with the design
goals of Python; but in the end, the divends are small compared to
improving other aspects of the language.


--
CARL BANKS

 
Reply With Quote
 
David Bolen
Guest
Posts: n/a
 
      12-30-2004
Ian Bicking <(E-Mail Removed)> writes:

> The one motivation I can see for function expressions is
> callback-oriented programming, like:
>
> get_web_page(url,
> when_retrieved={page |
> give_page_to_other_object(munge_page(page))})


This is my primary use case for lambda's nowadays as well - typically
just to provide a way to convert the input to a callback into a call
to some other routine. I do a lot of Twisted stuff, whose deferred
objects make heavy use of single parameter callbacks, and often you
just want to call the next method in sequence, with some minor change
(or to ignore) the last result.

So for example, an asynchronous sequence of operations might be like:

d = some_deferred_function()
d.addCallback(lambda x: next_function())
d.addCallback(lambda blah: third_function(otherargs, blah))
d.addCallback(lambda x: last_function())

which to me is more readable (in terms of seeing the sequence of
operations being performed in their proper order), then something like:

def cb_next(x):
return next_function()
def cb_third(blah, otherargs):
return third_function(otherargs, blah)
def cb_last(x):
return last_function()

d = some_deferred_function()
d.addCallback(cb_next)
d.addCallback(cb_third, otherargs)
d.addCallback(cb_next)

which has an extra layer of naming (the callback functions), and
requires more effort to follow the flow of what is really just a simple
sequence of three functions being called.

> I think this specific use case -- defining callbacks -- should be
> addressed, rather than proposing a solution to something that isn't
> necessary. (...)


I'd be interested in this approach too, especially if it made it simpler
to handle simple manipulation of callback arguments (e.g., since I often
ignore a successful prior result in a callback in order to just move on
to the next function in sequence).

-- David
 
Reply With Quote
 
Bengt Richter
Guest
Posts: n/a
 
      12-30-2004
On Thu, 30 Dec 2004 23:28:46 +1000, Nick Coghlan <(E-Mail Removed)> wrote:

>GvR has commented that he want to get rid of the lambda keyword for Python 3.0.
>Getting rid of lambda seems like a worthy goal, but I'd prefer to see it dropped
>in favour of a different syntax, rather than completely losing the ability to
>have anonymous functions.
>
>Anyway, I'm looking for feedback on a def-based syntax that came up in a recent
>c.l.p discussion:
>http://boredomandlaziness.skystorm.n...in-python.html
>

Nit: You didn't try the code you posted

>>> funcs = [(lambda x: x + i) for i in range(10)]
>>>
>>> def incrementors():

... for i in range(10):
... def incrementor(x):
... return x + i
... yield incrementor
...
>>> #funcs = list(incrementors)

... funcs2 = list(incrementors())
>>>
>>> for f in funcs: print f(0),

...
9 9 9 9 9 9 9 9 9 9
>>> for f in funcs2: print f(0),

...
9 9 9 9 9 9 9 9 9 9

This is an easy trap to fall into, so if the new lambda-substitute could
provide a prettier current-closure-variable-value capture than passing a dummy default
value or nesting another def and passing the value in, to provide a private closure for each,
that might be something to think about.

IMO an anonymous def that exactly duplicates ordinary def except for leaving out
the function name and having a local indentation context would maximize flexibility
and also re-use of compiler code. People could abuse it, but that's already true
of many Python features.

From your web page:
----
def either(condition, true_case, false_case):
if condition:
return true_case()
else:
return false_case()

print either(A == B, (def "A equals B"), (def "A does not equal B"))
either(thefile, (def thefile.close()), (def 0))
----

I'd rather see (:something) than (def something) for this special case,
but the full-fledged anonymous def would spell it thus:

print either(A == B, (def():return "A equals B"), (def(): return "A does not equal B"))
either(thefile, (def(): return thefile.close()), (def(): return 0))

BTW,

funcs = [(lambda x: x + i) for i in range(10)]

might be spelled

funcs = [(def(x, i=i): return x + i) for i in range(10)]

or optionally

funcs = [(
def(x, i=i):
return x + i
) for i in range(10)]

or

funcs = [(def(x, i=i):
return x + i) for i in range(10)]
or
funcs = [(def(x, i=i):
return x + i)
for i in range(10)]
or
funcs = [def(x, i=i):
return x + i
for i in range(10)]
or
funcs = [
def(x, i=i):
return x + i
for i in range(10)]

and so on. (the def defines the indentation base if the suite is indented, and the closing ')'
terminates the anonymous def explicitly, or a dedent to the level of the def or less can do it,
as in the last two examples).

This one

(def f(a) + g(b) - h(c) from (a, b, c))

would be spelled (if I undestand your example)

(def(a, b, c): return f(a)+g(b)+h(c))

which seems to me familiar and easy to understand.

BTW, there are old threads where this and other formats were discussed. I am still
partial to the full anonymous def with nesting indentation rules. Syntactic sugar
could be provided for useful abbreviations (that could possibly be expanded by the
tokenizer -- re which possibilities I haven't seen any discussion than my own
recent post, BTW), but I'd like the full capability.

Regards,
Bengt Richter
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Would Anonymous Functions Help in Learning Programming/Python? Cristian Python 66 09-24-2007 03:26 PM
Is this a local anonymous class or a member anonymous class Reporter Java 3 05-12-2007 05:23 AM
help with an anonymous array of anonymous hashes noeldamonmiller@gmail.com Perl Misc 1 02-10-2005 01:08 AM
Re: Securing a future for anonymous functions in Python Jp Calderone Python 8 01-01-2005 12:00 AM
please help me in distinguish redefining functions, overloading functions and overriding functions. Xiangliang Meng C++ 1 06-21-2004 03:11 AM



Advertisments