Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

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
to
On Thu, 17 Apr 2003 09:55:46 +0200, Jean-Paul Roy <r...@unice.fr> wrote:
[...]

>- Pyhton is bad : recursion limit (I am astonished at that one)
I think it's just there to warn you, so you don't have to wait so long
or get potentially confusing OOM symptoms before you realize you've got
a lot of recursion. You can adjust the limit.

>>> import sys
>>> help(sys.setrecursionlimit)
Help on built-in function setrecursionlimit:

setrecursionlimit(...)
setrecursionlimit(n)

Set the maximum depth of the Python interpreter stack to n. This
limit prevents infinite recursion from causing an overflow of the C
stack and crashing Python. The highest possible limit is platform-
dependent.

>>> help(sys.getrecursionlimit)
Help on built-in function getrecursionlimit:

getrecursionlimit(...)
getrecursionlimit()

Return the current value of the recursion limit, the maximum depth
of the Python interpreter stack. This limit prevents infinite
recursion from causing an overflow of the C stack and crashing Python.

>>> sys.getrecursionlimit()
1000

The latter is the default on the 2.2.2 windows version.

Regards,
Bengt Richter

Steven Taschuk

unread,
Apr 17, 2003, 5:59:00 PM4/17/03
to
Quoth Jean-Paul Roy:

> I'm teaching Scheme in our Univ. to 2nd year students. The cursus is now:
[...]

> 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:
[...]

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

Although it's a bit annoying in principle, I've never found the
recursion limit to be a problem in practice. (But then, I don't
usually implement Ackermann's function.)

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

For teaching purposes, imho tail recursion is a Bad Thing.

Writing an iterative process using tail recursion has always
struck me as a clever but obfuscated technique. Write what you
mean: if you want an iterative process, write a loop; if you want
a recursive process, make recursive calls.

Conversely, it's easier to explain that a call always involves
stack growth, while a loop does not, instead of having to explain
that the compiler is under some circumstances able to do a call
without stack growth.

Talk about tail recursion when you start teaching the wee ones
about more advanced topics to which it is directly relevant, such
as compiler implementation, how loops might be implemented under
the hood, and so forth.

> - 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'd like to hear more about this objection. Is it that those who
object to objects (heh) feel they should be a more advanced topic?

[...]

--
Steven Taschuk stas...@telusplanet.net
"Study this book; read a word then ponder on it. If you interpret the meaning
loosely you will mistake the Way." -- Musashi, _A Book of Five Rings_

Bengt Richter

unread,
Apr 17, 2003, 7:45:41 PM4/17/03
to

Or if the stack trace is so deep the first part scrolls away and you
give up waiting for the last part ;-)

Perphaps a trace output that would transform the traceback of, e.g.,

>>> def recu(n):
... if n>0: recu(n-1)
... raise Exception, 'test'
...
>>> recu(5)
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 2, in recu
File "<stdin>", line 2, in recu
File "<stdin>", line 2, in recu
File "<stdin>", line 2, in recu
File "<stdin>", line 2, in recu
File "<stdin>", line 3, in recu
Exception: test

to

Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 2, in recu
[ ... above 1 line repeated 4 more times ...]
File "<stdin>", line 3, in recu
Exception: test

or the like, could be handy?
And IWT short repeating cycles could be handled too.

Regards,
Bengt Richter

Paul Prescod

unread,
Apr 17, 2003, 8:08:16 PM4/17/03
to
Henrik Motakef wrote:
> ...

>
> 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

There is nobody suggesting to make anything impossible. The question is
whether to have two or three syntactic variations for more or less the
same thing. Lambda is syntactic sugar for def. You literally can't
accomplish anything (useful) with it that you couldn't with def. map is
very near to syntactic sugar for list comprehensions (or vice versa).
apply is syntactic sugar for "*", "**", and so forth. If Python adds new
stuff (like "*", and list comprehensions) and never removes anything
then there will come a day when it is full of redundant features. I
don't really feel strongly enough to argue about lambda et. al. but I
want to make the point that there are two sides to this argument.

Paul Prescod

Courageous

unread,
Apr 17, 2003, 11:11:25 PM4/17/03
to

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

I was toying around in my own python parser about a year ago,
attempting to implement anonymous functions there. It was a
struggle, and in the end, I felt basically *forced* down the
same path the Python team went, until I included a set of tokens
for explicit scope (hey! this is just a toy environment, don't
look scandalized!).

Anyway, I guess what I'm saying is that I suspect that Guido
didn't have any good alternatives. If someone has some, that
fit well with our beloved block delimited language, SHOW ME
DA MONEY! :-)

C//

synthespian

unread,
Apr 17, 2003, 11:57:53 PM4/17/03
to
Alexander Schmolck wrote:
> 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) :).
>
Hahaha...

