Using generators and lambda, we can do functional programming with Python. You can also achieve the same thing with Ruby.

So the question is: why do we need specific functional programming languages such as Erlang, Haskell, and Scheme? Is there anything different that these specific functional programming languages provide? Why can't we just use Python for functional programming?

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
If this question can be reworded to fit the rules in the help center, please edit the question.

28

all of those were around even before python was created
–
Mahmoud HossamFeb 2 '11 at 23:50

48

A ford Pinto is a car. Why do we need specific fast cars like Ferraris?
–
Loki AstariFeb 2 '11 at 23:57

10

Using classes and templates, we can do anything OO in C++. Why Java and Python were ever created? What do they add?
–
9000Feb 3 '11 at 3:40

17

All programming languages (sans some purely academic research languages) are Turing equivalent, so what you can do in language A you can do in any other language. So, following this train of thought, we only need one Turing complete language -- say like sendmail.cf ;) okmij.org/ftp/Computation/#sendmail-Turing
–
MaglobFeb 3 '11 at 9:56

15

If you knew any of these languages, you wouldn't claim that Python does functional programming well. It doesn't. It does it well enough to incorporate a share of FP-ish things, but not any better.
–
delnanFeb 3 '11 at 15:35

11 Answers
11

I appreciate the question, because I'm personally a huge fan of both Python and functional style of programming. I have a long background in Python and I have started learning Haskell recently, so here's some points based on my personal experiences on the differences between these too languages, from a functional perspective.

Purity

Even if you don't care about the purity of functions (i.e. not having side effects) as a princible, it does have practical effect on how easy it is to read code and reason about it. Even if you maintain purity in your own Python functions, there is a big difference in having the compiler enforce purity and, most of all, having the standard library built on terms of purity and immutable data structures.

Performance

You may or may not care about performance depending on what your application domain is, but static typing and guaranteed purity gives the compiler a lot more to work with, compared to Python and other dynamic languages (although I have to admit that PyPy is making great inroads, and e.g. LuaJIT is bordering on miraculous).

Tail-call Optimization

Related to performance, but slightly different. Even if you don't care too much about runtime performance, not having tail-call optimization (especially for tail-recursion) limits the ways you can implement algorithms in Python without hitting stack limits.

Syntax

This is the biggest reason why I started to look at "real" functional languages instead of just using Python with functional style. Although I think that Python has a very expressive syntax in general, it has some weak spots specific to functional coding. For example:

Syntax for lambda functions is rather verbose and limited in what they can contain

No pattern matching or guards for function arguments, which make it easy to express recursion end conditions and some border cases with very readable syntax.

Brackets are never optional for function calls, and there's no syntactic sugar for nested calls. I guess this is a matter of taste, but especially in functional code, I find it's common to chain function calls and I find y = func1 $ func2 $ func3 x easier to read than y = func1(func2(func3(x))), once you are familiar with that notation.

tail recursion (this can be found in some non-functional languages too)

Also, you should have a look at languages from the ML family like SML, Ocaml and F# and Scala, which fuses OO and functional programming in a new way. All these languages have unique interesting features.

+1 good post. You could add type-inference on Haskell and Light-weight processes on Erlang.
–
JonasFeb 3 '11 at 23:18

1

Python does have map, filter and fold (reduce). Regarding "real closures": If you define a real closure as a closure which can contain something other than a single expression, Haskell doesn't have real closures either (but of course Haskell has few things that aren't expressions...). However the point about immutable data structures is a good one, so +1 for that. Also: tail recursion (and generally less expensive recursion).
–
sepp2kFeb 5 '11 at 1:53

2

+1 for "static typing ensures functions are pure". It's very cool to have a type system that discriminates between pure and non-pure functions. (C++'s const doe snot count. :)
–
MackeFeb 9 '11 at 10:10

1

@btilly: I wouldn't consider it a closure if you can't assign to a variable that is in scope. Otherwise we'd have to say that Java has closures too, since you can use the same trick there.
–
KimFeb 11 '11 at 19:59

2

In a closure I can access a variable in the same ways I normally can. This is true of Haskell's and Ruby's closures, but not of Python's or Java's poor substitutes. Maybe someone else can enlight us about erlang, I don't know it that well.
–
KimFeb 11 '11 at 21:53

It's hard to define exactly what a "functional language" is--out of the languages you listed, only Haskell is purely functional (all the others adopt some sort of hybrid approach). There are certain language features that are very helpful for functional programming, though, and Ruby and Python don't have enough of them to be very good environments for FP. Here is my personal checklist, in order of importance:

