Home > Programming > Zen and the art of statefulness

Zen and the art of statefulness

The venerable master Qc Na was walking with his student, Anton. Hoping to prompt the master into a discussion, Anton said “Master, I have heard that objects are a very good thing – is this true?” Qc Na looked pityingly at his student and replied, “Foolish pupil – objects are merely a poor man’s closures.”

Chastised, Anton took his leave from his master and returned to his cell, intent on studying closures. He carefully read the entire “Lambda: The Ultimate…” series of papers and its cousins, and implemented a small Scheme interpreter with a closure-based object system. He learned much, and looked forward to informing his master of his progress.

On his next walk with Qc Na, Anton attempted to impress his master by saying “Master, I have diligently studied the matter, and now understand that objects are truly a poor man’s closures.” Qc Na responded by hitting Anton with his stick, saying “When will you learn? Closures are a poor man’s object.” At that moment, Anton became enlightened.

Anton van Straaten

When I first read the above koan some time ago, I didn’t really understand it. I had a very basic idea of closures, but at the time they were just a syntactic oddity to me – something you could do a few cool things with, but not particularly useful. Since then I’ve worked through quite a bit of Structure and Interpretation of Computer Programs and delved into functional programming in JavaScript, which has given me a much deeper understanding of closures. On the other side of the divide, I’ve been doing a lot of Ruby programming, which has helped me grok objects a lot better. I now feel like I can begin to comprehend what the quote was getting at.

My moment of enlightenment came today while reading Test-Driven JavaScript Development and looking at the code for a JavaScript strftime function (abbreviated here for brevity):

