Why functional Python matters

7 views
Skip to first unread message

Dave Benjamin

unread,
Apr 15, 2003, 3:22:47 PM4/15/03
to
It has been my increasing concern that Python is headed in a decidedly
object-oriented direction, ignoring the benefits it currently offers to
functional programmers. Before you respond, "but Python *is*
object-oriented!", please allow me to explain. I don't know how many people
I speak for, but I feel a need to speak up and hopefully influence this
direction.

When I first discovered Python, it was with "mailman", which to this day is
the best mailing list software I have ever used. Before I was even a
competent PHP programmer, I knew of one high-quality web application written
in Python. Thus, in the back of my mind, I was interested in the language
for web-releated work (which is more or less what I do). However, at the
time, nobody I knew was writing web applications in Python. They were using
either Perl, PHP, ASP, or JSP, and being a rebellious GNU/Linux lover
frustrated with my awkwardness with Perl, I naturally chose PHP.

PHP turned out to be a very fine language for the tasks I had assigned it
to. It was fast, database-friendly, and provided massive libraries of
functionality catered toward typical web needs. As I became more advanced
with PHP, I began to uncover the beauty of its array functions. To clarify
some terminology here, an "array" in PHP is like a "dictionary" in Python
except that its keys are ordered, and it is sometimes treated like a "list".
One of the nicest things about built-in data structures like these is that
they can be dumped to the console or browser very easily. The presence of
fast, built-in collection types combined with a set of useful utility
functions and an easy method to observe their state at any point have made
them invaluable to my programming projects so far.

I did not do a lot of object-oriented programming in PHP, mainly because it
didn't buy me much, and techniques that I later discovered to be more
functional in nature were more helpful. For example, I tried looking at EJB
and modeling database records with dynamically-generated classes like Entity
Beans, but once I compared this with what I had been used to using
(typically lists of dictionaries representing tables of rows), I saw few
benefits for this method of modeling data. Representing result sets as lists
of dictionaries allowed me to generalize my algorithms and streamline the
data path from the database to the HTML template. Representing rows as
objects made my code bigger, more awkward, and harder to debug.

I should also mention that PHP's support for objects is not very robust, and
I admit in advance that this undoubtedly has biased me away from their use
in general. However, I will also note that I have a CS degree from a college
that promoted object-oriented programming very heavily, and was in the midst
of settling on Java as a standard. All feelings about Java set aside, I
think I have a fair amount of experience with--and well-rounded
understanding of--the object-oriented methodology.

My interest in functional programming exploded when I discovered the
following library of functional tools for PHP by Ian Kjos:

http://functional-php.sourceforge.net/

You might say that this library is to PHP what the Xoltar toolkit is to
Python, although the Xoltar toolkit is far more advanced. Nonetheless, this
source code and accompanying site opened my eyes to the functional style of
programming, and I saw immediate benefits which I was able to apply to my
everyday work. Learning about the power of higher-order functions and the
elimination of side-effects helped me write more concise, more reliable
software than ever before. This was a huge epiphany for me.

The next thing I read will probably not surprise you if you have ever done a
Google search on functional programming. It was David Mertz's "Charming
Python" series on IBM's DeveloperWorks. His papers were not easy to digest
in one sitting, but I made a great effort to understand them and apply the
techniques he described. At this point, I should mention that I was still
programming only in PHP!

By using Ian's functional.php library, I was satisfied to find that I could
follow many of David's examples, and fill in the gaps as I went along. Those
of you who balk at Python's lambda syntax might be less harsh if you knew
the kind of syntax we have to put up with PHP:

Python: x = lambda y, z: y + z
PHP: $x = lam('$y, $z', '$y + $z');

The more I read of David's series, the less I could effectively translate to
PHP, mostly because it ventures into constructs like list comprehensions and
generators that PHP did not support. Eventually, Python's clean, simple
syntax and straightforward approach won me over, and I began migrating my
knowledge to the mod_python platform where I could free myself from all of
those dollar signs and semicolons and play with some really powerful
functional tools. As long as I'm naming names, let me just say that Gregory
Trubetskoy is my hero for what he did with mod_python and the publisher
module. I am greatly indebted to his work.

Now, I write web applications in PHP, mod_python, Zope, and even Java. Of
all of these platforms, my preference is mod_python because it lets me
program in Python--real Python, with no restrictions, no extension modules,
no Jython-stuck-at-Python-2.1, but Python proper. I absolutely adore Python
as a web language.

In fact, as I was originally learning Python, I began to consider it the
Perfect Language(tm). I know that this is a silly thing to do, but I had
learned over a dozen languages previously, and I honestly couldn't find a
single thing wrong with Python, and instead found myself trying to recreate
Python in every other language I used (often with positive results). Now,
I'd say I'm a lot more experienced with Python, and understand its strengths
and weaknesses better, but I still see Python as approaching perfection for
reasonable values of "perfect". =)

Guido's recent musings in the newsgroups and on his presentation on "Python
Regrets" have made me a bit uneasy. In particular, they brought to light the
fact that he generally prefers the object-oriented style to the functional
style and would like to "deprecate" certain features:

- apply, to be replaced with *-notation
- map and filter, to be replaced with list comprehensions
- lambda

Lambda has had the thorniest history of all of these, I think. Lambda has
its roots in LISP and the Lambda calculus, and can be used to create
"anonymous functions" at runtime that can be passed around as needed. This
is a very powerful and useful feature for functional programming, as well as
for event-driven programming. It baffles me that anyone would want to remove
it.

The first problem the "lambda" keyword had was that it couldn't be nested
easily or bound to a particular local variable namespace. This resulted in a
(minor) abuse of keyword arguments, and much criticism from misguided
functional advocates for its lack of "real closures"--I heavily debated this
because a) classes and closures are strikingly similar, and b) the
keyword-argument trick wasn't really that bad, once you got used to it. In
any case, with dynamic scoping, this problem has completely disappeared.

The second "problem" that everyone seems to keep bringing up is that lambda
limits you to expressions, not statements. This makes me laugh every time,
because this is one of the things that I *loved* about Python when I was
first learning it! If you get used to writing functions that only return
expressions, you are on the road to understanding the functional style! One
thing that I recommend that anyone try as a learning experience is this: try
writing a program where every single function starts with "return". Better
yet, write your whole program with lambdas. <screams from the back row> Of
course, I don't recommend doing this sort of thing "out in industry", but I
guarantee that you will learn to write code that is more reusable,
side-effect free, and finely decomposed once you have gained some practice
writing code this way.

I would not like to see lambda support "statements". I think that would ruin
a good thing. I would not like it removed from the language. I want it the
way it is. The only thing between "lambda" and perfection is the name. It
should be "fun" or something. If I had a lambda key on my keyboard, I would
press it. <grin>

"apply" is less of a big deal to me, but I'd still like to keep it because
it allows for greater portability. I feel so more strongly about map and
filter. Yes, I know about list comprehensions. I think they are wonderful, I
thank Guido for adding them, I thank Haskell for inspiring them, and I don't
want them to ever go away. But just because you can do a similar set of
things with list comprehensions than with map and filter doesn't mean that
they are completely redundant. In fact, I believe that it is advantageous to
design functions specifically for use with map and filter. If you design
this way, you will benefit from cleaner syntax than list comprehensions can
offer. For example:

- map(process_record, records)

compared with:

- [process_record(record) for record in records]

I'm aware that adding lambdas, nesting, multiple filters, etc. can make
map/filter much less readable than list comprehensions, but functional
decomposition is another solution. If you have to nest that much, perhaps
your functions are too complicated and need to be broken up. I'm not saying
that this is always the case, but for the sake of clarity - in certain
situations - I greatly prefer map/filter to list comprehensions. For
starters, they eliminate the need to name the temporary variable.

Rather than remove these important functional built-ins, I would like to see
two last built-ins be added: unzip (to reverse the behavior of zip), and
curry (see the example by Alex Martelli, et. al. in the Python Cookbook,
sec. 15.7). Anything else can be thrown into a "functional" standard module.
The global namespace doesn't need any more clutter, and I sympathize with
those who wish to reduce it, but--please!--not at the expense of the
functions that form the foundation of functional programming!

I have observed Guido making several comments about Python being
object-oriented from the core, and that the natural way of expressing
solutions is object-oriented. I think that Paul Prescod feels even more
strongly about this. It is true that many common functional techniques could
be re-implemented elegantly through the use of object-oriented techniques,
and the opposite is also true. You can program o-o without side effects, and
you can emulate classes with closures. However, please do not draw the
conclusion that supporting both methodologies would be redundant.

Please resist the temptation to oversimplify the language and force users
who enjoy Python's functional-friendly features to go back to the drawing
board, especially when Python's ability to do FP was a prime reason for
people like me to migrate to Python in the first place! I don't think that
objects are the way of the future. I think they are part of the future, but
I think that they focus too much on state, where I tend to concentrate on
data flow and functionality. If Python evolves to be a language that is
increasingly hostile toward functional programming, I will (*very
reluctantly*) have to look at other languages to focus my primary work on).

Finally, I'd like to make one comment about Perl. I think that this is
important and relevant. There is clearly a difference in philosophy between
Perl culture and Python culture. Perl says There's More Than One Way To Do
It, and Python begs to differ. Perl is all-inclusive, Python is more
exclusive. However, let's not get carried away with the exclusivity! There
are clearly multiple of ways of doing many things in Python, and that's not
a bad thing. Sometimes you want a list, other times you want an iterator.
Sometimes you want a list comprehension, other times you want map/filter.
Closures? Objects! Dispatches? Polymorphism! Inheritance? Composition? Just
because Perl says you can do anything any-which-way doesn't mean that to
compete Python should force you to a single method of problem-solving.

Perl is a beautiful thing. It encourages more creativity in the sense of
language design than any other language I have ever used, including Python.
There are many things to learn from Perl, and open-mindedness is one of
them. Java, on the other hand, is extremely rigid about its way of doing
things--trying to do functional programming in Java requires the use of
bulky wrapper classes instead of true, lightweight higher-order functions,
and its lack of parametric polymorphism makes the entire type system a pain
in the butt.

Python is a nice happy medium between regularity and freedom. I'd like to
see it stay that way.

Thanks for listening,
Dave

John Roth

unread,
Apr 15, 2003, 4:22:01 PM4/15/03
to

"Dave Benjamin" <ra...@lackingtalent.com> wrote in message
news:slrnb9on0q...@lackingtalent.com...

[snip long post about functional constructs]

I agree completely. I got turned on to the existing functional
constructs while I was doing a TDD challenge. I managed
to do that with exactly one if statement and no loops because
of the functional constructs.