Guaranteed tail-call optimization (Erlang, Haskell, and Scheme have this, but not Python, Ruby, or Clojure (yet)).

Support for immutability in the language and standard libraries (this is a big one that all of the "functional languages" you listed have (except Scheme) but Ruby and Python don't).

Language-level support for referentially transparent (or pure) functions (as far as I know, only Haskell has this currently).

The need for (1) should be obvious--higher-order functions are extremely difficult without first-class functions. When people talk about Ruby and Python being good languages for FP, they are usually talking about this. However, this particular feature is necessary but not sufficient to make a language good for FP.

(2) has been a traditional necessity for FP ever since Scheme was invented. Without TCO, it is impossible to program with deep recursion, which is one of the cornerstones of FP, because you get stack overflows. The only "functional" (by popular definition) languages that don't have this are Clojure and Scala (because of limitations of the JVM), but Clojure has a variety of hacks to simulate TCO and it will definitely incorporate it once it's supported by the JVM. (FYI, Ruby TCO is implementation-specific, but Python specifically does not support it.) The reason TCO has to be guaranteed is that if it is implementation-specific, deep recursive functions will break with some implementations, so you can't really use them at all.

(3) is another big thing that modern functional languages (especially Haskell, Erlang, Clojure, and Scala) have that Ruby and Python don't. Without going into too much detail, guaranteed immutability eliminates whole classes of bugs, especially in concurrent situations, and allows for neat things like persistent data structures. It's very difficult to take advantage of these benefits without language-level support. (As far as I can tell, this is the only significant difference between Ruby and Scala in terms of "functionalness.")

(4) is, for me, the most interesting thing about purely-functional languages (as opposed to hybrid languages). Consider the following extremely simple Ruby function:

def add(a, b)
a + b
end

This looks like a pure function, but because of operator overloading, it could mutate either parameter or cause side effects such as printing to the console. It's unlikely that someone would overload the + operator to have a side effect, but the language gives no guarantees. (The same applies to Python, although maybe not with this specific example.)

In a purely functional language, on the other hand, there are language-level guarantees that functions are referentially transparent. This has numerous advantages: pure functions can be easily memoized; they can be easily tested without relying on any sort of global state; and values within the function can be evaluated lazily or in parallel without worrying about concurrency issues. Haskell takes full advantage of this, but I don't know enough about other functional languages to know if they do.

All that being said, it's possible to use FP techniques in almost any language (even Java). For instance, Google's MapReduce is inspired by functional ideas, but as far as I know they don't use any "functional" languages for their large projects (I think they mostly use C++, Java, and Python).

@kRON: Well, the type system is an important property of a language, and he asked "Is there anything different that these specific functional programming languages provides?". Sure, you can use the Actor model with other languages but Erlang has it built-in in the language. Erlang uses lightweight processes and has built-in language constructs for distributed programming - thence a "concurrent" language.
–
JonasFeb 3 '11 at 0:23

So indeed we don't absolutely need Erlang, Haskell, Scheme, or any specific programming language, but they all represent different approaches and different trade-offs, making some tasks easier and some harder. What you should use depends on what you want to achieve.

A functional programming language isn't a language that permits functional programming. If we were to go by that definition, then pretty much any language anywhere is a functional programming language. (The same applies to OOP, incidentally. You can write in an OOP style in C if you like. Thus, according to your logic, C is an OOP language.)

What makes a functional programming language isn't what it permits you to program like, it's what it lets you program like easily. That's the key.

So, Python has lambdas (which are incredibly anaemic closure-like affairs) and gives you a couple of library functions that you'll see in functional libraries as well like "map" and "fold". This is not enough to make it a functional programming language, however, because it is difficult to impossible to consistently program in a proper functional style in it (and the language certainly doesn't enforce this style!). At its core Python is an imperative language concerned with state and state manipulation operations and this is simply at odds with the expression and expression evaluation semantics of a functional language.

This question can be applied to an infinite number of languages and paradigms.

Since everyone uses C++, why do we need any other general purpose languages?

Since java is such a great OO language, why do other OO languages exist?

Since perl is an amazing scripting language, why do we need python?

Yatta, yatta, yatta

