Securing a future for anonymous functions in Python

S

Steven Bethard

Alan said:
That's a fair point I suppose but I still don't see much point in
introducing new names and syntaxes when the existing name is a
sensible one, even if unfamiliar to many. After all it works in
Lisp and Haskell - Haskell even uses Lambda as its emblem...

Yeah, I personally expect that if GvR doesn't like lambda now, he won't
like any of the new syntaxes either. But I'm in the camp that won't
miss lambda if it's gone, so I'm not too worried. ;)

Steve
 
J

James Stroud

Richard Feynman told a story about being on a review committee for
some grade-school science textbooks. One of these book said something
about "counting numbers" and it took him a while to figure out that
this was a new term for what he'd been used to calling "integers".


I think we should not try too hard to make everything "English" like. Its a
crappy language anyway (though its the only one I speak good). Matt Neuberg,
in _AppleScript: The Definitive Guide_, refers to "the English-likeness
monster". His example is that instead of

x = 4

you have to say

copy 4 to x

I think every reader of this list would prefer to look at the former.

The point is that once we learn new symbolics of expression, they are as
simple to decipher as plain old English if we format properly and
gIvEnThAtwEiNcLuDEsOmEhElPfUlfORmaTtInGInOuRcOdEFroMtImEtOtiME.

So I think that being fearful of new additions to the language (read "more
ability for expression") is mainly fear of abuse by poor programmers--and
that is akin to being afraid of the dark.

James



--
James Stroud, Ph.D.
UCLA-DOE Institute for Genomics and Proteomics
611 Charles E. Young Dr. S.
MBI 205, UCLA 951570
Los Angeles CA 90095-1570
http://www.jamesstroud.com/
 
R

Roy Smith

James Stroud said:
I think we should not try too hard to make everything "English" like. Its a
crappy language anyway (though its the only one I speak good). Matt Neuberg,
in _AppleScript: The Definitive Guide_, refers to "the English-likeness
monster". His example is that instead of

x = 4

you have to say

copy 4 to x

The syntax was taken directly from HyperCard.
 
A

Anna

Jacek said:
Anna said:
Having taken some calculus (derivatives, limits, some integrals) but
never even heard of lambda calculus, to me, lambda means absolutely
NOTHING. Less than nothing.

And before you took calculus, the chances are that derivatives, limits
and integrals meant less than nothing to you.

But now, I am quite sure, you know that in Python lambda is a keyword
which creates anonymous functions. Now that you know what lambda does,
what's the problem with it? (It certainly doesn't mean "Less than
nothing" to you now.)
So, I guess I don't like the word itself

Fair enough. I guess there are people out there who might have a
distaste for the word "class" or "def" or any of the other words which
are keywords in Python.
Every other word in Python has an obvious meaning. lambda doesn't.

Obvious to whom?

The meaning of every word is obvious, once you have been taught it;
and a complete mystery if you have not.

What do you make of "seq[2:-2]"? It means "less than nothing" to the
uninitiated. Just like lambda.

Actually - whether or not I understood the [2:-2] notation, knowing
nothing else, the "seq" would clue me in that we're probably doing
something with sequences...

Personally, I like lambdas less than regular expressions (of which I'm
particularly UNfond but understand their usefulness at times). At least
with regular expressions - I know that the gibberish I need to decipher
(probably) has to do with text parsing... With class and def, I at
least have a *name* to start with - class Square pretty obviously is
going to have something to do with geometric shapes, I would hope (or
maybe with boring people...). def getfoo() tells me I'm the function is
likely to go elsewhere and get something. It's a *start*, a handle, to
deciphering whatever the following statements are doing. (Yes, I
realize that often class and function names suck - but more often than
not, they give *some* clue).

Whereas, with lambda - I have *nothing* to go on. With lambdas, all I
know is that the programmer wanted to hide whatever it is the program
is doing behind the curtain... (at least that's the way it comes
across). So, not only is the word itself not descriptive of anything to
me - even knowing that it means "anonymous function" - the use of it
precludes descriptiveness, as compared to defining a function. IMHO,
YMMV, etc etc

Anna
 
J

Jacek Generowicz

Anna said:
With class and def, I at least have a *name* to start with - class
Square pretty obviously is going to have something to do with
geometric shapes, I would hope (or maybe with boring people...).

Or maybe with multiplying something by itself. Or maybe the author
made some changes in his program, and forgot to rename the class
sensibly, and the class' functionality has nothing to do with squares
of any sort any more. Or maybe he felt the name "Square" was very
appropriate for something else in his program and inadvertently gave
the same name to two different entities thereby clobbering the one
whose use was intended at this point.
def getfoo() tells me I'm the function is likely to go elsewhere and
get something. It's a *start*,

All too often a start in the wrong direction.
a handle, to deciphering whatever the following statements are
doing. (Yes, I realize that often class and function names suck

Yup. I waste quite some time because of crappily chosen names.
- but more often than not, they give *some* clue).

Whereas, with lambda - I have *nothing* to go on.

Aaah. OK, you object to lambda because it gives you no clue as to what
the function does, rather than with the word "lambda" itself? Is that
it?

So, IIUC, you consider

def add_one(x):
return x+1

map(add_one, seq)

to be clearer than

map(lambda x:x+1, seq)

?
With lambdas, all I know is that the programmer wanted to hide
whatever it is the program is doing behind the curtain...

I find this a strange way of looking at it, given that, with lambda,
what the program is doing is right there in front of your very eyes at
the very point at which it is doing it. Were there a name, _then_ you
could argue that the functionality is hidden ... and you would have to
look the name up, to make sure that it really represents what you
inferred it meant (and, to be absolutely sure, you'd have to double
check that it hasn't been rebound by some other part of the program in
some nasty way). None of these problems arise with lambda.
IMHO, YMMV, etc etc

Of course. Same here.
Personally, I like lambdas less than regular expressions (of which
I'm particularly UNfond but understand their usefulness at
times). At least with regular expressions - I know that the
gibberish I need to decipher (probably) has to do with text
parsing...

Hmm, that tells you about as much as lambda does. With lambda you know
that the gibberish you need to decipher has to do with functions :)
 
