evan_tech

Previous Entry Share Next Entry
A common pattern in functional languages is attaching some mutable state to a function that needs to exist across calls. (Like static local variables in C.) You could just make the state a global variable alongside the function, but you can hide it in a cute way.

The idea is you write a function that has the state as a local variable, then return a closure holding that variable. It's harder to explain in text than it is in code:
# let at_most n f =
    let count = ref 0 in  (* "ref" is ml for "mutable" *)
    fun x ->
      if !count < n then (incr count; f x)
                    else ()
  ;;
val at_most : int -> ('a -> unit) -> 'a -> unit = <fun>

(* and demonstration: *)
# let say_hi () = print_endline "hi";;
val say_hi : unit -> unit = <fun>
# let limited_say_hi = at_most 2 say_hi;;
val limited_say_hi : unit -> unit = <fun>
# limited_say_hi ();;
hi
- : unit = ()
# limited_say_hi ();;
hi
- : unit = ()
# limited_say_hi ();;
- : unit = ()
(* ... it ran twice, so it will no longer
   produce any output. *)


It occurred to me that this would be pretty useful in JavaScript, especially when you're doing alert()-based debugging. The problem you often run into is that you want to alert() inside of a loop to see a value but if you let the loop go you get an endless cascade of popups.

function at_most(n, f) {
  var i = 0;
  return function(x) {
    if (i++ < n) f(x);
  };
};
var aler = at_most(3, alert);

(I can't promise I got the JS-closure-fu right, but it seems to work.) I can now sprinkle calls to aler(...) throughout my code and it'll never bring up more than three popups.