Most, if not all languages exists for a specific reason. They exist because someone had a need that no current language filled, or filled poorly. (This of course doesn't apply to every language, but I feel it applies to most of the well known languages.) For example, python was originally developed to interface with the Amoeba OS [1,2] and Erlang was created to help in the development of telephony applications [3]. So one answer to the question "Why do we need another functional language?" can simply be, because [insert-name-of-someone-who-knows-how-to-design-languages] didn't like the way python did it.

That pretty much sums up what I think the answer is. While you can do anything with python that you can do with a functional language, would you really want to? Everything you can do in C, you can do in assembly, but would you want to? Different languages will always be best at doing different things, and that's the way it should be.

Functional programming is as much about a design paradigm as it is about specific language features. Or, put another way, lambdas and a map function do not a functional programming language make. Python and Ruby have some features inspired by functional programming languages, but you still generally write code in a very imperative fashion. (It's sort of like C: you can write OO-like code in C, but no one seriously considers C to be an OO language.)

Look: functional programming is not just about lambdas, or map, or higher-order functions. It's about design. A program written in a "true" functional programming language solves problems via the composition of functions. While programs written in Ruby or Python may use FP-like features, they generally don't read like a set of composed functions.

Each functional language you mentioned fits into a certain niche quite well and the idiomatic patterns that each encourages makes them very well suited for certain tasks that would be impossible to accomplish in Python unless you built a huge library of helper modules. The most obvious of one such niche excellence is Erlang's model of concurrency. The other ones also have similar strengths.

Every concept available in lambda-calculus, LISP, and Scheme is available in Python, so, yes, you can do functional programming in it. If it's convenient or not is a matter of context and taste.

You can easily write a LISP (or other functional language) interpreter in Python (Ruby, Scala) (what does that amount to?). You can write an interpreter for Python using purely functional, but it would take a lot of work. Even "functional" languages are multi-paradigm nowadays.

@Arkaaito But do you agree that every concept available in lambda calculus, LISP, and Scheme is available in Python?
–
Mark CFeb 3 '11 at 17:16

Are you sure that every lisp concept is available in Python? Macros, code-is-data?
–
SK-logicFeb 3 '11 at 19:28

@SK-logic Macros are not in lambda-calculus, but yes, they are available in Python, though not by that name. Python provides an eval() function, which is that's needed for code is data, but it goes further: it lets you modify most of the runtime environment, like in LISP.
–
ApalalaFeb 16 '11 at 21:11

@Apalala, dynamic languages eval() is a runtime metaprogramming. Sometimes it is useful, but it is extremely expensive. Lisp macros are different, it is a compile time metaprogramming. It is not available in Python in any usable form.
–
SK-logicFeb 16 '11 at 22:28

Because Python can also program in a non-functional style, and that's not good enough for the FP purist. More pragmatic coders, though, can enjoy the benefits of functional style without being dogmatic about it:

“The functional programmer sounds
rather like a medieval monk, denying
himself the pleasures of life in the
hope that it will make him virtuous.
To those more interested in material
benefits, these “advantages” are not
very convincing. Functional
programmers argue that there are great
material benefits … [but] this is
plainly ridiculous. If omitting
assignment statements brought such
enormous benefits then FORTRAN
programmers would have been doing it
for twenty years. It is a logical
impossibility to make a language more
powerful by omitting features, no
matter how bad they may be.”

Mason, the paper you are citing is telling the exact opposite. Your citation is just a fragment of a couple of paragraphs of a paper that tells a different story. In fact, if you cited both paragraphs as a whole, they would clearly show another meaning.
–
Marco MustapicFeb 7 '11 at 15:39

2

@Mason: yes, the author claims modularization and lazy evaluation are the true benefits. But note how your original quote was out of context -- you seem to suggest the author is claiming something against FP, when in fact you quoted a paragraph from a paper with the conclusion that FP is great, just not for the misleading reason of "less is more". The title of the paper shows the intent of the author pretty clearly: "why functional programming matters" ;-) It certainly doesn't support your claim that the purer FP languanges "are a nuisance".
–
Andres F.Feb 7 '11 at 17:06

5

@Mason Wheeler: Hybrid languages predate Python by a loooooong stretch. Lisp, for example, dates to 1959 and is, in fact, a multi-paradigm language. It fully supports functional approaches, procedural approaches and object-oriented approaches to programming. With the right macro packages on top you can also do logic programming pretty easily too. Scheme, too, predates Python (and this paper). It goes back to 1975. Maybe you should take a glance at this timeline of programming languages sometime.
–
JUST MY correct OPINIONFeb 10 '11 at 9:14