6

In F#, a tail recursive List.filter function can be implemented like:

let filter f =
    let rec filterImpl f acc = function
        | [] -> List.rev acc
        | h :: t -> filterImpl f (if f h then h :: acc else acc) t
    filterImpl f []

But it can also be implemented by a closure (i.e. without passing f explicitly into filterImpl)

let filter f =
    let rec filterImpl acc = function
        | [] -> List.rev acc
        | h :: t -> filterImpl (if f h then h :: acc else acc) t
    filterImpl []

What is the difference and which is preferred in F# or functional programming in general?

6
  • 4
    In your simple example, there may not be any material difference. You use a closure when you need the benefits a closure provides. Apr 5, 2016 at 15:07
  • @RobertHarvey, can you please explain a bit further what that benefit might be?
    – rexcfnghk
    Apr 6, 2016 at 14:58
  • In your simple example, there isn't one. Apr 6, 2016 at 15:00
  • Then in what case will it make a difference?
    – rexcfnghk
    Apr 6, 2016 at 15:02
  • 2
    For what it's worth, I see widespread closure use in Javascript and some other functional languages, especially the lisp-style ones. In both places, the ability to close over some local state is extremely important. Because of the way Javascript is constructed, the only way to get encapsulation of state is by wrapping it in a function. Closures allow you to return a function that has access to its local environment within another function. It takes a bit getting used to if you've never seen this kind of programming style. Apr 6, 2016 at 15:09

3 Answers 3

4

From the compiler's point of view, there's very little difference between a closed over variable and a function argument. They are just given to the function's symbol table at different times.

In general you would prefer the closure version, because it is simpler, but if it were a longer function, or shared by other functions, you might want to pull it out and just accept the extra parameter.

2

Afaic, at least in C#, at least sometimes behind the scenes a class is generated to store captured variables in it's fields. It is a significant overhead compared to stack allocation to pass parameter directly.

As of C#, Raymond Chen has excellent explanation of closures:

When faced with this “hard” type of anonymous method, wherein variables are shared with the lexically-enclosing method, the compiler generates a helper class

2
0

A closure is generally implemented as some data structure mixing code (e.g. a pointer to a routine) and data (the closed data, or environment).

Imagine that you implement a F# to C compiler. Then a closure is translated to a struct mixing a function pointer with more data.

Queinnec's Lisp In Small Pieces book explains that well.

Pitrat's book Artificial Beings, the conscience of a conscious machine also explains that well.

The Dragon book also explains that.

See also the RefPerSys project, which generates C code and has closures too.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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