J

Jacek Generowicz

Nick Coghlan said:
The ability to pass around functions at run-time was probably the
hardest thing to get my head around when I started with Python,

And I suspect that this particular case is further complicated by the
fact that int is not a function ... it's a type!

I can imagine it might make a newbie's brain melt. Still, most of them
survive and thoroughly enjoy the course :)
 
A

Anna

Jacek said:
Or maybe with multiplying something by itself. Or maybe the author
made some changes in his program, and forgot to rename the class
sensibly, and the class' functionality has nothing to do with squares
of any sort any more. Or maybe he felt the name "Square" was very
appropriate for something else in his program and inadvertently gave
the same name to two different entities thereby clobbering the one
whose use was intended at this point.

Idjits abound. ;-)

Can't make anything foolproof because fools are so ingenious.
Aaah. OK, you object to lambda because it gives you no clue as to what
the function does, rather than with the word "lambda" itself? Is that
it?

So, IIUC, you consider

def add_one(x):
return x+1

map(add_one, seq)

to be clearer than

map(lambda x:x+1, seq)

Completely, totally, and unambiguously: the version with the defined
function is immediately clear to me; the version with the lambda is
decipherable, but requires deciphering (even at 2nd and 3rd glance).
But first, wouldn't something like:

[x+1 for x in seq]

be even clearer?

Given an example more complex (which you must admit, lambdas usually
are) - the name of the function is something my brain can hold on to to
represent the group of operations; where with the lambda, I need to
mentally go through each operation each time I try to read it. And the
more complex f is, the harder time I have holding it all in my head
while I figure out how to get from the beginning value x to the ending
value f(x). lambda is an O(N*N) problem for my brain.

I could see someone more mathematically-minded being happier with
lambda. It's not, after all, the word "lambda" itself; I would still
have some issues with using, say "function", instead of "lambda", but
at least then I would immediately know what I was looking at...

Anna
 
V

Ville Vainio

James> I think we should not try too hard to make everything
James> "English" like. Its a crappy language anyway (though its
James> the only one I speak good). Matt Neuberg,

QOTW material, unless you stole this from someone else :).
 
J

Jacek Generowicz

Anna said:
Idjits abound. ;-)

Yup ... which is one reason why lambda is so useful. Everything there
is to know about it is right in front of your eyes. There is no chance
that some idjit changed the meaning of lambda, or the code which
appears within it (unless that refers to some external names, of
course).
Completely, totally, and unambiguously:

Curious. It's very much the other way around for me.
the version with the defined function is immediately clear to me;
the version with the lambda is decipherable, but requires
deciphering (even at 2nd and 3rd glance). But first, wouldn't
something like:

[x+1 for x in seq]

be even clearer?

I'm glad you mentioned that. My next question was going to be
something along the lines of what you think of the equivalent list
comprehension, which is spectacularly devoid of any names to give you
any hints whatsoever.

