Here's an example I -just- had, actually, in production code (not in OCaml; below is pseudocode). It's not super powerful, but it made me happy because it turned what would have been a good 30 minutes to refactor and re-test into a quick 1 minute task.
I had written a synchronous interface for some functionality, that had quite a bit of input data. It called an external web api twice, once to post some data, then a recursive check to periodically ping the API until some changes took effect (yes, none of this was ideal, but I couldn't change the API).
I later realized that the code calling this interface needed to do some work in between these two calls. To refactor it into two calls would be a lot of work, and require a lot of book keeping, passing variables around or recalculating them, etc, and bloat the code.
Instead, I just wrapped the second call in a closure, changing the interface; now rather than returning the result of that second function, it just returned that second function, which the calling code could invoke after it did its work.
That is, I went from
calling_func() ->
Val = interface();
...
interface() ->
...//Do stuff to calculate vars
do_work1();
do_work2(Var1, Var2, ...);
to
calling_func() ->
SynchFunc = interface();
...//Do whatever needs to happen between the two calls
Val = SynchFunc();
...
interface() ->
...//Do stuff to calculate vars
do_work1();
fun() -> do_work2(Var1, Var2, ...) end;
I could also have done (provided I just needed side effects, not values) -
calling_func() ->
Val = interface(fun() -> ... end);
interface(Func) ->
...//Do stuff to calculate vars
do_work1();
Func();
do_work2(Var1, Var2, ...);
to achieve the same effect, depending on how I want the interface to behave. I could also keep all existing calls working if my language supports multiple function arities, with
interface() -> interface(fun() -> pass; end)
or similar. The thing that closures give you, that I love, is that utility. I can minimally touch a function to inject entire chunks of functionality, without having to do major re-architecturing.
I had written a synchronous interface for some functionality, that had quite a bit of input data. It called an external web api twice, once to post some data, then a recursive check to periodically ping the API until some changes took effect (yes, none of this was ideal, but I couldn't change the API).
I later realized that the code calling this interface needed to do some work in between these two calls. To refactor it into two calls would be a lot of work, and require a lot of book keeping, passing variables around or recalculating them, etc, and bloat the code.
Instead, I just wrapped the second call in a closure, changing the interface; now rather than returning the result of that second function, it just returned that second function, which the calling code could invoke after it did its work.
That is, I went from
to