Date.prototype.strftime = (function () {
  function strftime(format) {
    var date = this;

    return (format + "").replace(/%([a-zA-Z])/g, function (m, f) {
      //format date based on Date.formats

  // Internal helper
  function zeroPad(num) {
    return (+num < 10 ? "0" : "") + num;

  Date.formats = {
    // Formatting methods
    d: function (date) {
      return zeroPad(date.getDate());
    //various other format methods

    // Format shorthands
    F: "%Y-%m-%d",
    D: "%m/%d/%y"

  return strftime;

The above code uses an IIFE (Immediately-invoked function expression) to produce a function with additional data (if Date.formats was instead declared as a local variable, this would be a better example). If it doesn’t make sense, I thoroughly recommend Ben Alman’s post on IFFEs for an overview of the technique. The code executes, and returns a function. The important thing is that one function is used to define another function and its context.

In Ruby, when you define a class, the class definition is executed as Ruby code, unlike in Java, for example, where a class definition is just a syntactic construct read at compile-time, but not executed in the way other Java code is. A Ruby class definition is read at run-time, and builds up a new class as it is interpreted.

In a lot of ways, Ruby class definitions and JavaScript function-defining functions are equivalent. I’ll give you a little example to illustrate:


var Cat = function () {
  var age = 1;

  function catYears() {
    return age * 7;

  function birthday() {

  return {
    catYears: catYears,
    birthday: birthday

var powpow = Cat();
var shorty = Cat();

//yo shorty, it's your birthday:

alert(powpow.catYears()); // => 7
alert(shorty.catYears()); // => 14


class Cat
  def initialize
    @age = 1

  def cat_years
    @age * 7

  def birthday
    @age += 1

powpow = Cat.new
shorty = Cat.new

#yo shorty, it's your birthday:

puts powpow.cat_years # => 7
puts shorty.cat_years # => 14

Strictly speaking, in zen.js I’m returning an object, but the private data and methods of that object are saved in a closure. So, zen.js stores its state in a closure, while zen.rb stores its state in an object. Every time Cat() is called in zen.js, a new closure is created with a unique age. Every time Cat.new is called in zen.rb, a new object is created with a unique @age. (These two examples aren’t strictly equivalent – each cat in zen.js gets a new copy of the functions, whereas in zen.rb they share the same methods. It’s possible to make the JavaScript version function more like a Ruby class definition, but it takes a bit more code.)

Of course, there’s a lot you can do with JavaScript closures that you can’t do with Ruby objects. And there’s a lot you can do with Ruby objects that can’t be emulated using JavaScript closures. Any time you decide that one is better than the other, just imagine Qc Na hitting you with his stick.

Further reading

  1. February 12th, 2011 at 16:06 | #1

    Thanks for these nice biscuits. Question: How is it that the strftime() example is related to state? There don’t seem to be any internal state-full vars such that one would make use of a persisting instance. Also, can you explain what the self-instantiation does that wouldn’t occur if it were function(){…} instead of (function(){…})() ?

    Perhaps enlightenment will come for me tomorrow.

  2. February 12th, 2011 at 16:19 | #2

    @Michael Richardson Thanks. You’re right about the strftime() example – I meant to add “(if Date.formats was instead declared as a local variable, this would be a better example)” which I’ve done now. If instead of Date.formats = it said var formats = it would have been a better – then formats would have been held in the function’s closure. I mainly included that function because it was what set me off thinking about all this, but it’s not perfect for illustrative purposes!

    If it were function(){} then Date.strftime() would call the function that returns the inner strftime. If you wanted to actually call strftime you’d have to write Date.strftime()(). Immediately invoking the anonymous function causes it to execute at that point in the code and return the inner function, which is what is assigned to Date.strftime. Hope that all makes sense!

  3. February 13th, 2011 at 14:05 | #3

    This does make sense, yes. Kind of! Wall. Screen. Ceiling. Beginner’s mind… Still squinting at all this to see the relevance to statefulness. …. Okay. Reading Sensei Alman’s piece about it, now I see what you’re saying about a local var: It would give you the medium with which to keep Date.strftime() as a stateful (alive, subject to amending, incrementing, etc) component into which you could, say, add a new format provided by a user.

  4. February 13th, 2011 at 23:32 | #4

    @Michael Richardson Exactly. It’s really not a very good example – I just didn’t like the idea of saying “this certain bit of code made me suddenly understand” without actually quoting the code.

    If I was going to rewrite the code sample, I could add a add_format function that could add a new format to the formats object. Then you’d have your mutable state :)

  5. December 13th, 2012 at 21:11 | #5

    I am in fact happy to glance at this blog posts which contains lots of useful data, thanks for providing these data.

    Feel free to visit my web-site – [iphone repair specialist](http://Iphonerepairkl.Webs.com/ ” iphone repair specialist”)

  6. gamanegumanews.com
    December 31st, 2012 at 15:31 | #6

    “Skilldrick Zen and the art of statefulness” was in fact a terrific article, can not wait to read more of your blogs. Time to spend some time on the web hehe. Thank you ,Deandre

  7. June 7th, 2013 at 16:26 | #7

    Hello, just wanted to tell you, I enjoyed this blog post. It was funny. Keep on posting!

  8. July 4th, 2013 at 09:42 | #8

    You made some good points there. I looked on the internet to learn more about the issue and found most individuals will go along with your views on this website.

  9. July 26th, 2013 at 17:37 | #9

    Until now – now there are Weber Performance Grills that offer the best of both grilling worlds.

    You will find them so much in varying sizes that they come in the range from very small and light weight to close to home sized. When looking for gas grills on sale, the best brands to choose from are Weber, Char-Broil, Brinkmann, and Coleman.

    Stop by my page: [top rated gas grills](http://www.

    picowiki.com/josh7854/index.php/Portable Gas Grills- Weber Spirit Liquid Propane Gas Grill “top rated gas grills”)

  10. July 31st, 2013 at 04:48 | #10

    I know this if off topic but I’m looking into starting my own weblog and was wondering what all is required to get set up? I’m assuming having a blog like yours would cost a pretty penny? I’m not very internet savvy so I’m not 100% certain. Any recommendations or advice would be greatly appreciated.


  11. September 9th, 2013 at 03:03 | #11

    Hello everyone, it’s my first pay a quick visit at this web site, and piece of writing is really fruitful designed for me, keep up posting such content.

  12. September 12th, 2013 at 03:58 | #12

    Hi there I am so glad I found your site, I really found you by accident, while I was looking on Digg for something else, Nonetheless I am here now and would just like to say cheers for a fantastic post and a all round enjoyable blog (I also love the theme/design), I don’t have time to read it all at the moment but I have bookmarked it and also included your RSS feeds, so when I have time I will be back to read much more, Please do keep up the awesome b.

  13. September 13th, 2013 at 23:47 | #13

    I just purchased a used lenovo Y410p for $469.99 at and I recommend it.

    It was basically new; no scratches or anything. They ship worldwide for free and they accept Paypal. It’s the best deal I’ve found for this gaming laptop.

  14. September 29th, 2013 at 10:31 | #14

    If you want a thigh gap or simply just want to slim down your thighs, I recommend the Thigh Gap Magic program. Just do a search in Google, you will find it. It’s amazing!

  15. January 26th, 2014 at 21:10 | #15

    Wow, that’s what I was seeking for, what a data! present here at this weblog, thanks admin of this web page.

    Also visit my blog post – Watch House of Cards Season 2 Online Free ([http://houseofcardsseason2.Blogspot.com](http://houseofcardsseason2.Blogspot.com/ “http://houseofcardsseason2.Blogspot.com”))

  16. May 19th, 2014 at 02:26 | #16

    Greg: I haven’t used them being a resource, but I went along to their site and like what I see. Thus, the technology supports phenomenally and everything is going to be driven very close for the activities worldwide through.

    report [Main Page](http://is.gd/eFulsQ “Main Page”)

  17. June 5th, 2014 at 02:50 | #17

    asus laptop comparison

  18. August 22nd, 2014 at 20:28 | #18

    Thanks a lot for sharing this with all people you really recognize what you are speaking about! Bookmarked. Please also talk over with my website =). We can have a hyperlink change agreement among us

  19. September 1st, 2014 at 18:02 | #19

    It’s remarkable to pay a visit this web page and reading the views of all friends about this article, while I am also keen of getting know-how.

    Feel free to surf to my blog post; [Birthday](https://play.google.com/store/apps/details?id=com.liberumsoft.birthdaywishes “Birthday”)

  20. September 3rd, 2014 at 11:00 | #20

    Thesee days ɑn extra income іs needed to sustain ƴour family becauѕе of the continuing rise of prices ftom groceries tߋ уouг children’s education. Оne of the tɦings I ɗߋ іs eitɦеr take fresh tomatyoes օr canned tomatoes.

    F oven fοr 30-40 minutes, սntil internal temperature reacdhes 165.

  21. September 15th, 2014 at 08:53 | #21

    Every weekend i used to pay a visit this website, for the reason that i want enjoyment, since this this site conations really pleasant funny material too.

    Have a look at my web-site; [Google](http://www.ask.com “Google”)

  22. September 19th, 2014 at 11:04 | #22

    You should take part in a contest for one of the most useful websites online. I’m going to highly recommend this website!

  23. September 22nd, 2014 at 08:34 | #23

    I’d like to find out more? I’d care to find out some additional information.

  24. September 23rd, 2014 at 01:45 | #24

    Nice blpog here! Also yyour web sie loads up fast! What host are you using? Can I get your affiliate link to your host? I wish mmy web site loaded up as fast as yours lol

    my webpage; quote ([Graciela](http://klh.pl/conveyancingquote130882 “Graciela”))

  25. September 24th, 2014 at 15:16 | #25

    I’m not sure the place you’re getting your info, but good topic.

    I needs to spend a while studying more or figuring out more.

    Thanks for great info I used to be looking for this info for my mission.

    My weblog … [cwiczenia z podstaw marketingu](http://szkolniks.eu/v/ddaaw/cwiczeniazpodstaw_marketingu “cwiczenia z podstaw marketingu”)

  26. October 8th, 2014 at 03:12 | #26

    Hey, I think your website might be having browser compatibility issues. When I look at your blog site in Chrome, it looks fine but when opening in Internet Explorer, it has some overlapping. I just wanted to give you a quick heads up! Other then that, terrific blog!

  27. October 11th, 2014 at 09:20 | #27

    Very good write-up. I absolutely appreciate this site. Thanks!

  28. January 29th, 2015 at 01:06 | #28

    What a material of un-ambiguity and preserveness of valuable familiarity concerning unexpected emotions.

  29. February 3rd, 2015 at 03:54 | #29

    Langsung berikan aku dan kamu informasi uaruar terbaik lainnya ya cakap admin. dan semoga melulu dapat melahirkan sebuah kendaraan akan adanya informasi ini.

  30. February 8th, 2015 at 19:59 | #30

    I got this web page from my friend who shared with me regarding this web page and at the moment this time I am browsing this site and reading very informative articles or reviews here.

  31. February 26th, 2015 at 19:34 | #31

    Excellent write-up. I absolutely appreciate this site. Continue the good work!

  32. February 27th, 2015 at 15:43 | #32

    Great post. I used to be checking constantly this weblog and I’m impressed! Very helpful info specifically the last phase :) I take care of such info a lot. I was looking for this certain information for a very long time. Thanks and good luck.

  33. April 22nd, 2015 at 08:17 | #33

    Its not my first time to pay a visit this site, i am browsing this web page dailly and take pleasant data from here every day.

  34. May 3rd, 2015 at 09:33 | #34

    Thanks for another informative blog. Where else may I am getting that kind of information written in such an ideal approach? I have a mission that I am just now working on, and I have been on the look out for such info.

  35. June 3rd, 2015 at 21:48 | #35

    I’m not sure that i could done this, but i’ll try my best

  36. June 8th, 2015 at 21:07 | #36

    Hello my loved one! I want to say that this post is amazing, great written and include almost all important infos. I would like to peer extra posts like this .

  37. October 3rd, 2015 at 15:32 | #37

    Good article. I’m experiencing some of these issues as well..

  38. December 30th, 2015 at 09:58 | #38

    Heya outstanding website! Does running a blog similar to this take a massive amount work? I’ve absolutely no knowledge of coding however I had been hoping to start my own blog in the near future. Anyways, should you have any ideas or techniques for new blog owners please share. I know this is off subject but I just needed to ask. Thanks!

    My blog post: [sell bulk auto notes by wellspring](http://sociologicalyou.cybrok.com/groups/obtain-the-car-you-would-like-with-a-fantastic-price/ “sell bulk auto notes by wellspring”)

  1. February 12th, 2011 at 16:23 | #1
  2. February 13th, 2011 at 03:39 | #2
  3. August 15th, 2011 at 09:33 | #3
  4. April 23rd, 2013 at 00:20 | #4
  5. May 17th, 2014 at 09:29 | #5
  6. June 27th, 2014 at 04:39 | #6
  7. June 27th, 2014 at 07:07 | #7

Comments parsed as Markdown.