Hacker Timesnew | past | comments | ask | show | jobs | submitlogin

> Rossum, the inventor of Python, hates Lisp, but he was dragged kicking and screaming to lambda

I'm not sure that's true, anyone have more details? Most people don't like the parens everywhere with lisp, but otherwise speak of it highly.

Edit: thanks for the links on lambda, read all of them. However, didn't see anything obvious written about lisp itself.



"Kicking and screaming", to be fair, is a bit of a literary exaggeration. But Rossum did not particularly want to add functional features to the language and only did so at the behest of his users. Lambda as well as map/filter/reduce were "a significant, early chunk of contributed code", not something he intended the language to have from the outset[1]. More recently, he has been trying to deemphasize these features in favor of list comprehensions.

Moreover, Rossum is opposed to proper tail calls and even recursion in general[2]. He also doesn't like folds, and generally thinks you should just express that sort of logic as some sort of loop. (I forget exactly where I read that opinion, but it could easily have been [1].)

He's a staunchly imperative programmer, and the design of Python shows this off consistently except for an initial accident of first-class functions and closures (of a sort)—a design he likes because it enabled other, non-functional language features like new-style classes.

"Kicking and screaming" might have been an exaggeration, but it captures his overall attitude towards functional programming pretty well.

[1]: http://python-history.blogspot.com/2009/04/origins-of-python...

[2]: http://neopythonic.blogspot.com/2009/04/tail-recursion-elimi...


There are many thing he didn't intend from the outset, so that by itself isn't so significant. Some other things he didn't intend were the type/class dichotomy and the inability to raise an exception from comparison. Two changes that come from external users include David Ascher's rich comparisons and Samuele Pedroni's proposal to use the C3 method resolution order.

Van Rossum's preference for loops over map dates to at least 1994, which you can see in http://legacy.python.org/search/hypermail/python-1994q2/0705... :

> "Steven Majewski might not agree with me, but in Python you are better off using "for" loops (the overhead of calling a function for each element is quite substantial)."

You can see that's still true with CPython:

  % python -mtimeit -c 'x=range(100)' 'd=[]' 'for a in x: d.append(a*a)'
  10000 loops, best of 3: 22.1 usec per loop
  % python -mtimeit -c 'x=range(100)' 'map(lambda a: a*a, x)'
  100000 loops, best of 3: 18.2 usec per loop
  % python -mtimeit -c 'x=range(100)' 'd=[];ADD=d.append' 'for a in x: ADD(a*a)'
  100000 loops, best of 3: 12.7 usec per loop
  % python -mtimeit -c 'x=range(100)' '[a*a for a in x]'
  100000 loops, best of 3: 9.91 usec per loop
FWIW, Python has made at least one language change in order to improve performance. In Python 1.x the following was possible:

  def f(x):
    from math import *
    return cos(x*sin(x))
Python 1 used a dictionary for locals, while Python 2 introduced a pre-allocated array of variables for locals so lookup could be done via a simple index offset.

In the same email, van Rossum writes:

> "To be honest, I wish I hadn't introduced lambda, map, filter and reduce -- they support a style that is inconsistent with the rest of Python. Unfortunately, in the sake of backward compatibility, I can't take them out. So enjoy them if you have to. But don't get too thrilled!"

That same email also says:

> Ah, the infamous "first class objects" argument again. Really, I don't understand all the fuzz about lambda, and I don't see why its introduction made functions any more first class than they already were in Python. They are entirely syntactic sugar for local function definitions. Everything you can do with lambda you could always do with local functions, at the cost of one local temporary identifier -- surely no big deal!

This is interesting because you mentioned "initial accident of first-class functions". Why do you think first-class objects are an "initial accident", and not a deliberate decision?


I just can't understand anyone who is black and white. I like when I have both tools at my disposal: recursion and iteration.


when you have a project concerned with readability, adding new features is a huge community cost in the long run because it's one more thing you have to learn to deal with as you go across projects.

One of the wonderful things with python is that you can dig into the code of most python projects and not have to worry much about completely different idioms requiring a complete context switch to understand how they work.

He is not really being black and white, he is doing a service by preventing language bloat ala C++ as much as possible.


It always struck me as a reaction against Perl's "Tim Toady" approach, encouraging a more idiomatic and unified programming strategy to ease comprehension and teaching (IIRC the origin of Python, or at least ABC).


This is exactly what makes Python a bad language. Lack of expressive power results in an unnecessary complexity of the code. It's much easier to comprehend a short, compact code written in the familiar, domain-specific idioms rather than digging through convoluted pile of low-level leaky idioms like loops, list comprehensions, generators, classes, recursion and all that irrelevant crap.


