5

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?

  • 4
    In your simple example, there may not be any material difference. You use a closure when you need the benefits a closure provides. – Robert Harvey Apr 5 '16 at 15:07
  • @RobertHarvey, can you please explain a bit further what that benefit might be? – rexcfnghk Apr 6 '16 at 14:58
  • In your simple example, there isn't one. – Robert Harvey Apr 6 '16 at 15:00
  • Then in what case will it make a difference? – rexcfnghk Apr 6 '16 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. – Robert Harvey Apr 6 '16 at 15:09
3

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

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.