As to whether it is clearer. That depends. I would venture to suggest
that, given a pool of laboratory rats with no previous exposure to
Python, more of them would understand the map-lambda than the list
comprehension.

There are no words in the list comprehension at all (besides the
common "seq"): it's all syntax. Even if "map" and "lambda" ring no
bells by association with anything you might have learned outside of
Python, they sure are a lot easier to look up in the documentation.
Given an example more complex (which you must admit, lambdas usually
are)

Well, they can't be _that_ much more complex in Python :) But I'll
grant you, they are often more complex that the one above.
- the name of the function is something my brain can hold on to to
represent the group of operations; where with the lambda, I need to
mentally go through each operation each time I try to read it. And the
more complex f is, the harder time I have holding it all in my head
while I figure out how to get from the beginning value x to the ending
value f(x). lambda is an O(N*N) problem for my brain.

Fair enough. If I understand the code just by looking at it, then I
prefer to see it inline. If its meaning isn't obvious immediately,
then I'd go for the named function too. But I still value the ability
to inline-define the function while developing ... even if the inline
function will be outlined in the final product.

But, how do you feel about the individual lines of code in the body of
a multi-line function? They don't have individual names.
I could see someone more mathematically-minded being happier with
lambda. It's not, after all, the word "lambda" itself;

Aaah ... you did suggest (upthread) that it was the word itself which
gave you problems ... which is what piqued my interest.
 
J

Jeff Shannon

Jacek said:
Anna said:
But first, wouldn't something like:

[x+1 for x in seq]

be even clearer?

I'm glad you mentioned that. [...]

As to whether it is clearer. That depends. I would venture to suggest
that, given a pool of laboratory rats with no previous exposure to
Python, more of them would understand the map-lambda than the list
comprehension.

I would venture to suggest the exact opposite, that the syntax of a
list comprehension is in itself suggestive of its meaning, while 'map'
and 'lambda' are opaque until you've researched them. The verb 'to
map', in this mathematical sense, is not part of standard usage among
anyone that *I* know. Instead, they'd speak of doing something for
(or to) each item in a group -- exactly what list comps express.

Speaking for *this* laboratory rat, at least, map/lambda was always a
nasty puzzle for me and difficult to sort out. But when list comps
were introduced, after reading just a sentence or two on how they
worked, they were completely clear and understandable -- much more so
than map/lambda after many months of exposure.

Jeff Shannon
Technician/Programmer
Credit International
 
A

Anna

You cut something from that...

"""It's not, after all, the word "lambda" itself; I would still
have some issues with using, say "function", instead of "lambda", but
at least then I would immediately know what I was looking at..."""

I would have fewer ambiguities about using, say "func" rather than
lambda. Lambda always makes me feel like I'm switching to some *other*
language (specifically, Greek - I took a couple of semesters of Attic
Greek in college and quite enjoyed it.) But, the fact that lambda
doesn't MEAN anything (and has come - I mean - DELTA at least has a
fairly commonly understood meaning, even at high-school level math.
But, lambda? If it was "func" or "function" or even "def", I would be
happier. At least that way I'd have some idea what it was supposed to
be...

BTW - I am *quite* happy with the proposal for "where:" syntax - I
think it handles the problems I have with lambda quite handily.

Anna
 
S

Steve Holden

Anna said:
You cut something from that...

"""It's not, after all, the word "lambda" itself; I would still
have some issues with using, say "function", instead of "lambda", but
at least then I would immediately know what I was looking at..."""

I would have fewer ambiguities about using, say "func" rather than
lambda. Lambda always makes me feel like I'm switching to some *other*
language (specifically, Greek - I took a couple of semesters of Attic
Greek in college and quite enjoyed it.) But, the fact that lambda

Good God, you mean there's a language just for the attic? Those Greeks
certainly believed in linguistic specialization, didn't they?
doesn't MEAN anything (and has come - I mean - DELTA at least has a
fairly commonly understood meaning, even at high-school level math.
But, lambda? If it was "func" or "function" or even "def", I would be
happier. At least that way I'd have some idea what it was supposed to
be...
Well, I suspect that Church originally chose lambda precisely because of
its meaninglessness, and I'm always amused when mathematical types try
to attribute an intuitive meaning to the word. It's purely a learned
association, which some arrogantly assume simply *everyone* knows or
should know.

