With respect to Python, I am somewhat shocked at some of the other answers. This is what Andrew Kuchling (Python Functional Programming HOWTO) says:
The designers of some computer languages choose to emphasize one particular
approach to programming. This often makes it difficult to write programs
that use a different approach. Other languages are multi-paradigm languages
that support several different approaches. Lisp, C++, and Python are
multi-paradigm; you can write programs or libraries that are largely procedural,
object-oriented, or functional in all of these languages. In a large program,
different sections might be written using different approaches; the GUI might
be object-oriented while the processing logic is procedural or functional,
for example.
Dave Mertz presented a more in(1) depth(2) discussion of functional programming, saying,
Summary: Although users usually think of Python as a procedural
and object-oriented language, it actually contains everything you need
for a completely functional approach to programming. This article
discusses general concepts of functional programming, and illustrates
ways of implementing functional techniques in Python.
Python fully supports higher order functions (the first example on that wikipedia page is written in Python!). This is a common misconception. Even if map()
were not built-in, it is trivially manufactured by
def map(function, l):
return [function(item) for item in l] # A complete list object is returned
In fact, observing the function written so should immediately inform as to why map()
might be considered redundant. The above example can be trivially converted into a form that returns each function evaluation lazily, by changing the list comprehension into a generator:
def map(function, l):
return (function(item) for item in l) # A generator object is returned
It would be called like so:
def dbl(x):
return x + x
for answer in map(dbl, [1,2,3,4,5]):
print answer # Produces 2 4 6 8 10 one per line
The sometimes flammable issue of lambda
(please don't debate this with me, this issue has been beaten to death in far more illustrious places than my answer, I am not qualified to debate this point, etc) is another good example:
function = lambda x,y: x + y
print function(2,3) # produces '5'
is completely equivalent to
def f(x,y):
return x + y
function = f
print function(2,3) # produces '5'
There is no reason to persist with a keyword called lambda, when the syntax of the language itself provides the functionality. Functional programming isn't about what specific functions are called; it is more about how things get done. As far as I am aware, the primary deficiency of Python compared to something like Scheme is the inability to modify the code itself in as easy a way as modifying a list: this code-is-data property is a consequence of using S-expressions, because then all code syntax looks like a list. Python doesn't do that, or not as easily. If this is something you want to get into, then that pretty much decides the case for you and you'll have to focus on a language with S-expressions/prefix notation.
Having said all that, there are some problems with Python as a functional language:
The Global Interpreter Lock (GIL) in Python means that dividing up python threads amongst multiple separate CPU cores is not possible. IronPython may or may not get around this (exercise left to reader). The point of having multiple cores available is that functional languages lend themselves to parallelizable execution paradigms, and you just won't see a big benefit of this using stock Python on a multi-core machine. (In practice, many people use the excellent multiprocessing package in the standard library for multi-core concurrency, or even manually launching multiple instances of an app on the command line with shell scripts and so on; but these are practical considerations that have nothing to do with functional programming.)
Not being forced to adopt functional programming idioms might hinder your learning. Idiomatic Python is by no means close to the "functional programming paradigm", and you have to go out of your way to stick to a functional "style", simple because more idiomatic ways are easier to do, and more frequently recommended in online documentation and tutorials. The Mertz article should help with that though.
Recursion. By default, Python has a recursion limit, and there is the C stack floating around there in the background when using the standard CPython distribution. IronPython may or may no deal with this issue specifically, but I can't say. There is always Stackless. Anyhow, this is something you need to look out for. Python doesn't have tail recursion, for example, so certain kinds of "typical" or "common" functional programming examples (fibo()
comes to mind) may present implementation difficulties.
I know Python far, far better than I know F# (as far as "functional" programming goes, I have little-to-moderate experience with PLT Scheme); and my largely uninformed opinion thus far is that F# falls largely in the same camp as Lisp, Scheme and the becoming-rapidly-popular Clojure. These are all fine languages, but you should be aware that working in them means that you are pretty much bound to the "functional programming paradigm" (OOP in Lisp does not look like OOP in any other language I've seen, regardless of what promoters may say). On the other hand, since you said you wanted to learn, with Python you can immediately compare and contrast functional-vs-OOP-vs-procedural all within the same syntax; and even in the same program. That's gotta be worth something.
Comic relief: the Y combinator in Python (ugliest valid Python you'll ever see):
fact = (lambda func:
(lambda f:
func(lambda x:
(f(f))(x)))(lambda f:
func(lambda x:
(f(f))(x))))(lambda f:
lambda n:
1 if n < 2 else n*f(n-1))
print fact(10)
>>>
3628800