However, losing apply() isn't a big deal because there is
an exactly equivalent construct. I'd hate to see the rest
of them go away, especially since the (possible) implementation
of PEP 308 will remove one of the restrictions on lambdas.

Also notice that there are a set of new functional constructs
in 2.3 alpha.

John Roth
>
> Thanks for listening,
> Dave


Dave Benjamin

unread,
Apr 15, 2003, 4:40:08 PM4/15/03
to
In article <v9oq71i...@news.supernews.com>, John Roth wrote:
> I agree completely. I got turned on to the existing functional
> constructs while I was doing a TDD challenge. I managed
> to do that with exactly one if statement and no loops because
> of the functional constructs.

TDD as in "test-driven development"? I'm not really familiar with this.
Got any good URLs to look at?

> However, losing apply() isn't a big deal because there is
> an exactly equivalent construct. I'd hate to see the rest
> of them go away, especially since the (possible) implementation
> of PEP 308 will remove one of the restrictions on lambdas.

You're right, it's not a big deal. I never use apply anymore, since
Python provides a very convenient syntactic-sugaring as a replacement.

But, I still want to point out the fact that this construct is Python-only.
On the other hand, apply can be implemented with nearly identical behavior
in many other languages, if it doesn't exist already.

> Also notice that there are a set of new functional constructs
> in 2.3 alpha.

I assume you're talking about the "itertools" module. I'm very interested in
this module, though I haven't fully grokked it. I like the "starmap" function.

I think it'd be good to have a module called "functional" where the more
unusual functional tools can live, and I know that it's been brought up before.
Polluting the built-ins further is obviously a bad thing for backward
compatability, not to mention the learning curve. But it would at least make
a statement that functional programming is possible and supported in Python.

Take care,
Dave

Jp Calderone

unread,
Apr 15, 2003, 4:30:02 PM4/15/03
to
On Tue, Apr 15, 2003 at 07:22:47PM -0000, Dave Benjamin wrote:
>
> [snip - comparisons to and examples from PHP]

>
> Guido's recent musings in the newsgroups and on his presentation on "Python
> Regrets" have made me a bit uneasy. In particular, they brought to light the
> fact that he generally prefers the object-oriented style to the functional
> style and would like to "deprecate" certain features:
>
> - apply, to be replaced with *-notation
> - map and filter, to be replaced with list comprehensions
> - lambda
>

While they take getting used to, you can't say that list comprehensions
aren't functional. They're not traditional-lisp functional, but that isn't
the only kind :)

> Lambda has had the thorniest history of all of these, I think. Lambda has
> its roots in LISP and the Lambda calculus, and can be used to create
> "anonymous functions" at runtime that can be passed around as needed. This
> is a very powerful and useful feature for functional programming, as well as
> for event-driven programming. It baffles me that anyone would want to remove
> it.

No worries, there are enough people who would shout loudly enough were
this to be removed that its existence is safe, at least for the near future.

Just make sure you give a holler anytime someone suggests discarding them.

> [snip - default argument hacks, nested scopes]


>
> The second "problem" that everyone seems to keep bringing up is that lambda
> limits you to expressions, not statements. This makes me laugh every time,
> because this is one of the things that I *loved* about Python when I was
> first learning it! If you get used to writing functions that only return
> expressions, you are on the road to understanding the functional style! One
> thing that I recommend that anyone try as a learning experience is this: try
> writing a program where every single function starts with "return". Better
> yet, write your whole program with lambdas. <screams from the back row> Of
> course, I don't recommend doing this sort of thing "out in industry", but I
> guarantee that you will learn to write code that is more reusable,
> side-effect free, and finely decomposed once you have gained some practice
> writing code this way.

Lambdas are an excellent tool for obfuscation, that's for sure. You're
right not to recommend overusing them in production code. Generally, I try
to limit myself to the simplest expressions, on the order of "x and y" or
"result[index]", and translate to fully fledged functions for larger
expressions. It's just easier to maintain.

Also, note that lambdas *aren't* side-effect free, because Python isn't
side-effect free. You can write ones that are, but then again, you can
write functions with "def" that are side-effect free too.

>
> I would not like to see lambda support "statements". I think that would ruin
> a good thing. I would not like it removed from the language. I want it the
> way it is. The only thing between "lambda" and perfection is the name. It
> should be "fun" or something. If I had a lambda key on my keyboard, I would
> press it. <grin>

Statements are, by definition, things which cannot appear in lambdas ;)
No worries here, I think.

>
> "apply" is less of a big deal to me, but I'd still like to keep it because
> it allows for greater portability. I feel so more strongly about map and
> filter. Yes, I know about list comprehensions. I think they are wonderful, I
> thank Guido for adding them, I thank Haskell for inspiring them, and I don't
> want them to ever go away. But just because you can do a similar set of
> things with list comprehensions than with map and filter doesn't mean that
> they are completely redundant. In fact, I believe that it is advantageous to
> design functions specifically for use with map and filter. If you design
> this way, you will benefit from cleaner syntax than list comprehensions can
> offer.

Luckily, map() and filter() are implementable in terms of list
comprehensions. So even in Python3k, when they're finally removed from the
language, you can implement them yourself in Python, and gain the
performance benefits of using a JIT on python bytecode ;)

> For example:
>
> - map(process_record, records)
>
> compared with:
>
> - [process_record(record) for record in records]
>
> I'm aware that adding lambdas, nesting, multiple filters, etc. can make
> map/filter much less readable than list comprehensions, but functional
> decomposition is another solution. If you have to nest that much, perhaps
> your functions are too complicated and need to be broken up. I'm not saying
> that this is always the case, but for the sake of clarity - in certain
> situations - I greatly prefer map/filter to list comprehensions. For
> starters, they eliminate the need to name the temporary variable.

I use both in my programs, but I find more and more that I only use
map/filter for the runtime speedup they sometimes provide. Again, list
comprehensions are functional, just not in the same way.

>
> Rather than remove these important functional built-ins, I would like to see
> two last built-ins be added: unzip (to reverse the behavior of zip), and
> curry (see the example by Alex Martelli, et. al. in the Python Cookbook,
> sec. 15.7). Anything else can be thrown into a "functional" standard module.
> The global namespace doesn't need any more clutter, and I sympathize with
> those who wish to reduce it, but--please!--not at the expense of the
> functions that form the foundation of functional programming!

The inverse of zip is already available (and with one less character than
unzip! ;). x == zip(*zip(x)) (ignoring sequence types, of course).

> [snip - flexibility of Python]


>
> Finally, I'd like to make one comment about Perl. I think that this is
> important and relevant. There is clearly a difference in philosophy between
> Perl culture and Python culture. Perl says There's More Than One Way To Do
> It, and Python begs to differ. Perl is all-inclusive, Python is more
> exclusive. However, let's not get carried away with the exclusivity! There
> are clearly multiple of ways of doing many things in Python, and that's not
> a bad thing. Sometimes you want a list, other times you want an iterator.
> Sometimes you want a list comprehension, other times you want map/filter.
> Closures? Objects! Dispatches? Polymorphism! Inheritance? Composition? Just
> because Perl says you can do anything any-which-way doesn't mean that to
> compete Python should force you to a single method of problem-solving.

I don't think Python is headed the way of Unlambda, don't worry :)

>
> Perl is a beautiful thing. It encourages more creativity in the sense of
> language design than any other language I have ever used, including Python.
> There are many things to learn from Perl, and open-mindedness is one of
> them. Java, on the other hand, is extremely rigid about its way of doing
> things--trying to do functional programming in Java requires the use of
> bulky wrapper classes instead of true, lightweight higher-order functions,
> and its lack of parametric polymorphism makes the entire type system a pain
> in the butt.

What I think is an important distinction to make here is the language vs
the library. Right now, there are overlapping language features. I'd much
prefer it if some of the things, even the useful things like map(), were
re-implemented in terms of other Python features and moved out of the
language and into the library. This gives the best of both worlds - a
language simple to learn and use that also provides an expressive set of
features through its stdlib.

>
> Python is a nice happy medium between regularity and freedom. I'd like to
> see it stay that way.
>

Jp

--
Somewhere, something incredible is waiting to be known.
-- Carl Sagan
--
up 26 days, 17:02, 6 users, load average: 1.06, 1.16, 1.12

laotseu

unread,
Apr 15, 2003, 7:49:37 PM4/15/03
to
Dave Benjamin wrote:
> It has been my increasing concern that Python is headed in a decidedly
> object-oriented direction, ignoring the benefits it currently offers to
> functional programmers.

(snip a long and interesting post)

Agree++

Even for OO programmers, functionnal features in Python are IMHO a great
plus, and BTW functionnal and OO paradigm does not have to conflict
(that would be functionnal vs imperative and object vs procedural). CLOS
is one of the great system objects out here, and it's been implemented
on top of a functionnal language, so...

In fact, I'd rather regret that Python is not more functional *and*
object oriented !-)

My 2 eurocents
Laotseu

laotseu

unread,
Apr 15, 2003, 7:50:31 PM4/15/03
to
Dave Benjamin wrote:
> It has been my increasing concern that Python is headed in a decidedly
> object-oriented direction, ignoring the benefits it currently offers to
> functional programmers.

(snip a long and interesting post)

Agree++

Even for OO programmers, functionnal features in Python are IMHO a great
plus, and BTW functionnal and OO paradigm does not have to conflict
(that would be functionnal vs imperative and object vs procedural). CLOS
is one of the great system objects out here, and it's been implemented
on top of a functionnal language, so...

In fact, I'd rather regret that Python is not more functional *and*
object oriented !-)

Guido, if you hear us... !-)

My 2 eurocents
Laotseu

Alexander Schmolck

unread,
Apr 15, 2003, 5:46:38 PM4/15/03
to
Dave Benjamin <ra...@lackingtalent.com> writes:

> The next thing I read will probably not surprise you if you have ever done a
> Google search on functional programming. It was David Mertz's "Charming
> Python" series on IBM's DeveloperWorks. His papers were not easy to digest
> in one sitting, but I made a great effort to understand them and apply the
> techniques he described. At this point, I should mention that I was still
> programming only in PHP!