Not that I'm trying to write off lambda supporters as arrogant (though I
*do* have a suspicion that many of them break the wrong end of their
boiled eggs).
BTW - I am *quite* happy with the proposal for "where:" syntax - I
think it handles the problems I have with lambda quite handily.
Whereas I find it to be an excrescence, proving (I suppose) that one
man's meat is another person's poison, or something.

regards
Steve

[who only speaks Ground Floor English]
 
T

Tim Peters

....

[Anna]
[Steve Holden]
Whereas I find it to be an excrescence, proving (I suppose) that one
man's meat is another person's poison, or something.

I've been waiting for someone to mention this, but looks like nobody
will, so I'm elected. Modern functional languages generally have two
forms of local-name definition, following common mathematical
conventions. "where" was discussed here. The other is "let/in", and
seems a more natural fit to Python's spelling of block structure:

let:
suite
in:
suite

There's no restriction to expressions here. I suppose that, like the
body of a class, the `let` suite is executed starting with a
conceptually empty local namespace, and whatever the suite binds to a
local name becomes a temporary binding in the `in` suite (like
whatever a class body binds to local names becomes the initial value
of the class __dict__). So, e.g.,

i = i1 = 3
let:
i1 = i+1
from math import sqrt
in:
print i1, sqrt(i1)
print i1,
print sqrt(i1)

would print

4 2
3

and then blow up with a NameError.

LIke it or not, it doesn't seem as strained as trying to pile more
gimmicks on Python expressions.
 
J

Jacek Generowicz

Steve Holden said:
Well, I suspect that Church originally chose lambda precisely because
of its meaninglessness,

IAANM, Church didn't choose lambda at all. He chose to put a "hat"
(like a circumflex accent) above the bound name. Then, because of some
typesetting difficulties, this was transformed into the nearest thing
that looked like it: a capital lambda in front of the name ... and
later the capital lambda turned into a lowercase one.
 
J

Jacek Generowicz

Jeff Shannon said:
Jacek said:
Anna said:
But first, wouldn't something like:

[x+1 for x in seq]

be even clearer?
I'm glad you mentioned that. [...]
As to whether it is clearer. That depends. I would venture to suggest
that, given a pool of laboratory rats with no previous exposure to
Python, more of them would understand the map-lambda than the list
comprehension.


I would venture to suggest the exact opposite, that the syntax of a
list comprehension is in itself suggestive of its meaning, while 'map'
and 'lambda' are opaque until you've researched them.

In the population of all laboratory rats, I think that the proportion
that would understand either form, would be as good as zero.

Given a population with previous exposure to computer programming, my
money is on the map-lambda version. But this last point is mostly
irrelevant. The fact is that you cannot program computers without
doing a bit of learning ... and the lambda, map and friends really do
not take any significant learning.
Speaking for *this* laboratory rat, at least, map/lambda was always a
nasty puzzle for me and difficult to sort out. But when list comps
were introduced, after reading just a sentence or two on how they
worked, they were completely clear and understandable -- much more so
than map/lambda after many months of exposure.

Forgetting about lambda, map, filter and reduce, do you find that you
pass callables around in your Python programs, or is this not
typically done in your programs?
 
M

michele.simionato

Jacek:
Given a population with previous exposure to computer programming, my
money is on the map-lambda version. But this last point is mostly
irrelevant. The fact is that you cannot program computers without
doing a bit of learning ... and the lambda, map and friends really do
not take any significant learning.

This kind of "sociological" study would be pretty interesting to me ;-)

Personally, I find out that my mind manage pretty well one-level of
indirection
at time, not two. Consider for instance

def add1(x): return x+1
map(add1, mylist)

Here there are *two* levels of indirection:

first, I need to define add1;
second I need to translate mentally map to a loop.

Using lambda does not help:

map(lambda x: x+1, mylist)

still would require two levels for me, one to recognize the lambda
and one to convert map to a loop.

This is too much for me, so I just write

[x+1 for x in mylist]

where everything is explicit (or if you wish, I have just to recognize
that there
is a loop going on, pretty easy).

However, if I can skip a level of indirection (i.e. I do not need to
define
a function) I just prefer map:

map(int, mylist)

is simpler for me than

[int(x) for x in mylist]

since the latter introduces an useless x (which is also polluting my
namespace,
but this not my point, I could use a generator-expression instead).

So, in practice, I only use map with built-in or with predefined
functions, i.e. functions
which are already there for some other purpose; I do not like to be
forced to write a
function (or a lambda) for the only purpose of using map (at least in
Python).