The OP might also be interested, then, in the Clean language. This is
haskell-like, but with modifications in the type system (combines static
/and/ dynamic typing and has destructive updates [1]), to improve
performance (it compiles). Some issues remain in what regards exception
handling, it seems (for pretty much the same reasons that they remain in
haskell, probably. I'm no expert on FP, so I might be wrong).
It was developed by serious people in the FP research community, but
it is intended to be used in the "real" world. They have an IDE writen
in Clean, I/O libraries, and even a graphics Game library! So, they mean
what they say.
Licensed under the LGPL. IDE for win32 only (for now).


home page:
http://www.cs.kun.nl/~clean/

some libraries:
http://www.cs.kun.nl/~clean/About_Clean/page_modified/page_modified.html

foldoc (kind of useless, too outdated)
http://wombat.doc.ic.ac.uk/foldoc/foldoc.cgi?Clean

Regs

Henry

[1] "Clean is the only functional language in the world which offers
/uniqueness typing/. This type system makes it possible in a pure
functional language to incorporate destructive updates of arbitrary data
structures (including arrays) and to make direct interfaces to the
outside imperative world. The type system makes it possible to develop
efficient applications."


Jean-Paul Roy

unread,
Apr 18, 2003, 4:14:57 AM4/18/03
to
In article <mailman.1050609281...@python.org>,
Ian Bicking <ia...@colorstudy.com> wrote:

That's a point, but in that case it would suffice to enveloppe the call
by an identity function...
Let me cite the Normalization Report on Scheme:

"Programming languages should be designed not by piling feature on top
of feature, but by removing the weaknesses and restrictions that make
additional features appear necessary."

And so the wile or for... loops could be defined in Python as in Scheme
with the tail recursion optimzation.
In the same spirit as Paul Graham's invited talk at PyCon'2003.

My teaching experience is that students knowing loops through the while
construct actually *understand* the concept of iteration when they see
that it is modelized by a tail recursive function which transforms a
"vector of loop variables" (a state vector). Then, it is only a GOTO
which passes arguments. I'm really happy to teach that way.

-jpr

Donnal Walter

unread,
Apr 18, 2003, 6:58:25 AM4/18/03
to
Steven Taschuk wrote:
> Quoth Jean-Paul Roy:

>>- Python is bad : tail recursion is not iterative (also astonished at
>>that, I can understand with an interpreter, but compiler ?)
>
>
> For teaching purposes, imho tail recursion is a Bad Thing.
>
> Writing an iterative process using tail recursion has always
> struck me as a clever but obfuscated technique. Write what you
> mean: if you want an iterative process, write a loop; if you want
> a recursive process, make recursive calls.

What is the difference between "recursive calls" and "tail recursion"?
Sometimes I have written methods that call the same method on a parent
or child object, with the depth of recursion being limited by a method
of the same name NOT calling itself. In the past I have thought of this
as tail recursion. Is this incorrect?

Thanks,

Donnal Walter
Arkansas Children's Hospital

Alex Martelli

unread,
Apr 18, 2003, 9:53:30 AM4/18/03
to
Donnal Walter wrote:

A function-call is "tail" if it's the last thing the caller does,
i.e., basically, if the caller executes "return somefunction(args)"
or a semantically equivalent sequence.

A function-call is "recursive" if it's a call of the function to
itself (there's also "mutual recursion", where two functions call
each other).

A function-call is "tail recursive" if it's tail and recursive.
Such calls can be optimized by avoiding the allocation of a new
stack frame -- the same frame object that's already on the
stack to handle this specific call can be re-used (if you're
willing to lose traceback information -- Python currently does
not allow that).

Your example is not recursive: the fact that the various functions
being called have the same name is accidental, as they're different
functions anyway.


Alex

Bjorn Pettersen

unread,
Apr 18, 2003, 10:52:31 AM4/18/03
to
> From: Alex Martelli [mailto:al...@aleax.it]
>
> Donnal Walter wrote:
>
> >
> > What is the difference between "recursive calls" and "tail
> > recursion"? Sometimes I have written methods that call the
> > same method on a parent or child object, with the depth of
> > recursion being limited by a method of the same name NOT
> > calling itself. In the past I have thought of this
> > as tail recursion. Is this incorrect?
>
> A function-call is "tail" if it's the last thing the caller does,
> i.e., basically, if the caller executes "return somefunction(args)"
> or a semantically equivalent sequence.
>
[..recursive..]

>
> A function-call is "tail recursive" if it's tail and recursive.
> Such calls can be optimized by avoiding the allocation of a new
> stack frame -- the same frame object that's already on the
> stack to handle this specific call can be re-used (if you're
> willing to lose traceback information -- Python currently does
> not allow that).

[To digress, elaborate, use my MS for something :-)] It's acutally more
general. Any tail calls (recursive or not) can be optimized, trivially
(assuming the return address is stored in sp, etc.), instead of:

return f()

being compiled to (A) -- excuse my shorthand:

push sp, loc1
jump f
loc1: pop sp
reg1 = pop fn_result_stack # 1
push reg1, fn_result_stack # 2
jump sp

(1 and 2 would disappear with a peephole optimizer, assuming there is
one) tail call optimization creates (B):

jump f

with the last two lines of f looking like the last two lines of (A) the
semantics are the same.