Just wanted to add my voice: this matches exactly my perception. I used to really like Python, but I've come to the conclusion that there's a certain point in terms of the complexity of a Python program where everything just blows up and it's next to impossible to keep it from becoming a tangled mess. This point is reached incredibly soon, something like five classes with some inheritance, some interface/virtual/abstract class. Ugh. Now I avoid Python as much as possible, much preferring C++ or Java, which I think work incredibly better for larger programs.


I used to think I needed both, but since picking up Haskell I don't miss for loops at all and I rarely need to use explicit recursion either--now I almost exclusively use higher-order functions like `map`.


When I started learning Python, I always used map and filter because they were just how I thought about problems. But there is a certain bit of elegance to being able to write

    [process(child) for child in node if child is not None]
in lieu of

    map(process, filter(notNone, child))
The functional style makes better use of conceptual primitives, but the imperative style is generally better for documenting.

    for child in node:
        if child is not none: # Comment explaining decision.
             process(child) # Comment explaining more stuff.


The first thing you show is a list comprehension [1], and it's still very much functional style, even if it has a "for" in it.

Heck, Haskell has pure list comprehensions. [2]

[1] https://en.wikipedia.org/wiki/List_comprehension#Python

[2] https://en.wikipedia.org/wiki/List_comprehension#Haskell


Oh, I agree. I mentioned it because is the preferred style in Python -- probably because it is so readable. But my points still apply to the loop version.


I'm actually a bit scared of using recursion in production (at a web company). It has its place of course, but gratuitous recursive code that could have been written without gives me pause. It's too easy to miss an edge case and end up with a stack overflow, and that can bring down a whole server farm.


I think LINQ got this very nearly right. You can write this LINQ-style

    from child in node where child != null select process(child)
or with extension methods

    node.Where(c => c != null).Select(process)


Haskell (using function composition):

    map process . filter notNone $ child


If node is a list of children that are wrapped in Maybes you could do something like this:

     map process $ catMaybes node
(catMaybes :: [Maybe a] -> [a] - The catMaybes function takes a list of Maybes and returns a list of all the Just values.) https://www.haskell.org/hoogle/?hoogle=catMaybes

edit: and even if it's not a list, there's a more general implentation of catMaybes for any type that fulfills isSequence here: https://github.com/snoyberg/mono-traversable/blob/master/src...


Of course you are talking about practical useage, not making blanket theoretical statements, but it may be worth knowing that there are computable functions, if somewhat tortured ones, that can't be computed just by `map`s and `fold`s. See https://en.wikipedia.org/wiki/Primitive_recursive_function#L... and http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=6... .


Lambda entered Python in 1993:

  changeset:   1369:89e1e5d9ccbf
  branch:      legacy-trunk
  user:        Guido van Rossum <guido@python.org>
  date:        Tue Oct 26 17:58:25 1993 +0000
  summary:     * compile.[ch]: support for lambda()
so that's only two years after it was first released, and before it was 1.0. The code was user-contributed, but given the timing and the recollections at http://python-history.blogspot.com/2009/04/origins-of-python... I can't agree that the historical record is compatible with "dragged kicking and screaming to lambda."

(See also http://legacy.python.org/search/hypermail/python-1994q2/0705... for his views on the topic from 1994.)

Van Rossum doesn't think lambda is important, and would rather not have it in Lisp. He wanted to remove it for Python 3, but there was large opposition to that. See his viewpoint from 2005 at http://www.artima.com/weblogs/viewpost.jsp?thread=98196 . After a large debate about alternatives (see https://wiki.python.org/moin/AlternateLambdaSyntax ) he agreed to keep lambda in 2006 at https://mail.python.org/pipermail/python-dev/2006-February/0... .


What a shame it would be if he'd removed it. Pyspark now makes great use of lambdas, and I'd strongly argue that having to name every function argument would be strictly worse.


Tk developers have long agreed with you, because it really is easier to say

   Button(frame, text="abc",
          command=lambda: self.highlight("abc"))
than to make a function for each command.

The loose consensus in Python is that lambdas are best when they fit on a line, which is what the examples at http://www.mccarroll.net/blog/pyspark2/index.html do. Otherwise, make a named function.

I think arguments like this are one of the main reasons why van Rossum has kept lambda in the language.


This looks like Guido's version of the story: http://python-history.blogspot.com/2009/04/origins-of-python...




Consider applying for YC's Fall 2026 batch! Applications are open till July 27.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: