5

All functional programming languages that I know of (e.g. Haskell, Scala, Scheme, Clojure, SML, OCaml, ...) support a notion of closures.

Also, I often read that a language X can be considered functional because it supports closures.

On the other hand there are programming languages that do have closures but are not considered functional. The best example I know of is Smalltalk: Smalltalk has blocks (which in most implementations behave like closures, see e.g. here) but it is considered a pure object-oriented language.

So, while closures are a very common (or even essential) construct in functional programming, are they really sufficient to characterize functional programming? If the support of closures is sufficient for considering a language functional, why isn't Smalltalk considered functional too?

Or is the notion of a closure orthogonal to both functional and object-oriented programming?

6
  • 3
    No. There are other types (non functional) of language that have closures. Jul 27, 2013 at 19:35
  • Can the downvoter explain what is wrong with this question so I can try to improve it?
    – Giorgio
    Jul 27, 2013 at 21:43
  • @Giorgio Indeed. That always annoys me, down-voting without saying why. StackExchange should force to leave a comment when down-voting.
    – Chiron
    Jul 28, 2013 at 0:18
  • 2
    @Chiron: Argued many many times and always rejected: meta.programmers.stackexchange.com/q/159/12917 Jul 28, 2013 at 0:35
  • 1
    Gilad Bracha's "Deconstructing Functional Programming" presentation tackles this question: infoq.com/presentations/… Jan 11, 2014 at 4:10

5 Answers 5

4

The hallmarks of functional programming languages:

  • Higher Order Functions. (Passing functions as parameters, storing functions in data structures, returning functions, creating functions at runtime).
  • Encouraging "Referential transparency".
  • And I would dare to say "Laziness".
  • Immutability

A functional programming language makes a heavy use of Functional Data Structures.

Having Closures doesn't mean the language is "Functional". Examples: Java 8 (if Lambdas are going to be added), Groovy and Objective-C,

Edit:
Based on the comment, I removed Memoization from the previous list.

Functional programming languages employs the "Memoization" technique because it is easier with Functional code.

8
  • 8
    Laziness is not a hallmark of functional languages. They form 1 branch of functional languages but CL, SML, OCaml, Scheme etc are all strict. Haskell and it's predecessors are the exceptions, not the rule Jul 27, 2013 at 20:45
  • 3
    Also, I'm a bit surprised by memoization. It's not like it's built into any major languages (not even Haskell, where it would be comparatively easy to do correctly). It's easier with functional code, but I don't think of it as a hallmark of functional programming. It's just one of many tools that fits the paradigm well, much like how in-place sorting fits imperative languages rather well.
    – user7043
    Jul 27, 2013 at 20:50
  • 1
    @jozefg: True about laziness, but it is pretty straightfoward to implement it in most functional languages (e.g. SML, Scheme) using closures to represent suspended computations.
    – Giorgio
    Jul 27, 2013 at 21:32
  • 2
    @Giorgio That's laziness. Memoization would be only evaling ` f 1 ` once in the entire program Jul 27, 2013 at 21:47
  • 2
    @user102008 "Encouraging referential transparency" would be more accurate. All the languages that I meant let you have mutiple variables, but don't encourage them like Ruby does Jul 28, 2013 at 12:07
3

Closures are orthogonal to FP. Really, all they are is a different way of looking at the same basic concepts as objects. If what's really important to you is the behavior, you use a closure. If what's really important is the state data, you use an object. A lot of OO languages these days offer ways to do both, but that doesn't make them "functional languages."

1
  • Well you can use data structures to store the data. Maps/Hashed are mainly used in functional programming languages as "objects".
    – Chiron
    Jul 27, 2013 at 19:55
3

Closures are certainly a major part of functional programming. However, there are many languages nowadays that support closures, and at least some level of functional programming, without being "functional languages". Examples include Perl, Python, JavaScript, C#, Java 8, Ruby, and others. Conversely, closures are apparently not completely necessary to functional languages, in that the first functional languages predated the invention of the closure. Early versions of Lisp used dynamic scope for all variables, so the notion of "closure" could not be expressed: a variable was bound in the scope when a function was called, not when the function was declared. That said, I believe that all modern functional languages do offer closures; I certainly can't imagine programming in a functional language without them!

1
  • +1 for mentioning that early versions of Lisp did not have closures (I am glad that Common Lisp does).
    – Giorgio
    Jul 27, 2013 at 21:40
1

The concept of a closure is not specific to functional programming. It simply means that you have:

  • A variable in a scope
  • Something constructed inside this scope (typically a function or an object) that uses said variable
  • That something being passed to somewhere outside the originating scope