[[Now what if you came up with an algorithm that converted any function
to a function with tail call? Your code for return would be really fast,
it would never "return" to a previous state, you wouldn't need a stack
anymore, implementing continuations would be trivial... They did it for
SML, and the various steps, algorithms, etc. are nicely described in:

Compiling with Continuations, Andrew Appel
Cambridge University Press 1992, ISBN 0-521-41695-7

which is one of the more interesting books I read in college both for
language and compiler theory (couldn't find an online-ref).]]

-- bjorn

laotseu

unread,
Apr 18, 2003, 1:50:55 PM4/18/03
to
Greg Ewing (using news.cis.dfn.de) wrote:
> 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.

lol !-)

Laotseu

Alex Martelli

unread,
Apr 18, 2003, 11:23:26 AM4/18/03
to
On Friday 18 April 2003 04:52 pm, Bjorn Pettersen wrote:
> > From: Alex Martelli [mailto:al...@aleax.it]
> >
> > Donnal Walter wrote:
> > > What is the difference between "recursive calls" and "tail
> > > recursion"? Sometimes I have written methods that call the
> > > same method on a parent or child object, with the depth of
> > > recursion being limited by a method of the same name NOT
> > > calling itself. In the past I have thought of this
> > > as tail recursion. Is this incorrect?
> >
> > A function-call is "tail" if it's the last thing the caller does,
> > i.e., basically, if the caller executes "return somefunction(args)"
> > or a semantically equivalent sequence.
>
> [..recursive..]
>
> > A function-call is "tail recursive" if it's tail and recursive.
> > Such calls can be optimized by avoiding the allocation of a new
> > stack frame -- the same frame object that's already on the
> > stack to handle this specific call can be re-used (if you're
> > willing to lose traceback information -- Python currently does
> > not allow that).
>
> [To digress, elaborate, use my MS for something :-)] It's acutally more
> general. Any tail calls (recursive or not) can be optimized, trivially

Nor did I say otherwise, please note -- IF you can reuse the stack
frame rather than having to generate a new one, which depends
of course on what's going on behind the scenes (can the function
being called use the same frame that was used to call the one
that's now tail-calling it -- depends on stackframe format).

> (assuming the return address is stored in sp, etc.), instead of:
>
> return f()
>
> being compiled to (A) -- excuse my shorthand:
>
> push sp, loc1
> jump f
> loc1: pop sp
> reg1 = pop fn_result_stack # 1
> push reg1, fn_result_stack # 2
> jump sp
>
> (1 and 2 would disappear with a peephole optimizer, assuming there is
> one) tail call optimization creates (B):
>
> jump f
>
> with the last two lines of f looking like the last two lines of (A) the
> semantics are the same.

You're not dealing with the question of the stack frame. How does
f know it's being called without arguments? Surely it will find the
needed indication in its stack frame. Who removes the stack frame
from the stack, caller or callee? What happens if different calls need
different-sized stack frames -- can the currently-topmost stack frame
be "resized", and if so, can it still be correctly removed afterwards
(e.g. in a caller-removes-frame approach, does the caller needs the
frame size information to do the removal, and if so, can it find it out
about a frame that may have been resized?).

Calling conventions are established to try and optimize many issues,
and the ability to optimize all tail calls is only one of many. The case
of a recursive tail call can sometimes be optimized (because all stack
frames received by function f are in some manner "uniform", but ones
received by other functions need not be) even in call conventions that
do not allow the general-case optimization.


> [[Now what if you came up with an algorithm that converted any function
> to a function with tail call? Your code for return would be really fast,
> it would never "return" to a previous state, you wouldn't need a stack
> anymore, implementing continuations would be trivial... They did it for

Of course, such a design would ensure uniformity of stack frames, having
chosen to focus on this optimization. BTW, for those who may have
dabbled with Forth and friends in the past, this has some similarities
to "threaded interpreters" (even though there need not be an interpreter
involved, and it looks more like direct-threading than indirect) -- in Forth
of course the stack frame problem is swept away by having the programmer
handle the stack explicitly.

BTW, you may claim you don't need a stack, but that's in some sense
word-trickery;-). If a calls b calls c calls d calls e, at this point the
"nonstack" frames for 4 ongoing calls need to be "somewhere" -- this
somewhere may e.g be a singly linked list, but that's just because such
a list is a rather good implementation of... ahem, a last-in-first-out queue,
yes, that's the ticket! [must not say the S-word...]

> SML, and the various steps, algorithms, etc. are nicely described in:
>
> Compiling with Continuations, Andrew Appel
> Cambridge University Press 1992, ISBN 0-521-41695-7
>
> which is one of the more interesting books I read in college both for
> language and compiler theory (couldn't find an online-ref).]]

Nolo contendere (I didn't study it deeply, barely browsed it, 10 years
ago or so -- my work was Fortran, C and some C++ then...:-).


Alex


Steve Holden

unread,
Apr 18, 2003, 12:30:57 PM4/18/03
to
"laotseu" <bde...@removethis.free.fr> wrote ...
This *finally* gives me the chance to ask: when a lambda grows up, does it
become a sheepda?

regards

Steven Taschuk

unread,
Apr 18, 2003, 12:44:38 PM4/18/03
to
Quoth Jean-Paul Roy:
[...]

> Let me cite the Normalization Report on Scheme:
>
> "Programming languages should be designed not by piling feature on top
> of feature, but by removing the weaknesses and restrictions that make
> additional features appear necessary."
>
> And so the wile or for... loops could be defined in Python as in Scheme
> with the tail recursion optimzation.

Let me paraphrase another source: "A programming language should
be as simple as possible, but no simpler." :)

[...]


> My teaching experience is that students knowing loops through the while
> construct actually *understand* the concept of iteration when they see
> that it is modelized by a tail recursive function which transforms a
> "vector of loop variables" (a state vector). Then, it is only a GOTO
> which passes arguments. I'm really happy to teach that way.

A nice point.

I wrote earlier that tail recursion is an obfuscated way of
writing iteration; I see now that I misunderstood what you're
teaching.

For teaching simply how to program, explicit loop syntax is better
than tail recursion imho, since it makes the programmer's intent
more explicit. For teaching theory, tail recursion is better,
since it makes the state vector more explicit (as an argument list
to the tail-recursive function, rather than implicit in the
environment).

--
Steven Taschuk stas...@telusplanet.net
Every public frenzy produces legislation purporting to address it.
(Kinsley's Law)

laotseu

unread,
Apr 18, 2003, 7:30:05 PM4/18/03
to
Bjorn Pettersen wrote:
>>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>.
>

Ok folks

Due to my deep ignorance, I came to believe that Lisp was the first
programming language based on the lambda calculus theory, the first
language to promote functions as first class objects, and the first
language to promote side-effect free programming style...

It seems that good old time is gone, and that even lispers themselves -
BTW, is Paul Graham still a Lisper ? - claims that Lisp is not a
functional language. So I just can agree with them and <troll>proudly
announce that Lisp is now a procedural, pascal-style language</troll>.
oops, sorry, that was not that either. Er, a general multi-paradigm
language.

So :

for x in range(100):
print "I shall not say that Lisp is a functional language anymore"


Laotseu

Henrik Motakef

unread,
Apr 18, 2003, 5:45:26 PM4/18/03
to
laotseu <bde...@removethis.free.fr> writes:

> Due to my deep ignorance, I came to believe that Lisp was the first
> programming language based on the lambda calculus theory, the first
> language to promote functions as first class objects, and the first
> language to promote side-effect free programming style...

On the other hand, Common Lisp claims to be the first language with a
standardized (as in "ANSI standard") object system :)

> BTW, is Paul Graham still a Lisper?

Yes he is. He is currently designing a new dialect of Lisp called
Arc, see http://www.paulgraham.com.

> for x in range(100):
> print "I shall not say that Lisp is a functional language anymore"

(prog ()
10 (print "I will not make my programming language do my homework.")
20 (go 10))

;-)

Regards
Henrik

A. Lloyd Flanagan

unread,
Apr 18, 2003, 5:41:14 PM4/18/03
to
"Terry Reedy" <tjr...@udel.edu> wrote in message news:<RoacnSAeGeS...@comcast.com>...
> "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

I'll second that. Maybe we could get func added as a synonym for lambda, at least.

Thaddeus L Olczyk

unread,
Apr 18, 2003, 6:05:31 PM4/18/03
to
On 17 Apr 2003 17:53:15 +0200, Nils Goesche <car...@cartan.de> wrote:

>Thaddeus L Olczyk <olc...@interaccess.com> writes:
>
>> On 17 Apr 2003 16:27:53 +0200, Nils Goesche <car...@cartan.de> wrote:
>>
>> >A definition that seems sensible to me would be something like: A
>> >language is functional if it somehow contains the lambda calculus.
>> >If you can take lambda calculus formulae and readily translate them
>> >into working code.
>
>> That makes nearly every modern language functional.
>
>Certainly not Java or C# ;-)
Yes. Both contain lambda calculus. As does any language
which supports objects.

In ( a sort hand wavy way ),
class Lambda
{
public:
retval exec(arglist){...}
}

Java ( can't say I know enough about C# ) may lack some syntactic
sugar to make it pretty, but it's there.

>But even if that's true -- then so be it.
>If it is true that modern languages tend to be functional, too, then
>you could call that progress. Why should we change the definition of
>``functional创 every year in order to keep the ratio of functional to
>non-functional languages constant over time?
>
While it's true that in math and CS, many definitions evolve over
time ( ones that come to mind right now are function/procedure
[which were distinct, now considered the same thing], fiber bundles,
sheaves, topological space ... ), that's all just bullshit thrown out
to distract people from *your stupidity*.

That's because the definition that you have suggested is not some
formal definition appearing in seminal "Introduction to Functional
Programming" type books or papers. It's *your* definition, and it
sucks. Because it's your definition and not a formal one, there is
no suggestion that I am changing the definition over time. As I said,
it's simply a distraction to hide the fact that your definition
*sucks*.

As for your definition, it sucks because it fails to make any
distinction. Almost everyone would agree that languages like
Haskell, ML, Clean, Scheme and ( sometimes ) Lisp are functional.
And your definition includes those. But your definition would say that
languages like C, Eiffel and Smalltalk ( not to mention C++, Java and
C# ) are functional, which almost no one would agree with.

>> >And you have to be a bit relaxed when using this requirement; for
>> >instance, writing an Y-combinator in ML is very hard because of the
>> >stupid type checker.
>>
>> No it is easy.
>>
>> In OCaml,
>> let rec fix f x=f (fix f) x;;
>
>That's cheating and you know it :-)
>
No. It's not.
It's a standard definition of Y in a combinatorial approach
to computing.

>> For a more traditional approach.
>> type 'a rf = RF of ( 'a rf -> 'a );;
>>
>> let y f x=
>> let g (RF h) z=
>> f( h (RF h) ) z in
>> (g (RF g)) x;;
>>
>> Of course the example above looks like:
>> let fact x= y ( fun q->
>> (fun n->
>> if n<2 then 1
>> else n* (q (n-1)))) x;;
>>
>> When I did it this way the first time it was a bit difficult getting
>> the type right.
>
>I know: Been there done that ;-\ Took me some time.
What can I say. Some people are slower than others.

>Certainly /much/
>longer than simply translating the lambda calculus formula to Lisp, so
>I refuse calling it easy, even if the ML code that finally works is
>short.
And know we see why some people are slower.
I never even thought of "translating" the code.
I did what every one is taught in every math class.
I rederived it in ML. In the process I found it easy.
The only sticking point was that I did not understand
user defined types well enough to write HOFs. Once
I understood that it was trivial.

>
>> But the reason was that I was new to the OCaml typing system. It
>> wasn't what the type should look like, it was just getting the
>> declaration right.
>
>If it's so easy, why did they even bother putting it into the ML FAQ?
Because there are lazy people who don't write code from first
principles, or bother to learn enough about user defined types
to write HOFs ( the true FP practitioner doesn't just use HOFs
he writes them too ).

>
>> While not an expert, I should say this type of infinite cascading
>> type and data is typical of a class of ML programs. I believe the
>> little MLer has an example early on.
>>
>> This should also be easy for a Lisper/Schemer to grasp as it just
>> extends on some of their ideas.
>
>Sure, once you know how to do it, it seems easy and obvious. But that
>is true about almost all problems.
No. It's easy and obvious because I learned enough OCaml to make it
easy and obvious. These are aspects of the language which are
fundamental, and anyone taking a professional approach to programming
in ML should be familiar with it enough to understand how to write
HOF's. It's only hackers who have a hard time implementing Y in ML.


--------------------------------------------------
Thaddeus L. Olczyk, PhD
Think twice, code once.

Nils Goesche

unread,
Apr 18, 2003, 6:33:57 PM4/18/03
to
Thaddeus L Olczyk <olc...@interaccess.com> writes:

> While it's true that in math and CS, many definitions evolve
> over time ( ones that come to mind right now are
> function/procedure [which were distinct, now considered the
> same thing], fiber bundles, sheaves, topological space ... ),

Actually, the resp. definitions of fiber bundles, sheaves and
topological spaces /haven't/ changed much over time. If they
have changed at all, once they were called by that names.

> that's all just bullshit thrown out to distract people from
> *your stupidity*.

Darn, I had hoped I'd get away with it one more time.

> Thaddeus L. Olczyk, PhD

I was somewhat hoping that now, having finally obtained your
degree, which is seemingly very important to you, you'd have
become a bit more relaxed. I was wrong.

Farewell,
--
Nils Gösche
Ask not for whom the <CONTROL-G> tolls.

PGP key ID #xD26EF2A0

Thaddeus L Olczyk

unread,
Apr 19, 2003, 1:39:10 AM4/19/03
to
On 19 Apr 2003 00:33:57 +0200, Nils Goesche <n...@cartan.de> wrote:

>Thaddeus L Olczyk <olc...@interaccess.com> writes:
>
>> While it's true that in math and CS, many definitions evolve
>> over time ( ones that come to mind right now are
>> function/procedure [which were distinct, now considered the
>> same thing], fiber bundles, sheaves, topological space ... ),
>
>Actually, the resp. definitions of fiber bundles, sheaves and
>topological spaces /haven't/ changed much over time. If they
>have changed at all, once they were called by that names.
>

When Gauss spoke of topological spaces they were more
like smooth manifolds ( smooth Hausdorff manifolds to be more
precise ). The definition changed over a period of time till
it settled on it's present definition mid 40's ( IIRC).

Steenrod discusses the problems of varying definitions
of fibre bundles in his book.

I'll skip sheaves since I don't remember the details.


>> that's all just bullshit thrown out to distract people from
>> *your stupidity*.
>
>Darn, I had hoped I'd get away with it one more time.
>

Don't you mean twice, as it's clear that this reply is
another attempt at distraction, totally ignoring the
issues.

>> Thaddeus L. Olczyk, PhD
>
>I was somewhat hoping that now, having finally obtained your
>degree,

Sorry to disillusion you, but I got my doctorate many years ago.
I stopped keeping track when it passed ten.

Perhaps you will learn from this mistake. Making unfounded
assumptions will often cause you to make dumb errors. Keep
this in mind when you start doing serious programming, as
it wil save you from a lot of errors in your code.

>which is seemingly very important to you,

Is it? I suppose so. A doctorate is not something just anyone
can accomplish. It takes a dedicated effort over a period of years,
something most people don't have the patience for.

Most of the time I really don't think about it. It's just something
I did in the past.


>you'd have
>become a bit more relaxed. I was wrong.

You seem to be wrong quite a bit of the time. Perhaps you would
not be wrong as much if you did not make unfounded assumptions.

Cliff Wells

unread,
Apr 19, 2003, 3:24:33 AM4/19/03
to
On Thu, 2003-04-17 at 09:02, Steve Holden wrote:

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

Yes, but what many fail to realize is that the nine commands can never
be referred to directly, not even in casual conversation. This is
evident from the ruebot's reluctance to explicitly name them or write
code that describes them in any fashion. This being the case, even
writing something as seemingly simple as hello_world.vic would require a
seemingly endless entanglement of pointers. Only at the moment when
equilibrium is achieved between utter incomprehensibility and endless
self-references does a vic program actually begin to function. In fact,
being either too smart or too dumb will prevent one from grasping the
tao of vic. The exact IQ requirements aren't certain at this point, but
apparently it's somewhere between being able to put up a web page and
being able to write code. Also, if your website seems coherent, then
you're probably too smart as well. It's also known that people too
smart to understand the vic often write working code out of spite and
jealousy.

That definitely makes anyone who writes books like, hm... say _Python
Web Programming_ a loser. Not to name any names <wink>

--
Cliff Wells, Software Engineer
Logiplex Corporation (www.logiplex.net)
(503) 978-6726 x308 (800) 735-0555 x308


Ivan Boldyrev

unread,
Apr 19, 2003, 1:12:03 AM4/19/03
to
On 8353 day of my life Thaddeus L. Olczyk wrote:
>
> >> >And you have to be a bit relaxed when using this requirement; for
> >> >instance, writing an Y-combinator in ML is very hard because of the
> >> >stupid type checker.

> >> No it is easy.

> >> In OCaml,
> >> let rec fix f x=f (fix f) x;;

> >That's cheating and you know it :-)

> No. It's not.
> It's a standard definition of Y in a combinatorial approach
> to computing.

But 'let rec' does Y-combination behind scene. So, it is trick.

Try to implement Y-combinator without rec...

--
Ivan Boldyrev
PGP fp: 3640 E637 EE3D AA51 A59F 3306 A5BD D198 5609 8673 ID 56098673

Outlook has performed an illegal operation and will be shut down.
If the problem persists, contact the program vendor.

Steve Holden

unread,
Apr 19, 2003, 9:45:11 AM4/19/03
to
"Thaddeus L Olczyk" <olc...@interaccess.com> wrote in message
news:bdh1avcltqircf31c...@4ax.com...

See what happens when the Lispers invade (or did we invade them? - either
way, it didn't take long to descend to the stage of ugly name-calling). I
didn't think an 11-year-old would be able to *get* a Ph.D. If it's just
something he did in the past, why does it appear at the foot of every email
he sends out?

glad-to-stick-to-a-friendlier-environment-ly y'rs - steve

Thaddeus L Olczyk

unread,
Apr 20, 2003, 10:23:42 PM4/20/03
to
On 17 Apr 2003 17:53:15 +0200, Nils Goesche <car...@cartan.de> wrote:

>Thaddeus L Olczyk <olc...@interaccess.com> writes:
>

>> On 17 Apr 2003 16:27:53 +0200, Nils Goesche <car...@cartan.de> wrote:

>>=20


>> >A definition that seems sensible to me would be something like: A
>> >language is functional if it somehow contains the lambda calculus.
>> >If you can take lambda calculus formulae and readily translate them
>> >into working code.
>
>> That makes nearly every modern language functional.
>

>Certainly not Java or C# ;-)=20


Yes. Both contain lambda calculus. As does any language
which supports objects.

In ( a sort hand wavy way ),
class Lambda
{
public:
retval exec(arglist){...}
}

Java ( can't say I know enough about C# ) may lack some syntactic
sugar to make it pretty, but it's there.

>But even if that's true -- then so be it.
>If it is true that modern languages tend to be functional, too, then
>you could call that progress. Why should we change the definition of

>``functional=B4=B4 every year in order to keep the ratio of functional t=


o
>non-functional languages constant over time?
>

While it's true that in math and CS, many definitions evolve over
time ( ones that come to mind right now are function/procedure
[which were distinct, now considered the same thing], fiber bundles,

sheaves, topological space ... ), that's all just bullshit thrown out


to distract people from *your stupidity*.

That's because the definition that you have suggested is not some


formal definition appearing in seminal "Introduction to Functional
Programming" type books or papers. It's *your* definition, and it
sucks. Because it's your definition and not a formal one, there is
no suggestion that I am changing the definition over time. As I said,
it's simply a distraction to hide the fact that your definition
*sucks*.

As for your definition, it sucks because it fails to make any
distinction. Almost everyone would agree that languages like
Haskell, ML, Clean, Scheme and ( sometimes ) Lisp are functional.
And your definition includes those. But your definition would say that
languages like C, Eiffel and Smalltalk ( not to mention C++, Java and
C# ) are functional, which almost no one would agree with.

>> >And you have to be a bit relaxed when using this requirement; for


>> >instance, writing an Y-combinator in ML is very hard because of the
>> >stupid type checker.

>>=20
>> No it is easy.
>>=20
>> In OCaml,=20
>> let rec fix f x=3Df (fix f) x;;


>
>That's cheating and you know it :-)
>
No. It's not.
It's a standard definition of Y in a combinatorial approach
to computing.

>> For a more traditional approach.
>> type 'a rf =3D RF of ( 'a rf -> 'a );;
>>=20
>> let y f x=3D=20
>> let g (RF h) z=3D


>> f( h (RF h) ) z in
>> (g (RF g)) x;;

>>=20


>> Of course the example above looks like:

>> let fact x=3D y ( fun q->
>> (fun n->=20
>> if n<2 then 1=20


>> else n* (q (n-1)))) x;;

>>=20


>> When I did it this way the first time it was a bit difficult getting
>> the type right.
>

>I know: Been there done that ;-\ Took me some time. =20


What can I say. Some people are slower than others.

>Certainly /much/
>longer than simply translating the lambda calculus formula to Lisp, so
>I refuse calling it easy, even if the ML code that finally works is
>short.
And know we see why some people are slower.
I never even thought of "translating" the code.
I did what every one is taught in every math class.
I rederived it in ML. In the process I found it easy.
The only sticking point was that I did not understand
user defined types well enough to write HOFs. Once
I understood that it was trivial.

>
>> But the reason was that I was new to the OCaml typing system. It
>> wasn't what the type should look like, it was just getting the
>> declaration right.
>
>If it's so easy, why did they even bother putting it into the ML FAQ?
Because there are lazy people who don't write code from first
principles, or bother to learn enough about user defined types
to write HOFs ( the true FP practitioner doesn't just use HOFs
he writes them too ).

>
>> While not an expert, I should say this type of infinite cascading
>> type and data is typical of a class of ML programs. I believe the
>> little MLer has an example early on.

>>=20


>> This should also be easy for a Lisper/Schemer to grasp as it just
>> extends on some of their ideas.
>
>Sure, once you know how to do it, it seems easy and obvious. But that
>is true about almost all problems.
No. It's easy and obvious because I learned enough OCaml to make it
easy and obvious. These are aspects of the language which are
fundamental, and anyone taking a professional approach to programming
in ML should be familiar with it enough to understand how to write
HOF's. It's only hackers who have a hard time implementing Y in ML.

Warren Postma

unread,
Apr 21, 2003, 1:29:38 AM4/21/03
to

> I'll second that. Maybe we could get func added as a synonym for lambda, at least.


Maybe we should translate all language keywords into some other popular
languages than english. In which case, Lambda can remain as is, for our
greek friends, and the rest of the keywords can change to greek words.

My-big-fat-greek-python-ly-yr's

Warren

A. Lloyd Flanagan

unread,
Apr 21, 2003, 9:21:49 AM4/21/03
to
Warren Postma <warren...@sympatico.ca> wrote in message news:<ilLoa.1695$Qg2.1...@news20.bellglobal.com>...

What's the greek word for "python"?

Cliff Wells

unread,
Apr 21, 2003, 6:32:14 AM4/21/03
to
On Fri, 2003-04-18 at 16:30, laotseu wrote:

for x in range(100):
> print "I shall not say that Lisp is a functional language anymore"

Better yet:

for x in range(1000):
print "I shall not invite those rude %$&!s at c.l.lisp to c.l.py anymore"

;)

Robin Munn

unread,
Apr 21, 2003, 5:40:22 PM4/21/03
to
Andrew Bennetts <andrew-p...@puzzling.org> wrote:
> 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:
[snip one question]
>> - 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
>

List length is cached with the list object, so this is indeed O(1).
Another way would have been:

try:
L[1]
except IndexError:
print "L has at most one element"

Note that this will not tell you whether the list has exactly one
element, so it answers a slightly different question. But it's always
useful to know of different ways of solving a problem.

--
Robin Munn <rm...@pobox.com>
http://www.rmunn.com/
PGP key ID: 0x6AFB6838 50FF 2478 CFFB 081A 8338 54F7 845D ACFD 6AFB 6838

Christian Tismer

unread,
Apr 21, 2003, 4:32:01 PM4/21/03
to
Alex Martelli wrote:
...

> 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.

FYI, Stackless 3.0 is almost ready. It re-invents the old principles
of Stackless 1.0, which means, it can avoid 80 percent of all
recursive calls without any hardware dependant code.
In a couple of hours, I will publish this version.
It will compile with hardware stack switching on all supported
platforms. On other platforms, it will at least try to avoid
recursive interpreter calls as much as it can.
With the latter version, you can do unlimited recursions,
unless you are usin deep recursive calls of special __ methods,
which are not supported by the software-only version, yet.

ciao - chris
--
Christian Tismer :^) <mailto:tis...@tismer.com>
Mission Impossible 5oftware : Have a break! Take a ride on Python's
Johannes-Niemeyer-Weg 9a : *Starship* http://starship.python.net/
14109 Berlin : PGP key -> http://wwwkeys.pgp.net/
work +49 30 89 09 53 34 home +49 30 802 86 56 pager +49 173 24 18 776
PGP 0x57F3BF04 9064 F4E1 D754 C2FF 1619 305B C09C 5A3B 57F3 BF04
whom do you want to sponsor today? http://www.stackless.com/

laotseu

unread,
Apr 21, 2003, 8:16:24 PM4/21/03
to
Steve Holden wrote:
> "Thaddeus L Olczyk" <olc...@interaccess.com> wrote in message

(snip *Dr* Olczyk prose)

> See what happens when the Lispers invade (or did we invade them? - either
> way, it didn't take long to descend to the stage of ugly name-calling). I
> didn't think an 11-year-old would be able to *get* a Ph.D. If it's just
> something he did in the past, why does it appear at the foot of every email
> he sends out?
>
> glad-to-stick-to-a-friendlier-environment-ly y'rs - steve

Lol !-)

And sorry for being somewhat responsible for this lisper's invasion
here. I had forgotten why I'd stop reading comp.lang.lisp first (bad
signal/noise ratio).

Laotseu

laotseu

unread,
Apr 21, 2003, 8:20:44 PM4/21/03
to
Cliff Wells wrote:
> On Fri, 2003-04-18 at 16:30, laotseu wrote:
>
> for x in range(100):
>
>> print "I shall not say that Lisp is a functional language anymore"
>
>
> Better yet:
>
> for x in range(1000):
> print "I shall not invite those rude %$&!s at c.l.lisp to c.l.py anymore"
>
> ;)
>

Yes, I do apologize for this too. As said in another post in this
thread, I had forgotten why I stopped reading c.l.lisp.

Now I remember :(

Laotseu

Robin Munn

unread,
Apr 21, 2003, 6:00:54 PM4/21/03
to
Steve Holden <sho...@holdenweb.com> wrote:
> "laotseu" <bde...@removethis.free.fr> wrote ...
>> Greg Ewing (using news.cis.dfn.de) wrote:
>> > 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.
>>
>> lol !-)
>>
> This *finally* gives me the chance to ask: when a lambda grows up, does it
> become a sheepda?

Only if it is stored in RAM.

Otherwise, it's a sheepma, don't ewe know.

Thomas Stegen

unread,
Apr 22, 2003, 10:10:22 PM4/22/03
to
Paul Wallich wrote:
>
> It's the second. In a strictest-sense functional language, it is
> impossible to write a whole program that *does* have side effects.

It would be easy to write such a program though. Without any sideeffects
the preconditions reduces to the postconditions and so the whole program
disappears. :) Now that would be very nice and simple, it might even be
the silver bullet.

--
Thomas.
"How long is six months? Ten years?"
- Denis Johnson, Fiskadoro

Mark Jason Dominus

unread,
Apr 23, 2003, 2:17:39 PM4/23/03
to
In article <btqu9vkh7u9nj6v25...@4ax.com>,
Courageous <jkr...@san.rr.com> wrote:
>
>>But he regrets the inclusion of a crippled lambda, rather than the
>>inclusion of support for anonymous functions (IIRC).
>
>Anyway, I guess what I'm saying is that I suspect that Guido
>didn't have any good alternatives.


I don't believe that's correct. At an early Open Source Conference,
perhaps around 1998 or so, I was present at a conversation between
Guido and Tom Christiansen. Tom asked Guido why Python didn't have
closures, and Guido's reply (and I think this is an exact quote) was
"Closures aren't important."

I remember it because I was so astonished by the obtuseness of the answer.

Aahz

unread,
Apr 23, 2003, 3:27:31 PM4/23/03
to
In article <b86lc3$tnd$1...@plover.com>,

Mark Jason Dominus <m...@plover.com> wrote:
>In article <btqu9vkh7u9nj6v25...@4ax.com>,
>Courageous <jkr...@san.rr.com> wrote:
>>Courageous as usual deleted someone else's attribution:

>>>
>>>But he regrets the inclusion of a crippled lambda, rather than the
>>>inclusion of support for anonymous functions (IIRC).
>>
>>Anyway, I guess what I'm saying is that I suspect that Guido
>>didn't have any good alternatives.
>
>I don't believe that's correct. At an early Open Source Conference,
>perhaps around 1998 or so, I was present at a conversation between
>Guido and Tom Christiansen. Tom asked Guido why Python didn't have
>closures, and Guido's reply (and I think this is an exact quote) was
>"Closures aren't important."
>
>I remember it because I was so astonished by the obtuseness of the answer.

Two points:

* I'd be mildly surprised if that were an exact quote. Python 2.1 was
released 4/2001, with support for nested scopes (which allows building
closures of sorts). That's roughly two years for Guido to change his
mind, which is a short timeframe for him. ;-)

* Many of the things for which programmers in other languages use
closures are better done in Python as classes. He's generally
antipathetic to borrowing idioms from other languages that make it easier
to write unpythonic code -- There's Only One Way. Like other leaders in
the Open Source community, Guido is occasionally prone to making
obnoxious comments Just Because.
--
Aahz (aa...@pythoncraft.com) <*> http://www.pythoncraft.com/

Why is this newsgroup different from all other newsgroups?

Tj

unread,
Apr 23, 2003, 6:30:18 PM4/23/03
to
m...@plover.com (Mark Jason Dominus) wrote in message news:<b86lc3$tnd$1...@plover.com>...

> I don't believe that's correct. At an early Open Source Conference,
> perhaps around 1998 or so, I was present at a conversation between
> Guido and Tom Christiansen. Tom asked Guido why Python didn't have
> closures, and Guido's reply (and I think this is an exact quote) was
> "Closures aren't important."
>
> I remember it because I was so astonished by the obtuseness of the answer.

Well, it seems the burden of proof is on you. Please explain the
usability advantages of closures vs. Python's current scope system.

Tj

andrew cooke

unread,
Apr 23, 2003, 7:15:11 PM4/23/03
to

a related question - why does queue have to be passed to helper() in the
code below? i tried to define it inside walktree (but outside helper)
since it's global to the function, but python objects saying that the
local variable "queue" in helper is accessed before it's defined. this
seems to be an example of where closures would work perfectly...

#!/usr/bin/python2.2

from __future__ import generators # needed for Python 2.2
import os

def walktree(basepath=".", postorder=True, depthfirst=True,
ignorelinks=True):

"""Noah Spurrier's code, modified to allow depth/breadth-first
traversal. The recursion is there *only* to allow postorder
processing as the stack rolls back - the rest of the algorithm is
imperative and queue would be declared outside helper if I knew
how."""

# why can't queue be defined here as [basepath] (and then omitted
# from calls to helper).

def helper(queue):

while queue:

if depthfirst: dir = queue.pop(-1)
else: dir = queue.pop(0)

children = os.listdir(dir)

dirs, nondirs = [], []

for name in children:
fullpath = os.path.join(dir, name)
if os.path.isdir(fullpath) and not \
(ignorelinks and os.path.islink(fullpath)):
dirs.append(name)
queue.append(fullpath)
else:
nondirs.append(name)

if not postorder:
yield dir, dirs, nondirs

if postorder:
for rest in helper(queue):
yield rest
yield dir, dirs, nondirs

return helper([basepath])

def test():
for basepath, dirs, nondirs in \
walktree(postorder=False, depthfirst=False):
for name in dirs:
print os.path.join(basepath, name)
for name in nondirs:
print os.path.join(basepath, name)

if __name__ == '__main__':
test()

tj_sc...@yahoo.com said:

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


--
http://www.acooke.org/andrew

Tj

unread,
Apr 23, 2003, 9:03:40 PM4/23/03
to
Hmm, must be sleepy because I could have sworn that you wrote that you
asked him this question, not Tom Christiansen.

Tj

tj_sc...@yahoo.com (Tj) wrote in message news:<ccc7084.03042...@posting.google.com>...

Tim Peters

unread,
Apr 23, 2003, 11:17:15 PM4/23/03
to
[attribution lost]

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

[Courageous]


>> Anyway, I guess what I'm saying is that I suspect that Guido
>> didn't have any good alternatives.

[Mark Jason Dominus]


> I don't believe that's correct.

In the Python world, you're missing the context: lambda was in version 1.0
of Python. They're "crippled" not so much because they didn't support
closures (they do in current Pythons, BTW), but because they're
syntactically limited to a single expression, and Python is not an
expression language (Python statements are not Python expressions, so no
matter how perverse you try to be, you can't write a Python lambda that
contains a Python statement -- what you can do inside a Python lambda is use
a crippled subset of the language).

That said, Guido regrets lambdas anyway <wink>.

> At an early Open Source Conference, perhaps around 1998 or so, I was
> present at a conversation between Guido and Tom Christiansen. Tom asked
> Guido why Python didn't have closures, and Guido's reply (and I think
> this is an exact quote) was "Closures aren't important."
>
> I remember it because I was so astonished by the obtuseness of the
> answer.

I expect he still believes that. I do too: in Python, closures aren't
important. Python eventually grew closures, and they're *nice* to have, but
it's always been possible to use Python's flexible classes to get the same
abilities, and it's even always been possible to get "real closures" via
abuse of Python's default-argument mechanism:

def make_adder(n):
def adder(i, n=n):
return n+i
return adder

add5 = make_adder(5)
add3 = make_adder(3)
print add5(1), add3(1)

has printed 6 4 for eons. This has too, replacing the function with a class
of the same name:

class make_adder:
def __init__(self, n):
self.n = n

def __call__(self, i):
return self.n+i

It often proves much better to carry state around in explicit objects
instead of in hard to introspect, or to modify (unless you planned for that
from the start), anonymous closures. In the above, I can easily introspect
to see what an instance of the make_adder class adds, and even change it if
I need to, and the class's author didn't need to anticipate either of those.
With the by-hand default-arg closure, introspection is still possible but
much harder, while mutation of what it does requires deep (and formally
undefined) wizardy. With the current "real closure" version:

def make_adder(n):
return lambda i: n+i

introspection and mutation are both too painful to contemplate (of course
that inability to inspect or change is also a feature in some parts of some
apps -- usually brittle ones <0.9 wink>).

Closures can be much more convenient in the small (I think make_adder is a
good example of that); in the large, piles of nested closures are often more
a maintenance nightmare than a blessing, and especially when they're used to
maintain state more naturally modeled via classes. Python doesn't need
closures -- they're just nice to have.

when-you-don't-have-a-hammer-only-nails-look-like-nails-ly y'rs - tim


Dave Benjamin

unread,
Apr 24, 2003, 3:04:41 AM4/24/03
to
In article <mailman.1051154381...@python.org>, Tim Peters wrote:
> (Python statements are not Python expressions, so no
> matter how perverse you try to be, you can't write a Python lambda that
> contains a Python statement -- what you can do inside a Python lambda is use
> a crippled subset of the language).

This is what I was talking about in my original post. I don't believe that
the Python lambda offers a crippled subset of the language any more than I
believe that a constant offers a crippled subset of the functionality of a
variable. Lambdas are expressions, for use with other expressions. Defs
are statements, for use with other statements. I don't find this crippled or
redundant.

Perhaps this is an over-generalization, but I think that nestability
encourages readability. The nice thing about lambdas in Python are that they
enforce this property.

> That said, Guido regrets lambdas anyway <wink>.

He may one day live to regret regretting lambdas. =) In the meantime, all
I'm saying is that I really like Python the way it is. Why ruin a good thing?