I think your life might be much happier if you just went to
http://www.drscheme.org/, dowloaded Dr Scheme and used *that* for
webdevelopment. Then you can use a real functional programming language and
read books by people who actually have a real clue about functional
programming (there is lots of *excellent* material available on-line and for
free, like SICP and HTDP, the latter uses Dr Scheme -- also have a look at
http://www.cs.brown.edu/courses/cs173/2001/Lectures/). Why settle for some
second-rate immitation? [1]

(Dr Scheme *does* have web libraries, I've never used them but I'd suspect
they shouldn't be too bad, because they seem to have hit on trick of using
webdevelopment as application domain to bring things like continuations to the
unwashed masses (viz. their sophomores) :).

> - lambda
>
> Lambda has had the thorniest history of all of these, I think. Lambda has
> its roots in LISP and the Lambda calculus, and can be used to create
> "anonymous functions" at runtime that can be passed around as needed. This
> is a very powerful and useful feature for functional programming, as well as
> for event-driven programming. It baffles me that anyone would want to remove
> it.

Ain't gonna happen. Anyway you can always replace

foo(lambda x: x+3)
with:
def bar(x): return x + 3
foo(bar)


> keyword-argument trick wasn't really that bad, once you got used to it. In
> any case, with dynamic scoping, this problem has completely disappeared.

^^^^^^^^^^^^^^^
not quite.


> The second "problem" that everyone seems to keep bringing up is that lambda
> limits you to expressions, not statements. This makes me laugh every time,
> because this is one of the things that I *loved* about Python when I was
> first learning it! If you get used to writing functions that only return
> expressions, you are on the road to understanding the functional style! One

Only that python won't let you use rather helpful things like ``if`` as
an expression, but never mind.

> In fact, I believe that it is advantageous to design functions specifically
> for use with map and filter. If you design this way, you will benefit from
> cleaner syntax than list comprehensions can offer. For example:

I wonder how a function written for map would look different from one written
for a list comprehension...

> Rather than remove these important functional built-ins, I would like to see
> two last built-ins be added: unzip (to reverse the behavior of zip), and

There is already an unzip function and it's written ``zip(*...)``

> curry (see the example by Alex Martelli, et. al. in the Python Cookbook,

Why not just use lambda? Python's argument passing is fairly complex, so I'm
not sure whether one (or rather two) curry function(s) would be worth the pain
(at least not if you tell your emacs to display lambda as greek character).

'as

Footnotes:
[1] I'm talking about *functional* programming.

David Mertz

unread,
Apr 15, 2003, 4:55:33 PM4/15/03
to
|> However, losing apply() isn't a big deal because there is
|> an exactly equivalent construct.

Not quite. For Appendix A of my book, I discuss one (realistic) example
where extended call syntax and apply() are not directly substitutable:

In most cases, the extended call syntax is more readable, since
the call closely resembles the -declaration- syntax of generic
positional and keyword arguments. But in a few
cases--particularly in higher-order functions--the older
`apply()` built-in function is still useful. For example,
suppose that you have an application that will either perform
an action immediately or defer it for later, depending on some
condition. You might program this application as:

#*----------- apply() as first-class function -----------#
defer_list = []
if some_runtime_condition():
doIt = apply
else:
doIt = lambda *x: defer_list.append(x)
#...do stuff like read records and options...
doIt(operation, args, keywds)
#...do more stuff...
#...carry out deferred actions...
map(lambda (f,args,kw): f(*args,**kw), defer_list)

Since `apply()` is itself a first-class function rather than a
syntactic form, you can pass it around--or in the example,
bind it to a name.

Of course, you could define your own apply() in one line of code if the
function were not built-in.

|..."itertools" module....


|I think it'd be good to have a module called "functional" where the
|more unusual functional tools can live

I definitely agree with this idea. A [functional] module in the
standard library would be GREAT. Xoltar had a number of useful ideas,
although other people have proposed different implementations of some of
them... so the best version would need to be decided.

But another collection of functions that I would REALLY like to see in
such a hypothetical standard library would be a good set of Higher Order
Functions (HOFs). My Gnosis Utilities contains gnosis.utils.combinators,
which has at least the ideas for the most useful few. The
implementations are overly concise and under documented though. But
it's short enough to list here:

from operator import mul, add, truth
apply_each = lambda fns, args=[]: map(apply, fns, [args]*len(fns))
bools = lambda lst: map(truth, lst)
bool_each = lambda fns, args=[]: bools(apply_each(fns, args))
conjoin = lambda fns, args=[]: reduce(mul, bool_each(fns, args))
all = lambda fns: lambda arg, fns=fns: conjoin(fns, (arg,))
both = lambda f,g: all((f,g))
all3 = lambda f,g,h: all((f,g,h))
and_ = lambda f,g: lambda x, f=f, g=g: f(x) and g(x)
disjoin = lambda fns, args=[]: reduce(add, bool_each(fns, args))
some = lambda fns: lambda arg, fns=fns: disjoin(fns, (arg,))
either = lambda f,g: some((f,g))
anyof3 = lambda f,g,h: some((f,g,h))
or_ = lambda f,g: lambda x, f=f, g=g: f(x) or g(x)
compose = lambda f,g: lambda x, f=f, g=g: f(g(x))
compose3 = lambda f,g,h: lambda x, f=f, g=g, h=h: f(g(h(x)))
ident = lambda x: x
not_ = lambda f: lambda x, f=f: not f(x)

def shortcut_all(*fns):
accum = fns[0]
for fn in fns[1:]:
accum = and_(accum, fn)
return accum
lazy_all = shortcut_all

def shortcut_any(*fns):
accum = fns[0]
for fn in fns[1:]:
accum = or_(accum, fn)
return accum
lazy_any = shortcut_any


Yours, David...

--
Keeping medicines from the bloodstreams of the sick; food from the bellies
of the hungry; books from the hands of the uneducated; technology from the
underdeveloped; and putting advocates of freedom in prisons. Intellectual
property is to the 21st century what the slave trade was to the 16th.

Dave Benjamin

unread,
Apr 15, 2003, 6:55:50 PM4/15/03
to
In article <mailman.1050438685...@python.org>,

Jp Calderone wrote:
> While they take getting used to, you can't say that list comprehensions
> aren't functional. They're not traditional-lisp functional, but that isn't
> the only kind :)

Certainly not, especially considering where they supposedly came from. I
think that they are certainly functional, but only representative of
particular (but common) functional idioms related to list processing.

For instance, there has yet to be a dictionary comprehension. This is
something I think would be nice to add, because I currently do things like
this:

dict([(x['key'], x['value']) for x in data])

Where it might be nice to say instead:

{x['key']: x['value'] for x in data}

But I'm getting off track here. I'm not arguing that we should have
map/filter instead of list comprehensions, or the other way around. I think
both are useful and operate on different levels, similar to the relationship
between relational algebra and relational calculus. Just because they can
both do the same things doesn't mean one should be abolished in lieu of the
other.

And in a broader sense, I'm not even talking about built-in functions or
language constructs so much as the direction of Python's evolution. I don't
necessarily think that Python needs to become another LISP, though I agree
with Paul Graham on many of his observations of language evolution. I think
that Python is just fine being Python, but I don't want to see it become
another Java either. The day Python tells me "top-level functions have been
deprecated" is the day I find a new pet language. ;)

>> [snip - my plea for lambda love]


>
> No worries, there are enough people who would shout loudly enough were
> this to be removed that its existence is safe, at least for the near future.
>
> Just make sure you give a holler anytime someone suggests discarding them.

Well, I suppose that's what I'm now attempting to do. =)

> Lambdas are an excellent tool for obfuscation, that's for sure. You're
> right not to recommend overusing them in production code. Generally, I try
> to limit myself to the simplest expressions, on the order of "x and y" or
> "result[index]", and translate to fully fledged functions for larger
> expressions. It's just easier to maintain.

This has certainly crossed my mind, and I understand that this is one of the
main reasons why Guido dislikes the construct. He seems to put readability
at a very high priority, which is why Python is often so elegant. But
readability is one of many things that are important to me. Another is
mathematical conciseness. If you have represented an idea very formally and
concisely, you can always expand it so that all functions and variables are
named and traditional if/while blocks are used. Doing the reverse is often
much more difficult.

For an even greater exercise in obfuscation, see my functional types recipe.
Warning: you may lose respect for me after you read this. ;)
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/161403

I have successfully produced a custom XML-generation script that translates
a Java-based object model into XML using Jython. I began by writing only
lambdas, and almost all of them were one-liners. Then, I turned the lambdas
into proper "def"ined functions. Then, I observed the patterns in argument
passing to determine what data could be shared, and used this observation to
determine what classes to create. When I was done, I had something that
looked like it had been an object-oriented design from the start, but it was
very logical, concise, fast, and readable. On top of all of that, I had
*confidence* that my code worked properly because it was designed from
small, easily-defined parts that I could (attempt to) prove the correct
operation of. Proving the correctness of objects isn't so easy.

> Also, note that lambdas *aren't* side-effect free, because Python isn't
> side-effect free. You can write ones that are, but then again, you can
> write functions with "def" that are side-effect free too.

This is true. And you can write classes that are side-effect free, too. The
string object is a perfect example. It's also an example of how performance
can suffer when you enforce being side-effect free (the += operator). It's
not cut-and-dry by any means. However, because of the way Guido designed
lists and dictionaries, mutators typically return None, so it's awkward at
best to write lambdas that use them. This encourages side-effect-free lambdas.

See this page for a good laugh:
http://p-nand-q.com/lambda.htm

> Statements are, by definition, things which cannot appear in lambdas ;)
> No worries here, I think.

Except that there are some that consider lambda "broken", and that it should
either support statements or be removed entirely. This I disagree with.

> Luckily, map() and filter() are implementable in terms of list
> comprehensions. So even in Python3k, when they're finally removed from the
> language, you can implement them yourself in Python, and gain the
> performance benefits of using a JIT on python bytecode ;)

So they are scheduled to be removed! I knew it! =) This is why I'm paranoid!

> The inverse of zip is already available (and with one less character than
> unzip! ;). x == zip(*zip(x)) (ignoring sequence types, of course).

Cool! Thanks for the tip...

> I don't think Python is headed the way of Unlambda, don't worry :)

Hehe... it does need a COME FROM construct though. Who wants to help me
write the PEP for that one?

> What I think is an important distinction to make here is the language vs
> the library. Right now, there are overlapping language features. I'd much
> prefer it if some of the things, even the useful things like map(), were
> re-implemented in terms of other Python features and moved out of the
> language and into the library. This gives the best of both worlds - a
> language simple to learn and use that also provides an expressive set of
> features through its stdlib.

I agree with your premise, but I've been feeling lately that there isn't
such a clear distinction between language and library. For instance, when
the string object and the string module merged, the main difference was that
my sentences were rearranged and I didn't have to say "import string"
anymore. But I never really thought in terms of a string *library*, so on the
surface it was part of the language all along.

If I just have to say "from functional import *" to get an environment
friendly to FP, I will happily quiet down and mind my own business. I just
want to make sure FP is being represented. ;)

Thanks for your reply,
Dave

Dave Benjamin

unread,
Apr 15, 2003, 7:04:06 PM4/15/03
to
In article <3E9C9A91...@removethis.free.fr>, laotseu wrote:
> Even for OO programmers, functionnal features in Python are IMHO a great
> plus, and BTW functionnal and OO paradigm does not have to conflict
> (that would be functionnal vs imperative and object vs procedural). CLOS
> is one of the great system objects out here, and it's been implemented
> on top of a functionnal language, so...