The textbook example is something like this:

function foo() {
    var x = 23;
    var bar = function(y) {
        return x + y;
    };
    return bar;
}

...and we say that bar closes over x.

However, we can do the same with objects, really:

function foo() {
    var x = 23;
    var bar = {
        "y": x
    };
    return bar;
}

The mechanism is the same, even though now it is not a function that closes over x, but an object. It is not usually called a closure though, because unlike function closures, this kind of behavior is "obvious" for an imperative programmer, and the idea is that we're just referencing a local variable to put a value into an object -- but then, that's exactly what a closure does, only that the object can also be a function.

Now, as far as functional programming goes: The most important concept is the function. Unlike functions in imperative languages, for which "routine" or "procedure" is actually a much better name, functional-programming functions are conceptually like Mathematical functions: mappings from things to things. By taking this concept and using it as the first and foremost expressive primitive, the other hallmarks of functional programming follow logically:

  • Functions map inputs to outputs; that is all they do. Side effects such as printing or maintaining mutable state don't fit this model, so functional programmers tend to avoid these things. This is what people call purity: a pure function is a function that does not have side effects. Different FP languages treat this matter differently; at the extreme end, there is Haskell, which does not allow any impure functions at all, while at the pragmatic end, there are Lisp, Scheme, JavaScript etc., which allow side effects to appear anywhere and leave their avoidance to boyscout programmers.
  • Functions are things, too, so it makes sense to have functions that take functions as input, or return functions as output, or both. Such functions are known as higher-order functions, and their use is ubiquitous in functional programming. The famous map function is such a higher-order function: one of its arguments is a function, which map applies to every element in the other argument (which is supposedly a list of some sort).
  • Functions can be expressed in terms of themselves, a.k.a. recursion. Recursive definitions are easier to write in a pure fashion; they do not rely on mutable-state constructs such as loop counter variables. Because of this, functional programmers tend to prefer recursive solutions over iterative ones, and functional programming languages provide various optimizations to avoid the problems that recursive programming can cause (stack overflow, memory leaks, etc.). Further, common types of recursion are available in a generic fashion in every functional programming language worth the label, the most famous ones being map and reduce (a.k.a. fold). With the help of these functions, a functional programmer can abstract away the details of the actual recursion, and thinking in terms of map, reduce and filter becomes second nature at some point.
  • The preferred type of function is the unary function, which takes only one argument. Using closures, any n-ary function can be rewritten as a unary function that returns an (n-1)-ary function, and by fully applying this logic, any n-ary function can be written as a nested chain of unary functions returning the next link in the chain. This process is called currying, while the concept of calling a function with an incomplete set of arguments, yielding another function that takes the rest of the arguments, is known as partial function application. As a simple example, if you have a function that you can call like so: foo(a, b, c), then the fully-curried version would be called as: foo(a)(b)(c); calling the curried foo like this: foo(a)(b) constitutes partial application and yields a function which, when called with c, gives the same result as the original call, e.g.: f = foo(a)(b); f(c).
0

To characterize functional language, one key feature is currying:

  1. hom(AxB, C) == hom(A,C^B)

This is one of the most important features available in functional languages, because it allows adding a parameter to a function. Languages that only support left side of the ==, can't be considered functional.

11
  • Again: downvote without explanation. It should really be introduced as a rule that downvotes must be explained.
    – Giorgio
    Jul 28, 2013 at 15:38
  • 2
    Sorry, I am the downvoter. I disagree that currying is a prereq for functional languages, notably no lisps are curried. SML (sometimes OCaml) traditionally relies on Tuples, not currying. Erlang and Scala are not curried. Yes currying is cool, but it's definitely not the difference between functional and imperative. It's roughly the same as saying "all functional languages must use whitespace for function application" since otherwise the syntax for currying just sucks f(1)(2)(3) Jul 28, 2013 at 23:54
  • I am not sure if this is correct, but isn't this (scala-lang.org/node/135) currying in the sense intended by tp1? Also, as far as I know an imperative language cannot do currying because it cannot create a function like f(1)(2) on the fly.
    – Giorgio
    Jul 29, 2013 at 5:26
  • Anyway, the point of my question was: Is it correct to say "Language X is functional because it supports closures". From the feedback I got so far, the answer seems to be NO.
    – Giorgio
    Jul 29, 2013 at 5:30
  • @Giorgio Imperative languages can absolutely be curried, it's just the syntax looks terrible usually and so no one does it. And yes, closures =/> functional Jul 29, 2013 at 11:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.