One last thing and I'm off of my soapbox. ;) I've been thinking more about
the parallel between list comprehensions and relational calculus vs.
map/filter functions and relational algebra. I mentioned this briefly before
but I want to bring it up again because nobody commented. I'm totally open
to criticism. Nonetheless, did anybody notice that filter+lambda can express
a "select" operation in relational algebra using almost identical syntax:

r.a.: select [age > 20] (people)
python: filter(lambda x: x.age > 20, people)

Now, most of the time, perhaps we use a form of relational calculus (SQL) to
do this type of thing anyway. But relational algebra is still around. It's
still a useful concept. Why?

1. It's very regular
2. It's easy to parse
3. It's very portable across languages

I can port my map/filter code to PHP, for instance, or to LISP, or even to
ActionScript (with appropriate language hacks). List comprehensions, on the
other hand, are proprietary Python (or Haskell) extensions from a
meta-linguistic perspective. I love them to death, still, but just think
about it.

Okay, I'm off to meta-land. 'Night, y'all. =)
Peac,
Dave

Dave Benjamin

unread,
Apr 24, 2003, 3:44:08 AM4/24/03
to
In article <slrnbaf35b...@lackingtalent.com>, Dave Benjamin wrote:
> Perhaps this is an over-generalization, but I think that nestability
> encourages readability. The nice thing about lambdas in Python are that they
> enforce this property.