Incidentally, I am not fond of the name "lambda" too. "fn", as Paul
Graham says,
looks much better.

What I would like, in Python, is some facility to manage callbacks in
the standard
library, then I would live pretty well without lambdas.
Just IMHO, YMMV, etc.

Michele Simionato
 
B

Bengt Richter

...

[Anna]
[Steve Holden]
Whereas I find it to be an excrescence, proving (I suppose) that one
man's meat is another person's poison, or something.

I've been waiting for someone to mention this, but looks like nobody
will, so I'm elected. Modern functional languages generally have two
forms of local-name definition, following common mathematical
conventions. "where" was discussed here. The other is "let/in", and
Well, I did say it reminded me of some kind of weird let ;-)
http://groups-beta.google.com/groups?q= Reminds me of some kind of weird let&hl=en&lr=&sa=N&tab=wg
seems a more natural fit to Python's spelling of block structure:

let:
suite
in:
suite

There's no restriction to expressions here. I suppose that, like the
body of a class, the `let` suite is executed starting with a
conceptually empty local namespace, and whatever the suite binds to a
local name becomes a temporary binding in the `in` suite (like
whatever a class body binds to local names becomes the initial value
of the class __dict__). So, e.g.,

i = i1 = 3
let:
i1 = i+1
from math import sqrt
in:
print i1, sqrt(i1)
print i1,
print sqrt(i1)

would print

4 2
3

and then blow up with a NameError.

LIke it or not, it doesn't seem as strained as trying to pile more
gimmicks on Python expressions.
I could get to like it ;-)

Hm, a little extension to this could provide a new way to populate closure variables,
and also (never mind, one thing at a time ;-)

#1: If you gave your 'let' above a list of 'externs' that can be rebound from within the let.
E.g.,

let(sqrt):

the effect in your example would be to eliminate the NameError you mention.
The compiler would make an entry for sqrt in the enclosing namespace, and generate
code to bind/rebind if assigned from within the let.

This would be an interesting way to create closure bindings:

let(foo):
preset = 'another way to make closure vairables'
in:
def foo(): return preset
...
print foo()

#2: Making the in: suite callable as a light weight function with no arguments. An optional
binding name after in would bind like def and create a persistent named callable instead of just an
implicitly called anonymous suite.

Then you could define the same effective foo by

let:
preset = 'another way to make closure vairables'
in foo:
return preset # return now legal
...
print foo()

The combination would work like:

let(rebindable):
factor = 10
in bar:
rebindable *= factor

rebindable = 2
bar()
print rebindable # => 20
rebindable += 5
bar()
print rebindable # => 250

You can see this could be used nicely in case functionality, with a dict of named in-functions.

What do you think?

Regards,
Bengt Richter
 
N

Nick Coghlan

Tim said:
LIke it or not, it doesn't seem as strained as trying to pile more
gimmicks on Python expressions.

Some of us are piling gimmicks on statements, not expressions :)

And I'm looking for out-of-order code execution as well as local namespaces, so
the let/in syntax wouldn't help much. (The out-of-order execution is what really
makes the property definition example pretty, IMO)

Cheers,
Nick.
 
C

Carl Banks

Tim said:
...

[Anna]
[Steve Holden]
Whereas I find it to be an excrescence, proving (I suppose) that one
man's meat is another person's poison, or something.

I've been waiting for someone to mention this, but looks like nobody
will, so I'm elected. Modern functional languages generally have two
forms of local-name definition, following common mathematical
conventions. "where" was discussed here. The other is "let/in", and
seems a more natural fit to Python's spelling of block structure:

let:
suite
in:
suite

Ah. During that discussion, I did kind of suggest this (spelling it
where...do) as an alternative to where (thinking I was clever). Only
no one seemed to take notice, probably because I suggested something
more poignant at the same time.

Now I see why I liked the idea so much; it was exactly like let forms.

There's no restriction to expressions here. I suppose that, like the
body of a class, the `let` suite is executed starting with a
conceptually empty local namespace, and whatever the suite binds to a
local name becomes a temporary binding in the `in` suite (like
whatever a class body binds to local names becomes the initial value
of the class __dict__). So, e.g.,

i = i1 = 3
let:
i1 = i+1
from math import sqrt
in:
print i1, sqrt(i1)
print i1,
print sqrt(i1)

would print

4 2
3

and then blow up with a NameError.

LIke it or not, it doesn't seem as strained as trying to pile more
gimmicks on Python expressions.

Indeed.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,013
Latest member
KatriceSwa

Latest Threads

Top