views:

1418

answers:

7

I have always thought that functional programming can be done in Python. Thus, I was surprised that Python didn't get much of a mention in this question, and when it was mentioned, it normally wasn't very positive. However, not many reasons were given for this (lack of pattern matching and algebraic data types were mentioned). So my question is: why isn't Python very good for functional programming? Are there more reasons than its lack of pattern matching and algebraic data types? Or are these concepts so important to functional programming that a language that doesn't support them can only be classed as a second rate functional programming language? (Keep in mind that my experience with functional programming is quite limited.)

+2  A: 

Maybe this article will help clear it up.

roar
+11  A: 

Guido has a good explanation of this here. Here's the most relevant part:

I have never considered Python to be heavily influenced by functional languages, no matter what people say or think. I was much more familiar with imperative languages such as C and Algol 68 and although I had made functions first-class objects, I didn't view Python as a functional programming language. However, earlier on, it was clear that users wanted to do much more with lists and functions.

...

It is also worth nothing that even though I didn't envision Python as a functional language, the introduction of closures has been useful in the development of many other advanced programming features. For example, certain aspects of new-style classes, decorators, and other modern features rely upon this capability.

Lastly, even though a number of functional programming features have been introduced over the years, Python still lacks certain features found in “real” functional programming languages. For instance, Python does not perform certain kinds of optimizations (e.g., tail recursion). In general, because Python's extremely dynamic nature, it is impossible to do the kind of compile-time optimization known from functional languages like Haskell or ML. And that's fine.

I pull two things out of this:

  1. The language's creator doesn't really consider Python to be a functional language. Therefore, it's possible to see "functional-esque" features, but you're unlikely to see anything that is definitively functional.
  2. Python's dynamic nature inhibits some of the optimizations you see in other functional languages. Granted, Lisp is just as dynamic (if not more dynamic) as Python, so this is only a partial explanation.
Jason Baker
You can do tail call optimization in Python just fine. Guido doesn't/didn't understand that.
Jules
It seems to boil down to that Guido van Rossum _doesn't_like_ functional style.
Svante
I think it's more accurate to say that Guido van Rossum doesn't understand functional style, and doesn't understand why Python needs them. You have to understand two things: 1) programming languages are at the bottom of a technology stack and affect everything built upon them and 2) just like any other piece of software, it's easier to add features than it is to remove them. So I think it's a good quality for a language designer to be critical of these kinds of requests.
Jason Baker
+3  A: 

Python is almost a functional language. It's "functional lite".

It has extra features, so it isn't pure enough for some.

It also lacks some features, so it isn't complete enough for some.

The missing features are relatively easy to write. Check out posts like this on FP in Python.

Check the answers to this question on functional programming languages. The comments are more informative than my lame answer.

S.Lott
For the most part, I agree with this post. But I can't agree with saying that Python is a functional language. It very much encourages imperative programming, and it's difficult not to with the "extra features" you mention. I think it's best to refer to Python as "functional lite" as you did in the other post. :-)
Jason Baker
+10  A: 

Scheme doesn't have algebraic data types or pattern matching but it's certainly a functional language. Annoying things about Python from a functional programming perspective:

  1. Crippled Lambdas. Since Lambdas can only contain an expression, and you can't do everything as easily in an expression context, this means that the functions you can define "on the fly" are limited.

  2. Ifs are statements, not expressions. This means, among other things, you can't have a lambda with an If inside it. (This is fixed by ternaries in Python 2.5, but it looks ugly.)

  3. Guido threatens to remove map, filter, and reduce every once in awhile

On the other hand, python has lexical closures, Lambdas, and list comprehensions (which are really a "functional" concept whether or not Guido admits it). I do plenty of "functional-style" programming in Python, but I'd hardly say it's ideal.

Jacob B
Map, filter, and reduce really aren't needed in python. I have yet to see a piece of code that was simplified very much by using them. Plus, calling functions in Python can be expensive, so it's usually better just to use a list/generator comprehension or a for loop anyway.
Jason Baker
This is exactly what Nathan Sanders says below: "Python does not promote functional programming even though it works fairly well." If Guido wanted Python to become a functional language, he'd make the implementation work well enough to use throwaway functions, and would uncripple Lambdas to the extent that you can actually use map/filter/reduce in useful ways.On the other hand, functional people are starting to wake up to the awesomeness of list comprehensions. Hopefully we won't have to pick one or the other.
Jacob B
map and filter are trivially replace by a list comprehension. reduce -- almost always -- it so inefficient that it should be replaced with a generator function.
S.Lott
+20  A: 

The question you reference asks which languages promote both OO and functional programming. Python does not promote functional programming even though it works fairly well.

The best argument against functional programming in Python is that imperative/OO use cases are carefully considered by Guido, while functional programming use cases are not. When I write imperative Python, it's one of the prettiest languages I know. When I write functional Python, it becomes as ugly and unpleasant as your average language that doesn't have a BDFL.

Which is not to say that it's bad, just that you have to work harder than you would if you switched to a language to promotes functional programming or switched to writing OO Python.

Here are the functional things I miss in Python:

  • Pattern matching
  • Tail recursion
  • Large library of list functions
  • Functional dictionary class
  • Automatic currying
  • Concise way to compose functions
  • Lazy lists
  • Simple, powerful expression syntax (Python's simple block syntax prevents Guido from adding it)


  • No pattern matching and no tail recursion mean your basic algorithms have to be written imperatively. Recursion is ugly and slow in Python.
  • A small list library and no functional dictionaries mean that you have to write a lot of stuff yourself.
  • No syntax for currying or composition means that point-free style is about as full of punctuation as explicitly passing arguments.
  • Iterators instead of lazy lists means that you have know whether you want efficiency or persistence, and to scatter calls to list around if you want persistence. (Iterators are use-once)
  • Python's simple imperative syntax, along with its simple LL1 parser, mean that a better syntax for if-expressions and lambda-expressions is basically impossible. Guido likes it this way, and I think he's right.
Nathan Sanders
+4  A: 

I would never call Python “functional” but whenever I program in Python the code invariably ends up being almost purely functional.

Admittedly, that's mainly due to the extremely nice list comprehension. So I wouldn't necessarily suggest Python as a functional programming language but I would suggest functional programming for anyone using Python.

Konrad Rudolph
+3  A: 

Let me demonstrate with a piece of code taken from an answer to a "functional" Python question on SO

Python:

def grandKids(generation, kidsFunc, val):
  layer = [val]
  for i in xrange(generation):
    layer = concat(itertools.imap(kidsFunc, layer))
  return layer

def concat(xs):
  for x in xs:
    for val in x:
      yield val

Haskell:

grandKids generation kidsFunc val =
  iterate (concatMap kidsFunc) [val] !! generation

The main difference here is that Haskell's standard library has useful functions for functional programming: in this case iterate, concat, and (!!)

yairchu