Before I get completely blasted for this, I meant to say "reusability", not
"readability". I am aware of the effect that nesting can have on readability.
It's not necessarily a good thing. ;)

Ducking,
Dave

Duncan Booth

unread,
Apr 24, 2003, 4:24:28 AM4/24/03
to
"andrew cooke" <and...@acooke.org> wrote in
news:mailman.1051139802...@python.org:

> a related question - why does queue have to be passed to helper() in the
> code below? i tried to define it inside walktree (but outside helper)
> since it's global to the function, but python objects saying that the
> local variable "queue" in helper is accessed before it's defined. this
> seems to be an example of where closures would work perfectly...

Well, I don't know what you did but the problem was your's not Python's. I
tried your code and it ran, I then added queue = [basepath] immediately
before the def helper, and removed the parameter queue and the [basepath]
from the call. I made no other changes. It still runs.

Perhaps you had some other version of the code where you tried assigning to
queue inside the helper function? That would give the problem you describe,
but simply mutating it as the code you posted does is fine.

--
Duncan Booth dun...@rcp.co.uk
int month(char *p){return(124864/((p[0]+p[1]-p[2]&0x1f)+1)%12)["\5\x8\3"
"\6\7\xb\1\x9\xa\2\0\4"];} // Who said my code was obscure?

Will Stuyvesant

unread,
Apr 24, 2003, 5:18:03 AM4/24/03
to
[Tim Peters]
> ...

> class make_adder:
> def __init__(self, n):
> self.n = n
>
> def __call__(self, i):
> return self.n+i
>
> It often proves much better to carry state around in explicit objects
> instead of in hard to introspect, or to modify (unless you planned for that
> from the start), anonymous closures.
> ...

> when-you-don't-have-a-hammer-only-nails-look-like-nails-ly y'rs - tim

Another great posting Tim! Who much time do you take to write
something like that?
Indeed, using a class it would be possible to *extend* a hammer, for
example such that it counts how much hits it did. With *pure*
closures this would be a pain.

closure-classes-for-hammers-that-count-ly y'rs

It is loading more messages.
0 new messages