This is a good point. O'Caml comes to mind as well--a functional language
with object support right out of the box. There is no reason the two
methodologies need to be mutually exclusive, or step on each other's toes.

But, there is of course the risk of setting precedent that there are more
than one ways to do it, and this is why I brought up Perl. I think that
there is a subtle fear in the Python community of letting Python become too
much like Perl, especially since both languages have similar application
domains. There are other options besides TMTOWTDI and military rigor. This
is precisely why I like Python, because it seems to be a good compromise
between the two.

I think that list comprehensions bridge the gap somewhat between FP and OO
methods, and this is one thing I really like them for. For instance:

[obj.method(x) for x in data]

looks nicer to me than:

map(lambda x: obj.method(x), data)

because it puts the emphasis on the method call, not the variable.

> In fact, I'd rather regret that Python is not more functional *and*
> object oriented !-)

In what ways? =)

Thanks for your input,
Dave

Dave Benjamin

unread,
Apr 15, 2003, 7:17:26 PM4/15/03
to
In article <yfs7k9v...@black132.ex.ac.uk>, Alexander Schmolck wrote:
> I think your life might be much happier if you just went to
> http://www.drscheme.org/, dowloaded Dr Scheme and used *that* for
> webdevelopment. Then you can use a real functional programming language and
> read books by people who actually have a real clue about functional
> programming (there is lots of *excellent* material available on-line and for
> free, like SICP and HTDP, the latter uses Dr Scheme -- also have a look at
> http://www.cs.brown.edu/courses/cs173/2001/Lectures/). Why settle for some
> second-rate immitation? [1]

I may just take your advice and investigate that. Thanks for the reference.
But keep in mind that I'm not saying "I don't like Python, it's not
functional enough". I'm saying "I love Python, it lets me work in both an FP
and OOP style, and this makes me happy. I just don't want to see FP support
drop out of the picture."

> (Dr Scheme *does* have web libraries, I've never used them but I'd suspect
> they shouldn't be too bad, because they seem to have hit on trick of using
> webdevelopment as application domain to bring things like continuations to the
> unwashed masses (viz. their sophomores) :).

Interesting.

> Ain't gonna happen. Anyway you can always replace
>
> foo(lambda x: x+3)
> with:
> def bar(x): return x + 3
> foo(bar)
>

That's true, but then I have to name "bar". And part of the joy of FP is not
having to name *everything*. Naming things is important if you need to call
them up later, but it's a hassle to name intermediate values, just as it
would be a hassle to have to say:

result = list()
result.append(x)
result.append(y)
result.append(z)
return result

When Python lets you instead say:

return [x, y, z]

>> keyword-argument trick wasn't really that bad, once you got used to it. In
>> any case, with dynamic scoping, this problem has completely disappeared.
> ^^^^^^^^^^^^^^^
> not quite.

Am I using the wrong terminology here? I'm specifically talking about the
named-argument hack to get around Python's previous lack of nested scopes.
This specific problem, as far as I know, is gone now. Am I missing something?

> Only that python won't let you use rather helpful things like ``if`` as
> an expression, but never mind.

Well, this leads us to the ternary operator thing, which I'll let other
people argue about. ;) I'm happy with my short-circuiting and/or for now.

>> In fact, I believe that it is advantageous to design functions specifically
>> for use with map and filter. If you design this way, you will benefit from
>> cleaner syntax than list comprehensions can offer. For example:
>
> I wonder how a function written for map would look different from one written
> for a list comprehension...

Well, I don't think people usually write functions for list comprehensions
at all. I've never done it. I've never made it an explicit part of my design
for an API that someone use my functions in list comprehensions. But this
could just be because I'm still learning where they fit in best.

However, I have written an API that consisted of functions that curried
their own arguments and could be used in a map, like this:

>>> addx = lambda x: lambda y: x + y
>>> map(addx(5), range(5))
[5, 6, 7, 8, 9]

>> Rather than remove these important functional built-ins, I would like to see
>> two last built-ins be added: unzip (to reverse the behavior of zip), and
>
> There is already an unzip function and it's written ``zip(*...)``

Thanks, I didn't know this.

>> curry (see the example by Alex Martelli, et. al. in the Python Cookbook,
>
> Why not just use lambda? Python's argument passing is fairly complex, so I'm
> not sure whether one (or rather two) curry function(s) would be worth the pain
> (at least not if you tell your emacs to display lambda as greek character).

Because it's a common operation in some contexts, and by naming it, its
behavior can be formalized. You can of course write curried functions, and
even self-currying functions (like my "addx" example above) with lambdas.

Perhaps it should go in the "functional" module, along with "compose" and
all that other fun stuff. I still like map/filter being global, though...

Thanks,
Dave

Jp Calderone

unread,
Apr 15, 2003, 8:35:24 PM4/15/03
to
On Tue, Apr 15, 2003 at 11:17:26PM -0000, Dave Benjamin wrote:
> In article <yfs7k9v...@black132.ex.ac.uk>, Alexander Schmolck wrote:
> [snip]

>
> >> keyword-argument trick wasn't really that bad, once you got used to it. In
> >> any case, with dynamic scoping, this problem has completely disappeared.
> > ^^^^^^^^^^^^^^^
> > not quite.
>
> Am I using the wrong terminology here? I'm specifically talking about the
> named-argument hack to get around Python's previous lack of nested scopes.
> This specific problem, as far as I know, is gone now. Am I missing something?
>

I think you meant "partial lexical scoping" ;) Dynamic scoping is what
Python used to do. Since it isn't quite lexical scoping, it's best to just
stick with the term "nested scopes".

> [snip]

Jp

--
#!/bin/bash
( LIST=(~/.sigs/*.sig)
cat ${LIST[$(($RANDOM % ${#LIST[*]}))]}
echo -- $'\n' `uptime | sed -e 's/.*m//'` ) > ~/.signature
--
up 26 days, 21:02, 4 users, load average: 0.25, 0.31, 0.63

Jp Calderone

unread,
Apr 15, 2003, 8:45:37 PM4/15/03
to
On Tue, Apr 15, 2003 at 11:04:06PM -0000, Dave Benjamin wrote:
> In article <3E9C9A91...@removethis.free.fr>, laotseu wrote:
> > Even for OO programmers, functionnal features in Python are IMHO a great
> > plus, and BTW functionnal and OO paradigm does not have to conflict
> > (that would be functionnal vs imperative and object vs procedural). CLOS
> > is one of the great system objects out here, and it's been implemented
> > on top of a functionnal language, so...
>
> This is a good point. O'Caml comes to mind as well--a functional language
> with object support right out of the box. There is no reason the two
> methodologies need to be mutually exclusive, or step on each other's toes.
>
> But, there is of course the risk of setting precedent that there are more
> than one ways to do it, and this is why I brought up Perl. I think that
> there is a subtle fear in the Python community of letting Python become too
> much like Perl, especially since both languages have similar application
> domains. There are other options besides TMTOWTDI and military rigor. This
> is precisely why I like Python, because it seems to be a good compromise
> between the two.
>
> I think that list comprehensions bridge the gap somewhat between FP and OO
> methods, and this is one thing I really like them for. For instance:
>
> [obj.method(x) for x in data]
>
> looks nicer to me than:
>
> map(lambda x: obj.method(x), data)
>

This reminds me of something I've long desired. A "message" type. I
think one might be implementable with descriptors, but I haven't gotten
around to figuring out just how yet.

As many of us know, you can do this in 2.2:

reduce(int.__add__, [1, 2, 3])

Unfortunately, this breaks when ints get promoted to longs, because you
can't pass longs to int.__add__! Similarly:

map(ClassObj.method, [x, y, z])

works, so long as x, y, and z are instances of ClassObj. But if they are
instances of different types, all of which merely happen to implement
method, you're out of luck! This is resolved with list comprehensions:

[i.method(foo) for i in [x, y, z]]

But what I'd like to see is a way to do:

map(message("method", foo), [x, y, z])

Of course, you could easily implement this as:

def message(name, *args, **kwarg):
return lambda o: getattr(o, name)(*args, **kwargs)

But this is stupendously inefficient. It'd be really great if there were
some built-in MessageType that could be used this way and also managed to
carry out the work in an efficient manner.

And I think this is both a highly functional and a highly OO feature :)

Dave Benjamin

unread,
Apr 15, 2003, 9:16:50 PM4/15/03
to
In article <mailman.1050453385...@python.org>,

Jp Calderone wrote:
> I think you meant "partial lexical scoping" ;) Dynamic scoping is what
> Python used to do. Since it isn't quite lexical scoping, it's best to just
> stick with the term "nested scopes".

Ahh... this sounds familiar. Thanks, and sorry for the confusion. =)

Now, just to be thorough, the reason Python doesn't support "full lexical
scoping" is...? I'm guessing that it doesn't apply to classes (thus still
necessitating the use of self.*). Anything else?

Thanks,
Dave

Alexander Schmolck

unread,
Apr 15, 2003, 9:21:25 PM4/15/03
to
Jp Calderone <exa...@intarweb.us> writes:

> On Tue, Apr 15, 2003 at 11:17:26PM -0000, Dave Benjamin wrote:
> > In article <yfs7k9v...@black132.ex.ac.uk>, Alexander Schmolck wrote:
> > [snip]
> >
> > >> keyword-argument trick wasn't really that bad, once you got used to it. In
> > >> any case, with dynamic scoping, this problem has completely disappeared.
> > > ^^^^^^^^^^^^^^^
> > > not quite.
> >
> > Am I using the wrong terminology here? I'm specifically talking about the
> > named-argument hack to get around Python's previous lack of nested scopes.
> > This specific problem, as far as I know, is gone now. Am I missing something?
> >
>
> I think you meant "partial lexical scoping" ;) Dynamic scoping is what
> Python used to do. Since it isn't quite lexical scoping, it's best to just
> stick with the term "nested scopes".

Aargh. No! You also have a look at:

http://www.supelec.fr/docs/cltl/clm/node43.html

'as

Alexander Schmolck

unread,
Apr 15, 2003, 9:19:38 PM4/15/03
to
Dave Benjamin <ra...@lackingtalent.com> writes:

> In article <yfs7k9v...@black132.ex.ac.uk>, Alexander Schmolck wrote:
> > I think your life might be much happier if you just went to
> > http://www.drscheme.org/, dowloaded Dr Scheme and used *that* for
> > webdevelopment. Then you can use a real functional programming language and
> > read books by people who actually have a real clue about functional
> > programming (there is lots of *excellent* material available on-line and for
> > free, like SICP and HTDP, the latter uses Dr Scheme -- also have a look at
> > http://www.cs.brown.edu/courses/cs173/2001/Lectures/). Why settle for some
> > second-rate immitation? [1]
>
> I may just take your advice and investigate that. Thanks for the reference.
> But keep in mind that I'm not saying "I don't like Python, it's not
> functional enough". I'm saying "I love Python, it lets me work in both an FP
> and OOP style, and this makes me happy. I just don't want to see FP support
> drop out of the picture."

Well it seems to me that you're currently *really* keen on functional
programming. You can do that (and learn about it) much better in scheme than
in python, so even if you want to program in python for the rest of your life
afterwards it might well be worth it. I mean you wouldn't want to learn OO in
C, would you -- there a fewer good ressources and it's just much more of a
pain (this comparison is of course overly pessimistic -- C is just horrible
and python really isn't).

Plus, Dr Scheme is a rather nice learning environment, has plenty of cool
stuff (and quite a few libraries) and let's you do OO, too (if you use Emacs
check out quack.el, BTW).


> That's true, but then I have to name "bar". And part of the joy of FP is not
> having to name *everything*. Naming things is important if you need to call
> them up later, but it's a hassle to name intermediate values

No argument here. I tend to think python would have been a better language if
it had included something like smalltalk-like blocks from day 1 (I still
really like python).

> >> keyword-argument trick wasn't really that bad, once you got used to it. In
> >> any case, with dynamic scoping, this problem has completely disappeared.
> > ^^^^^^^^^^^^^^^
> > not quite.
>
> Am I using the wrong terminology here? I'm specifically talking about the
> named-argument hack to get around Python's previous lack of nested scopes.
> This specific problem, as far as I know, is gone now. Am I missing something?

Yes but certainly not due to dynamic scoping (which python doesn't even have,
as you can see from the raging Emacs thread). It now has non-crippled lexical
scope :)

(have a look at http://www.supelec.fr/docs/cltl/clm/node43.html for a good
explanation)

> Well, I don't think people usually write functions for list comprehensions
> at all.

Never mind, I just shouldn't write postings when I'm tired (like now:).

'as

David Eppstein

unread,
Apr 15, 2003, 9:23:47 PM4/15/03
to
On Tue, Apr 15, 2003 at 11:04:06PM -0000, Dave Benjamin wrote:
> > I think that list comprehensions bridge the gap somewhat between FP and OO
> > methods, and this is one thing I really like them for. For instance:
> >
> > [obj.method(x) for x in data]
> >
> > looks nicer to me than:
> >
> > map(lambda x: obj.method(x), data)

Sure, but wouldn't it be even better to use
map(obj.method, data)
?

--
David Eppstein http://www.ics.uci.edu/~eppstein/
Univ. of California, Irvine, School of Information & Computer Science

Dave Benjamin

unread,
Apr 15, 2003, 9:40:12 PM4/15/03
to
In article <eppstein-8427F2...@news.service.uci.edu>,

David Eppstein wrote:
> On Tue, Apr 15, 2003 at 11:04:06PM -0000, Dave Benjamin wrote:
>> > I think that list comprehensions bridge the gap somewhat between FP and OO
>> > methods, and this is one thing I really like them for. For instance:
>> >
>> > [obj.method(x) for x in data]
>> >
>> > looks nicer to me than:
>> >
>> > map(lambda x: obj.method(x), data)
>
> Sure, but wouldn't it be even better to use
> map(obj.method, data)

Yes, of course. I didn't think that example out thoroughly. This trick
works, but only if that method happens to be a function of one argument. See
Jp Calderone's last post about the message types - he identified the problem
I was trying to convey here.

Thanks,
Dave

Jack Diederich

unread,
Apr 15, 2003, 9:54:07 PM4/15/03
to
On Tue, Apr 15, 2003 at 11:04:06PM -0000, Dave Benjamin wrote:
> But, there is of course the risk of setting precedent that there are more
> than one ways to do it, and this is why I brought up Perl. I think that
> there is a subtle fear in the Python community of letting Python become too
> much like Perl, especially since both languages have similar application
> domains. There are other options besides TMTOWTDI and military rigor. This
> is precisely why I like Python, because it seems to be a good compromise
> between the two.

No problem, lets just yank out list comprehensions :)

list comps versus map/filter comes down to personal preference and coding
style. I like map & filter.

fearing TMTOWTDI is good, but python hasn't fallen down because people can
write abominations like

i = 0
sum = 0
while (i < len(mylist)):
sum = sum + mylist[i]
i = i + 1

at a guess most people do

sum = 0
for (guy) in mylist:
sum += guy

or my favorite

sum = reduce(int.__add__, mylist, 0) # forget that zero at your peril

TOOWTDI when overdone makes for a bondage and discipline language.
The BDFL gets to decide the balance, sometimes with people whispering in his
ear, and sometimes with people screaming.

The ternary vote thing was more like a room full of crazy homeless people
talking to themselves.

-jack

Dave Benjamin

unread,
Apr 15, 2003, 10:05:58 PM4/15/03
to
In article <yfsistf...@black132.ex.ac.uk>, Alexander Schmolck wrote:
> Well it seems to me that you're currently *really* keen on functional
> programming. You can do that (and learn about it) much better in scheme than
> in python, so even if you want to program in python for the rest of your life
> afterwards it might well be worth it. I mean you wouldn't want to learn OO in
> C, would you -- there a fewer good ressources and it's just much more of a
> pain (this comparison is of course overly pessimistic -- C is just horrible
> and python really isn't).

Point taken. I followed that lecture notes link, by the way. Thanks for
sending that. It's interesting how the author begins by describing a GIF
viewer as an interpreter.

>> That's true, but then I have to name "bar". And part of the joy of FP is not
>> having to name *everything*. Naming things is important if you need to call
>> them up later, but it's a hassle to name intermediate values
>
> No argument here. I tend to think python would have been a better language if
> it had included something like smalltalk-like blocks from day 1 (I still
> really like python).

Are those anything like code blocks in Ruby? I think that's a cool idea...

> Yes but certainly not due to dynamic scoping (which python doesn't even have,
> as you can see from the raging Emacs thread). It now has non-crippled lexical
> scope :)

Thanks, I stand corrected. ;)

Peace,
Dave

Courageous

unread,
Apr 15, 2003, 10:42:29 PM4/15/03
to

> Lambdas are an excellent tool for obfuscation, that's for sure. You're
>right not to recommend overusing them in production code. Generally, I try
>to limit myself to the simplest expressions, on the order of "x and y" or
>"result[index]", and translate to fully fledged functions for larger
>expressions. It's just easier to maintain.

Anonymous functions are occasionally useful, as in Java's anonymous
class expressions, really used as a poor man's lambda of sorts. I've
seen this overused, though, that's for sure.

C//

Jack Diederich

unread,
Apr 15, 2003, 10:23:22 PM4/15/03
to
On Tue, Apr 15, 2003 at 08:45:37PM -0400, Jp Calderone wrote:
> reduce(int.__add__, [1, 2, 3])
>
> Unfortunately, this breaks when ints get promoted to longs, because you
> can't pass longs to int.__add__!

Or when the passed in list is empty.
Why is the 3rd argument to reduce optional again?

>
> map(ClassObj.method, [x, y, z])
>
> works, so long as x, y, and z are instances of ClassObj. But if they are
> instances of different types, all of which merely happen to implement
> method, you're out of luck! This is resolved with list comprehensions:
>
> [i.method(foo) for i in [x, y, z]]
>
> But what I'd like to see is a way to do:
>
> map(message("method", foo), [x, y, z])
>
> Of course, you could easily implement this as:
>
> def message(name, *args, **kwarg):
> return lambda o: getattr(o, name)(*args, **kwargs)
>
> But this is stupendously inefficient. It'd be really great if there were
> some built-in MessageType that could be used this way and also managed to
> carry out the work in an efficient manner.

this adds 3 extra function calls, 1 for message(), 1 for lambda, and 1 for
the getattr.

doing plane-jane
map(lambda x:x.method(foo), [x, y, z])
just has one extra level of function call overhead and does what you want

I was a little disapointed that the implementaion in bltinmodule.c doesn't
special case lambdas but instead does a regular function call. I don't think
it is possible to change the lambda since they are anonymous, so they could be
speical cased like list comps (which generate the bytecode for a for loop
during compile)

If lambdas were special-cased in this way the message("method", foo) could
only be _as efficient_ as lambdas even if it were made as core a part of the
language as list comps. And the message() syntax is harder to read to boot.

-jack

Greg Ewing (using news.cis.dfn.de)

unread,
Apr 15, 2003, 11:37:27 PM4/15/03
to
Jp Calderone wrote:
> I think you meant "partial lexical scoping" ;) Dynamic scoping is what
> Python used to do.

No, it didn't!

There isn't any widely understood name for what Python used
to do, because no other language has ever been quirky
enough to do it that way. It was lexical, but with only
three levels visible at any one time.

--
Greg Ewing, Computer Science Dept,
University of Canterbury,
Christchurch, New Zealand
http://www.cosc.canterbury.ac.nz/~greg

Greg Ewing (using news.cis.dfn.de)

unread,
Apr 15, 2003, 11:47:15 PM4/15/03
to
Jack Diederich wrote:
> I was a little disapointed that the implementaion in bltinmodule.c doesn't
> special case lambdas but instead does a regular function call.

How exactly would you propose to special-case lambdas?

Dave Benjamin

unread,
Apr 16, 2003, 2:11:49 AM4/16/03
to
In article <sggp9v8lpk0045klm...@4ax.com>, Courageous wrote:
> Anonymous functions are occasionally useful, as in Java's anonymous
> class expressions, really used as a poor man's lambda of sorts. I've
> seen this overused, though, that's for sure.

How frequently a feature is useful depends on the problem domain. Java's
anonymous classes are a poor substitute because they carry so much baggage.
For comparison, here's an implementation and usage of map in Java:

static interface Functor {Object call(Object[] args);}

static Object[] map(Functor func, Object[] array) {
Object[] result = new Object[array.length];
for (int i = 0; i < array.length; i++) {
result[i] = func.call(new Object[] {array[i]});
}
return result;
}

public static void main(String args[]) {
System.out.println(Arrays.asList(map(
new Functor() {
public Object call(Object[] args) {
return args[0] + ", world!";
}
}, new String[] {"Hello", "Goodbye"}
)));
}

And the same usage in Python:

>>> print map(lambda x: x + ', world!', ['Hello', 'Goodbye'])
['Hello, world!', 'Goodbye, world!']

This is why Java is IMHO unfit for common functional tasks where Python
shines with elegance. As to whether or not anonymous functions can be
overused, I think any feature can be overused. Classes, for one. In fact, in
my day to day work, I find the two of similar usefulness, but maybe it's
just because of the way I program. =)

Peace,
Dave

Dave Benjamin

unread,
Apr 16, 2003, 2:13:41 AM4/16/03
to
In article <b7iigt$1d3jt$1...@ID-169208.news.dfncis.de>,

Greg Ewing (using news.cis.dfn.de) wrote:
> There isn't any widely understood name for what Python used
> to do, because no other language has ever been quirky
> enough to do it that way. It was lexical, but with only
> three levels visible at any one time.

Three? I thought it was two! Locals, globals, and...?

Dave

Anthony Baxter

unread,
Apr 16, 2003, 2:22:05 AM4/16/03
to

>>> Dave Benjamin wrote

> Three? I thought it was two! Locals, globals, and...?

builtins.


kosh

unread,
Apr 16, 2003, 4:53:56 AM4/16/03
to
On Tuesday 15 April 2003 06:45 pm, Jp Calderone wrote:
> As many of us know, you can do this in 2.2:
>
> reduce(int.__add__, [1, 2, 3])
>
> Unfortunately, this breaks when ints get promoted to longs, because you
> can't pass longs to int.__add__! Similarly:

Thankfully this is trivially solved. I just tested with python 2.3a2+

import operator
reduce(operator.__add__, range(6000000))

which gives

17999997000000L


Alexander Schmolck

unread,
Apr 16, 2003, 7:51:56 AM4/16/03
to
Dave Benjamin <ra...@lackingtalent.com> writes:

> > No argument here. I tend to think python would have been a better language if
> > it had included something like smalltalk-like blocks from day 1 (I still
> > really like python).
>
> Are those anything like code blocks in Ruby? I think that's a cool idea...

Yes, in pretty much the same way that butter is like margarine.


'as

Tj

unread,
Apr 16, 2003, 8:50:11 AM4/16/03
to
Alexander Schmolck <a.sch...@gmx.net> wrote in message news:<yfs7k9v...@black132.ex.ac.uk>...

> I think your life might be much happier if you just went to
> http://www.drscheme.org/, dowloaded Dr Scheme and used *that* for
> webdevelopment.

I don't know what it is, but while I learn a lot from those lispish
languages, I never use them in practice. So much community
fragmentation, and Dr. Scheme seems to want you to differ from the
standard. I find it more effective to work around Python's functional
inexactness.

I can't really live without lambda since it's a keyword. But
map/filter/reduce can be done without since I can just express them as
libs. In fact, "reduce" is one of those terrible lisp names (for
fold-left) that explain nothing. Lambda could also stand renaming;
Pythonistas probably think it's an arrogant name. (Or exotic? I
can't tell.)

The main advantage of functional constructs is that they're a readable
way to get things done in less lines. Less lines is more important
because Python is a whitespace language, and for that you want your
functions to be concise. Otherwise you can start to lose your way.
As far as readability, I think it's more readable than all those for-
and while-loops. Not having to name simple functions is more
readable. The only thing is that people used to C programming find it
disorienting to deal with lists as a central thing rather than some
annoyance to package up a bunch of elements.

In my code, I'm almost always handling lists of things. It's like, if
what I'm doing is useful for one thing, it's probably useful for a
lot.

Tj

Steve Holden

unread,
Apr 16, 2003, 9:17:49 AM4/16/03
to
"Dave Benjamin" <ra...@lackingtalent.com> wrote in message
news:slrnb9pt1o...@lackingtalent.com...

I *still* say that Java is object-oriented COBOL. People tend to take
offence when I say it, but that example makes the point well. There's so
much crud in the typical Java application, most of which could probably be
macro-generated from a much more concise "super-source".

regards
--
Steve Holden http://www.holdenweb.com/
How lucky am I? http://www.google.com/search?q=Steve+Holden&btnI=1
Python Web Programming http://pydish.holdenweb.com/pwp/


Steve Holden

unread,
Apr 16, 2003, 9:19:18 AM4/16/03
to
"Dave Benjamin" <ra...@lackingtalent.com> wrote in message
news:slrnb9pt59...@lackingtalent.com...

... builtin

Terry Reedy

unread,
Apr 16, 2003, 1:48:14 PM4/16/03
to

"Tj" <tj_sc...@yahoo.com> wrote in message

> fold-left) that explain nothing. Lambda could also stand renaming;
> Pythonistas probably think it's an arrogant name. (Or exotic? I
> can't tell.)

For people without knowledge of Lisp, and maybe lacking complete
knowledge of the Greek 'alpha-beta' and math people's habit of using
such letters, try 'obscure'. To me (who had such knowledge) it is
just a bit jarring. All other Python keywords are English words (or
abbreviations thereof) with Python meanings similar to their everyday
meanings. 'Lambda' sticks out like a sore thumb. 'Func' would have
been better.

Terry J. Reedy


Tj

unread,
Apr 16, 2003, 2:00:00 PM4/16/03
to
Can anyone point me to a discussion of Python's scoping system vs.
Scheme-like lexical scoping? I'd like to know if people find Python's
scoping more intuitive or what. I know Guido once mentioned it was
because he thought it might encourage a lot of nesting, but now
"nested scopes" have made its way into the language.

laotseu

unread,
Apr 16, 2003, 6:58:44 PM4/16/03
to
Paul Foley wrote:

> On Tue, 15 Apr 2003 23:49:37 +0000, laotseu wrote:
>
>
>>Even for OO programmers, functionnal features in Python are IMHO a
>>great plus, and BTW functionnal and OO paradigm does not have to
>>conflict (that would be functionnal vs imperative and object vs
>>procedural). CLOS is one of the great system objects out here, and
>>it's been implemented on top of a functionnal language,
>
>
> Oh yes? Which functional language would that be?
>

CLOS means Common Lisp Object System.

Laotseu

Alexander Schmolck

unread,
Apr 16, 2003, 5:24:39 PM4/16/03
to
laotseu <bde...@removethis.free.fr> writes:

> Paul Foley wrote:
> > On Tue, 15 Apr 2003 23:49:37 +0000, laotseu wrote:
> >
> >>Even for OO programmers, functionnal features in Python are IMHO a
> >>great plus, and BTW functionnal and OO paradigm does not have to
> >>conflict (that would be functionnal vs imperative and object vs
> >>procedural). CLOS is one of the great system objects out here, and
> >>it's been implemented on top of a functionnal language,

^^^^^^^^^^^^^^^^^^^^

You go and say that in comp.lang.lisp :)

'as

Michael Hudson

unread,
Apr 16, 2003, 5:30:17 PM4/16/03
to
laotseu <bde...@removethis.free.fr> writes:

Paul knows that :-) I'd wager the point he was making is that Common
Lisp isn't "really" a functional programming language...

Ocaml would be a better example, I'd have thought.

Cheers,
M.

--
In general, I'd recommend injecting LSD directly into your temples,
Syd-Barret-style, before mucking with Motif's resource framework.
The former has far lower odds of leading directly to terminal
insanity. -- Dan Martinez

Bjorn Pettersen

unread,
Apr 16, 2003, 5:15:51 PM4/16/03
to
> From: laotseu [mailto:bde...@removethis.free.fr]
>
> Paul Foley wrote:
> > On Tue, 15 Apr 2003 23:49:37 +0000, laotseu wrote:
> >
> >
> >>Even for OO programmers, functionnal features in Python are IMHO a
> >>great plus, and BTW functionnal and OO paradigm does not have to
> >>conflict (that would be functionnal vs imperative and object vs
> >>procedural). CLOS is one of the great system objects out here, and
> >>it's been implemented on top of a functionnal language,
> >
> > Oh yes? Which functional language would that be?
> >
>
> CLOS means Common Lisp Object System.

"Houston: we have a claim that CL is a functional language, please
proceed with crosspost to c.l.sml, c.l.haskell, ..." <grin>.

-- bjorn

Greg Ewing (using news.cis.dfn.de)

unread,
Apr 16, 2003, 9:39:04 PM4/16/03
to
Tj wrote:
> Lambda could also stand renaming;
> Pythonistas probably think it's an arrogant name. (Or exotic? I
> can't tell.)

Actually, we think it's kind of cute.

Mary had a little lambda,
Its syntax white as snow,
And every program Mary wrote,
She wrote in Lisp, you know.

Although nowadays she's probably using Python instead.

Jean-Paul Roy

unread,
Apr 17, 2003, 3:55:46 AM4/17/03
to
Hi, snakes,

I'm teaching Scheme in our Univ. to 2nd year students. The cursus is now:
- Java in 1st year
- Scheme in 2nd year
- Java, C++... in 3rd year and above (+ some Scheme to build an
interpreter).

Now, is it a good move to swap from Java to Python in 1st year ? Some of
us find Java a bit heavy for algorithmics. The probable discussion will
be about:

- Python is bad : no static types (it's ok for me)
- Pyhton is bad : recursion limit (I am astonished at that one)
- Python is bad : tail recursion is not iterative (also astonished at
that, I can understand with an interpreter, but compiler ?)
- Python is bad : we are obliged to use message passing paradigm to add
an element to a list (it's ok for me but some of us get angry with
objects for beginners)
- Python is bad : where are classical arrays ? Does:
from array import array
actually imports contiguous arrays ? How can they stay contiguous if
they support adding an element ? Is the access only O(1) amortized ?
Comes from : wanting to play with big arrays of bitmap images.

Aside from that points, a personal question as a Schemer who reads the
Python primer:
- how do you ask if a list is empty ? Is the following ok ?
if L == [] :
- how do you ask if the list has only one element, with time 0(1) ? The
Scheme/Lisp analog is (null? (cdr L))
- more generally, is the length of a list a builtin ? Is the L[k] access
time O(1) with a list ? Probably not. And with a tuple ?

Sorry for so many questions and your time.

But thanks a lot, I guess that Python is a good guy :-)

-jpr

Erik Max Francis

unread,
Apr 17, 2003, 4:06:31 AM4/17/03
to
Jean-Paul Roy wrote:

> - Python is bad : tail recursion is not iterative (also astonished at
> that, I can understand with an interpreter, but compiler ?)

I think the reason for this is that there simply hasn't been enough
pressure to do so. I doubt anyone thinks it would be _bad_, it's just
not enough people have insisted it is worth doing.

> Aside from that points, a personal question as a Schemer who reads the
> Python primer:
> - how do you ask if a list is empty ? Is the following ok ?
> if L == [] :

Even simpler:

if L: ...

> - how do you ask if the list has only one element, with time 0(1) ?
> The
> Scheme/Lisp analog is (null? (cdr L))

I suspect the length of a Python list is cached in the list object, but
don't know that for a fact (a simple test would verify it easily
enough). I would think that

if len(L) == 1: ...

would be fine.

> - more generally, is the length of a list a builtin ?

I think so but have not checked.

> Is the L[k]
access
> time O(1) with a list ? Probably not. And with a tuple ?

Python lists and tuples are both implemented as computer science
"vectors," so indexing access time is indeed O(1).

--
Erik Max Francis / m...@alcyone.com / http://www.alcyone.com/max/
__ San Jose, CA, USA / 37 20 N 121 53 W / &tSftDotIotE
/ \ Can I walk with you / 'Till the day that my heart stops beating
\__/ India Arie
Polly Wanna Cracka? / http://www.pollywannacracka.com/
The Internet resource for interracial relationships.

Andrew Bennetts

unread,
Apr 17, 2003, 4:13:44 AM4/17/03
to
On Thu, Apr 17, 2003 at 09:55:46AM +0200, Jean-Paul Roy wrote:
[..]

> Aside from that points, a personal question as a Schemer who reads the
> Python primer:
> - how do you ask if a list is empty ? Is the following ok ?
> if L == [] :

Usually you'd just do
if not L:

You could also do
if len(L) == 0:

> - how do you ask if the list has only one element, with time 0(1) ? The
> Scheme/Lisp analog is (null? (cdr L))

len(L) == 1

> - more generally, is the length of a list a builtin ? Is the L[k] access
> time O(1) with a list ? Probably not. And with a tuple ?

Python lists are like C++ and Java vectors, they're stored contiguously in
memory, so indexing is O(1). Same with tuples.

-Andrew.


Simon Brunning

unread,
Apr 17, 2003, 4:29:24 AM4/17/03
to
> From: Erik Max Francis [SMTP:m...@alcyone.com]

> Jean-Paul Roy wrote:
>
> > - how do you ask if a list is empty ? Is the following ok ?
> > if L == [] :
>
> Even simpler:
>
> if L: ...

Surely:

if not L:

;-)

Cheers,
Simon Brunning
TriSystems Ltd.
sbru...@trisystems.co.uk
--LongSig


-----------------------------------------------------------------------
The information in this email is confidential and may be legally privileged.
It is intended solely for the addressee. Access to this email by anyone else
is unauthorised. If you are not the intended recipient, any disclosure,
copying, distribution, or any action taken or omitted to be taken in
reliance on it, is prohibited and may be unlawful. TriSystems Ltd. cannot
accept liability for statements made which are clearly the senders own.

Alex Martelli

unread,
Apr 17, 2003, 5:49:35 AM4/17/03
to
<posted & mailed>

Jean-Paul Roy wrote:

> Hi, snakes,
>
> I'm teaching Scheme in our Univ. to 2nd year students. The cursus is now:
> - Java in 1st year
> - Scheme in 2nd year
> - Java, C++... in 3rd year and above (+ some Scheme to build an
> interpreter).

OK. I might suggest adding some more-rigorously-functional language
to just Scheme (O'CAML has the advantage, for you, of being French and
having excellent French books about it...), but overall the picture
seems not bad.


> Now, is it a good move to swap from Java to Python in 1st year ? Some of

Yes, I think it WOULD be a good move, in general -- *however*, in terms
of the overall plan of study, I would then be a bit concerned if the
students were ONLY exposed to dynamically typed languages (Python first
year, Scheme second year) and never to statically typed ones until "the
third year and above". Adding (perhaps some subset of) O'CAML would be
very good for this concern, too, because it would show students a *GOOD*
static typing scheme [not *EXCELLENT* -- that's reserved for Haskell!-) --
but, seriously, pretty good indeed, and heads and shoulders above the
kludgey typesystems of both Java and C++].

> us find Java a bit heavy for algorithmics. The probable discussion will
> be about:

Yes, Java IS indeed quite heavy for algorithmics -- Python "gets out
of your way", when you're teaching algorithms and data structures, in
a way Java never will.


> - Python is bad : no static types (it's ok for me)

It's perfectly OK *in general* that Python's typing is dynamic, just
as it's perfectly OK for Scheme, *BUT* you should consider the need
to expose students to SOME kind of static typing, preferably within
the first 2 years. Doing it with a good, mathematically consistent
model such as ML's (any version -- O'CAML is a bit complicated by a
lot of twists and additions, but still the underlying model is quite
sound) or Haskell's is didactically VERY preferable to doing it with
the kludgey approaches of Java and the like, of course.

> - Pyhton is bad : recursion limit (I am astonished at that one)

Yeah, one spot where implementation and pragmatical issues have
taken priority over didactical and theoretical ones. I suspect you
could use _Stackless_ Python and free yourself from the recursion
limit, if you could accept the limitation of running on Intel and
Intel-compatible CPU's only, but I don't know it for a fact.

> - Python is bad : tail recursion is not iterative (also astonished at
> that, I can understand with an interpreter, but compiler ?)

Implementation detail -- nobody's ever cared deeply about it. I'm
sure a patch to _optionally_ deal with that would be well-received
(*optionally* because you want to be able to have the full stack
trace, normally, when a chain of calls including tail calls ends
up propagating an exception -- so, optimizing tail recursion would
need an explicit renunciation to see a complete stack trace in
such cases, and might be triggered by -O or some other dedicated
switch on the Python commandline, for example).

> - Python is bad : we are obliged to use message passing paradigm to add
> an element to a list (it's ok for me but some of us get angry with
> objects for beginners)

I'm sorry, but I just don't see this one. E.g.:

onelist = [1, 2, 3]
anotherone = onelist + [4]

yes, the "+" operator, "under the covers", *IS* calling the
__add__ method of object onelist, but, why is that a problem?
If you want to modify the onelist in place,

onelist += [4]

does it (internally by calling __iadd__ on onelist, but,
again, why would that be a problem???).

Sure, calling onelist.append is more idiomatic, but if you don't
want to teach that right at the start, where's the problem with
onelist+=[...] or just onelist+[item] ...? Perhaps I'm missign
something obvious -- I _would_ like you to clarify, thanks!

> - Python is bad : where are classical arrays ? Does:
> from array import array
> actually imports contiguous arrays ? How can they stay contiguous if
> they support adding an element ? Is the access only O(1) amortized ?
> Comes from : wanting to play with big arrays of bitmap images.

Python's so-called lists are actually "contiguous arrays" (of any
arbitrary objects, natch). They stay contiguous when you add
elements by having a carefully tailored overallocation strategy
(and, in the case of .insert, ALSO shifting in memory all the
items that follow the insertion point -- and similarly for slice
assignments), and reallocating when necessary. So, yes, appending
is amortized O(1) [inserting or deleting at an arbitrary point is O(N),
and _accessing_ anylist[index] is "hard" O(1), not just amortized).

The type array.array is used for *homogeneous* arrays -- contiguous
arrays (just like builtin lists) where all items of one array are of
the same primitive type (numbers or characters). As for the type's
overallocation strategy, that may vary by release [as it did for
lists - they didn't have .append as O(1) amortized a few releases
ago, since they did only bounded overallocation back then] -- if
such implementation details are crucial to your didactical purposes,
they can be studied in the Python sources (and I'll be glad to help
you with that, if needed). But I doubt you want to introduce the
array.array type to beginners -- it's really a memory optimization
for some common special cases, that's all!


> Aside from that points, a personal question as a Schemer who reads the
> Python primer:
> - how do you ask if a list is empty ? Is the following ok ?
> if L == [] :

It works, though it's not idiomatic. Other alternatives:

if len(L) == 0: print 'L is empty'

if not len(L): print 'L is empty'

if not L: print 'L is empty'

the latter is idiomatic: any container is false IFF it's empty, so,
the boolean 'not' operator does all you need.

> - how do you ask if the list has only one element, with time 0(1) ? The
> Scheme/Lisp analog is (null? (cdr L))

if len(L) == 1: print 'L has exactly 1 element'

is the only construct that would come to most pythonistas' minds (and
yes, it's O(1)). Other approaches you'd probably only see in some
kinds of "obfuscated Python" -- somebody trying hard to be clever --
and they might e.g. exploit slicing:

if not L[1:2]: print 'L has 0 or 1 elements'

Slicing can be handy because it's tolerant of indices out of bounds
(differently from indexing, which raises exceptions when you index
out of bounds!). But it makes no sense to "get too cute about it";
when you're interested in the length of L, len(L) is the way to go.

> - more generally, is the length of a list a builtin ? Is the L[k] access
> time O(1) with a list ? Probably not. And with a tuple ?

len is a built-in function. len(L) is O(1) for any list L, and len(T)
is O(1) for any tuple T. Indexing, L[k] and T[k], are also both O(1).


> Sorry for so many questions and your time.

The root of half of your problems is the strange use of the term
"list" in Python -- QUITE different from most uses of the same term
in all of CS and programming literature -- so it's WE, the Python
community, who should be apologizing to you for wasting some of
your time with it. It's too late of course to eradicate the Python
use of the term "list" (the word 'list' itself is the name of the
built-in type, among other considerations) but at least the tutorial
should definitely mention it up front that a 'list' is really a
(potentially heterogeneous) vector (able to grow and shrink, but
contiguous in memory at all times -- this is somewhat more than an
implementation detail, as it governs the O()-behavior of many of
the aspects of Python lists...).


> But thanks a lot, I guess that Python is a good guy :-)

You're welcome!!! And, yes, you'll do your students a world of
good if you can teach them Python as their first language -- it
can give them a very useful tool that will help them in a lot of
ways throughout their careers, both conceptually and practically
(e.g., when they later get around to studying sockets, or Java
libraries, etc, etc, being able to play interactively with them
with Python [or Jython -- same language, but implemented on top
of a JVM] will perhaps ease their learning enormously).


Alex

laotseu

unread,
Apr 17, 2003, 9:56:35 AM4/17/03
to
Michael Hudson wrote:
> laotseu <bde...@removethis.free.fr> writes:
>
>
>>Paul Foley wrote:
>>
>>>On Tue, 15 Apr 2003 23:49:37 +0000, laotseu wrote:
>>>
>>>
>>>>Even for OO programmers, functionnal features in Python are IMHO a
>>>>great plus, and BTW functionnal and OO paradigm does not have to
>>>>conflict (that would be functionnal vs imperative and object vs
>>>>procedural). CLOS is one of the great system objects out here, and
>>>>it's been implemented on top of a functionnal language,
>>>
>>>Oh yes? Which functional language would that be?
>>>
>>
>>CLOS means Common Lisp Object System.
>
>
> Paul knows that :-)

He does. Some may not...

> I'd wager the point he was making is that Common
> Lisp isn't "really" a functional programming language...

Ho yes ? Why ? Because it doesn't enforce a strict functionnal
programming style ? In this case, Python is not "really" an object
oriented language !-)

AFAIK, Common Lisp support all the features that make the definition of
a functionnal language, so it *is* a functionnal language.

> Ocaml would be a better example, I'd have thought.

Let's say another example...

Laotseu

laotseu

unread,
Apr 17, 2003, 10:02:17 AM4/17/03
to
Alexander Schmolck wrote:
> laotseu <bde...@removethis.free.fr> writes:

(snip : someone here posted about his fear that the few functionnal
features in Python could be deprecated one day)

Ok, cross-posted and fu2 positionned.

Lispers friends, let's have you're opinion on that point : is Common
Lisp a functionnal language ?

<Paul>
Your turn now : *you* go and say in comp.lang.lisp that Common Lisp *is
not* a functionnal language !-)
</Paul>

Laotseu

Henrik Motakef

unread,
Apr 17, 2003, 8:45:20 AM4/17/03
to
laotseu <bde...@removethis.free.fr> writes:

> Lispers friends, let's have you're opinion on that point : is Common
> Lisp a functionnal language ?

Common Lisp is whatever you want it to be: You can write
functional-style programs in it if you want, but is certainly not a
"pure" functional language. It supports several other paradigms
equally well, and even more important, it will let you integrate
yet-unkown paradigms when you think that they are useful.

There are really ideas to remove the functional stuff from Python? I
wonder why people frequently think that making things impossible will
improve programming languages.

just-because-it's-flexible-doesn't-mean-it's-perl-ly y'rs
Henrik

Daniel Barlow

unread,
Apr 17, 2003, 8:39:58 AM4/17/03
to
laotseu <bde...@removethis.free.fr> writes:

> Ok, cross-posted and fu2 positionned.

Followup reset. Lisp users already know the answer to this one; if
Python users also want to, it should go to comp.lang.python.

> Lispers friends, let's have you're opinion on that point : is Common
> Lisp a functionnal language ?

Common Lisp is a multiparadigm language. If the question is "Does
Common Lisp support a functional style of programming", the answer is
"yes". If the question is "Does Common Lisp _require_ a functional
style of programming", no, absolutely not.

And to say that CLOS is built "on top of" CL, though historically
accurate, is no longer really correct. CLOS is _part_ of ANSI Common
Lisp.


-dan

--

http://www.cliki.net/ - Link farm for free CL-on-Unix resources

Steve Holden

unread,
Apr 17, 2003, 10:49:33 AM4/17/03
to
"Henrik Motakef" <henrik....@web.de> wrote ...


I can see that, but wouldn't you agree that removing redundant features also
removes cruft from the source, and eases the maintenance burden, in turn
reducing the likelihood of implementation bugs? While Guido is known to
regret the inclusion of lambda in Python, I don't think he would want to
take it out on purely ideological grounds. Indeed, the suggestion was not so
much that it would be taken out of the existing language, rather that it
would not be implemented in some "futurePython", normally called Python 3 or
Python 3000.

It would be nice to have One True Python, but that's about as likely as One
True Lisp. The Python world is pragmatic enough to be able to live with "one
*most obvious* way to do it", but if there are two similar features in the
language they have to be maintained in lockstep as the language develops.

just-becuase-it's-there-doesn't-mean-it's-helpful-ly y'rs - steve

Matthew Danish

unread,
Apr 17, 2003, 11:43:16 AM4/17/03
to
On Thu, Apr 17, 2003 at 02:49:33PM +0000, Steve Holden wrote:
> I can see that, but wouldn't you agree that removing redundant features also
> removes cruft from the source, and eases the maintenance burden, in turn
> reducing the likelihood of implementation bugs? While Guido is known to
> regret the inclusion of lambda in Python, I don't think he would want to
> take it out on purely ideological grounds. Indeed, the suggestion was not so
> much that it would be taken out of the existing language, rather that it
> would not be implemented in some "futurePython", normally called Python 3 or
> Python 3000.
>
> It would be nice to have One True Python, but that's about as likely as One
> True Lisp. The Python world is pragmatic enough to be able to live with "one
> *most obvious* way to do it", but if there are two similar features in the
> language they have to be maintained in lockstep as the language develops.

What's wrong with Python and CL!!!? They have all these extraneous
features which can accomplish the same thing!!! All you need is the
<insert model of computability here>!!! Anything else is liable to
develop cruft and cause bugs in the single implementation of our ONE
PURE LANGUAGE!!! I can't believe that people might want to model
problems any other way!!!

--
; Matthew Danish <mda...@andrew.cmu.edu>
; OpenPGP public key: C24B6010 on keyring.debian.org
; Signed or encrypted mail welcome.
; "There is no dark side of the moon really; matter of fact, it's all dark."

Steve Holden

unread,
Apr 17, 2003, 12:02:50 PM4/17/03
to
"Matthew Danish" <mda...@andrew.cmu.edu> wrote in message
news:2003041711...@lain.cheme.cmu.edu...

Absolutely. Your pure approach causes me to shed tears of joy. If only
everyone else could see the Truth. In fact, were there endless time, all we
would need would be One True Turing Machine and an Infinite Number of
Monkeys.

Did I mention that you only need nine commands to write any program? ;-)

and-we-could-dispense-with-the-turing-machine-at-a-pinch-ly y'rs - steve

Jacek Generowicz

unread,
Apr 17, 2003, 11:16:05 AM4/17/03
to
"Steve Holden" <sho...@holdenweb.com> writes:

> While Guido is known to regret the inclusion of lambda in Python

But he regrets the inclusion of a crippled lambda, rather than the
inclusion of support for anonymous functions (IIRC).

Marco Antoniotti

unread,
Apr 17, 2003, 12:18:33 PM4/17/03
to

Steve Holden wrote:

> "Henrik Motakef" wrote ...


>
> >laotseu writes:
> >
> >
> >>Lispers friends, let's have you're opinion on that point : is Common
> >>Lisp a functionnal language ?
> >
> >Common Lisp is whatever you want it to be: You can write
> >functional-style programs in it if you want, but is certainly not a
> >"pure" functional language. It supports several other paradigms
> >equally well, and even more important, it will let you integrate
> >yet-unkown paradigms when you think that they are useful.
> >
> >There are really ideas to remove the functional stuff from Python? I
> >wonder why people frequently think that making things impossible will
> >improve programming languages.
> >
> >just-because-it's-flexible-doesn't-mean-it's-perl-ly y'rs
>
>
>
> I can see that, but wouldn't you agree that removing redundant
> features also
> removes cruft from the source, and eases the maintenance burden, in turn
> reducing the likelihood of implementation bugs? While Guido is known to
> regret the inclusion of lambda in Python, I don't think he would want to
> take it out on purely ideological grounds. Indeed, the suggestion was
> not so
> much that it would be taken out of the existing language, rather that it
> would not be implemented in some "futurePython", normally called
> Python 3 or
> Python 3000.
>
> It would be nice to have One True Python,


Hav I missed something? I thought that that is exactly what you have now :)

Cheers

--
Marco Antoniotti


Duane Rettig

unread,
Apr 17, 2003, 12:22:10 PM4/17/03
to
laotseu <bde...@removethis.free.fr> writes:

> Ok, cross-posted and fu2 positionned.

[re-cross-posted]

> Lispers friends, let's have you're opinion on that point : is Common
> Lisp a functionnal language ?

Other CL-ers have already correctly answered you. And the answers
assume an understanding of the dimensions of this question. There are
in fact at least a couple of dimensions to your question - it can be taken
as either a question of capability or as a question of focus. The "is",
on the other hand, implies a question of definition (e.g. what _is_ it?)


Definition: CL is a powerful, general-purpose programming language.

Capability: Can CL users program functionally in CL? Absolutely.
Can CL users write non-functional programs? Absolutely.

Focus: Does CL focus on or force a functional programming style? No.
Might some CL users force a functional programming style on
their programs? Yes, of course. Are such users still programming
in CL? Yes. Must other programmers modifying the original code
stick to the same functional model of programming? Not by CL
standards; any such agreement to stay within FP boundaries would
be external to CL (and would probably involve some kind of monetary
transaction :-)

--
Duane Rettig du...@franz.com Franz Inc. http://www.franz.com/
555 12th St., Suite 1450 http://www.555citycenter.com/
Oakland, Ca. 94607 Phone: (510) 452-2000; Fax: (510) 452-0182

laotseu

unread,
Apr 17, 2003, 5:43:04 PM4/17/03
to
Florian Weimer wrote:

> laotseu <bde...@removethis.free.fr> writes:
>
>
>>Lispers friends, let's have you're opinion on that point : is Common
>>Lisp a functionnal language ?
>
>
> It depends on your definition of "functional programming language".
> In the more general sense, any language with higher-order functions
> and functions as a first-class type is a functional programming
> language.

Ok, the question coming from a 'Functional Python' point of view, the
'more general sense' is enough for me.

And for you all dear Lispers, thanks for your opinions on that point. I
know enough of lisp to know that it supports many paradigms and doesn't
enforce a pure, religious FP style.

I notice that nobody here claimed that you could not do functional
programming in Common Lisp.

> In the strictest sense, the language has to be purely
> applicative (or free of side effects). Common Lisp satisfies the
> first definition, but not the second.

Do you mean that it is *absolutely not possible* to write a whole
program in CL whithout any side effect ? Or that many features in the
language, that you can choose to use or not, are not side effect free ?

I might say that, in the first case, this does not prevent CL from being
(also) a functional language in the 'strictest sens'.

Laotseu

Ian Bicking

unread,
Apr 17, 2003, 3:54:36 PM4/17/03
to
On Thu, 2003-04-17 at 02:55, Jean-Paul Roy wrote:
> - Python is bad : tail recursion is not iterative (also astonished at
> that, I can understand with an interpreter, but compiler ?)

Some would argue that tail recursion is not good for teaching and
understanding, because you loose the call stack. In the likely event of
a traceback, it can be very confusing if you don't fully indicate how
you got there, or if points upon the path were lost in an optimization.

Ian

Paul Wallich

unread,
Apr 17, 2003, 4:06:42 PM4/17/03
to
In article <3E9F1FE8...@removethis.free.fr>,
laotseu <bde...@removethis.free.fr> wrote:

> Florian Weimer wrote:

> > In the strictest sense, the language has to be purely
> > applicative (or free of side effects). Common Lisp satisfies the
> > first definition, but not the second.
>
> Do you mean that it is *absolutely not possible* to write a whole
> program in CL whithout any side effect ? Or that many features in the
> language, that you can choose to use or not, are not side effect free ?

It's the second. In a strictest-sense functional language, it is
impossible to write a whole program that *does* have side effects.
This leads to the usual amusements such as passing the universe to a
function that then returns a similar-but-not-identical universe with one
property differing...

paul

Bengt Richter

unread,
Apr 17, 2003, 5:53:25 PM4/17/03