Function-scope state in JavaScript

I needed to write some JavaScript that toggles its output. In Scheme it looks like this:

(define img-toggler
  (let ((down? #t))
    (lambda ()
      (if down?
          (begin (set! down? #f)
                 "right.gif")
          (begin (set! down? #t)
                 "down.gif")))))

JavaScript doesn’t have `let’ expressions, so I wrote an approximation of one:

var let = function(state) {
  var cb = new (function(state, args){
    this.state = state;
    this.call = function() { 
      var ret = null;
      for(var i = 1; i < args.length; i++)
        ret = args[i](this.state); 
      return ret;
    }
  })(state, arguments);
  return function() { return cb.call() };
};

And used it like this:

var imgToggle = let({on: true},
    function(state) {
      state.on = !state.on;
      if (!state.on) return 'right.gif';
      else return 'down.gif';
    });
Advertisements

5 Comments

  1. Brian Guthrie
    Posted July 24, 2007 at 12:49 pm | Permalink

    Neat. Is that the clearest possible way of expressing the purpose of that code?

  2. Posted July 24, 2007 at 3:01 pm | Permalink

    It’s certainly the clearest I could come up with at the time. I wanted a function that yields one of two results, alternating, each time it’s called.

    I guess another option is an infinite list of alternating results and a generator that produces the next result in that list; this would still require state, and the state should still be encapsulated in just the method.

    Since JavaScript is a prototype-based object language you’re always going to add the state to the object; I suppose this is an indirect way to do it, only useful if only one method needs access to the state.

  3. Roger Gonzalez
    Posted April 12, 2008 at 4:12 pm | Permalink

    On the one hand, kudos. That’s very clever.

    On the other hand, you’re writing sixteen lines of byzantine code that barely even warrants a dedicated function.

    var wibble = function()
    {
    return (this.state = !this.state)? “a” : “b”;
    }

    If I were your coworker, I’d want you dead.

  4. Posted May 27, 2008 at 9:09 pm | Permalink

    njizxyt mlrx glbf

  5. Posted May 31, 2008 at 12:11 am | Permalink

    aegsl vbuifoq


%d bloggers like this: