gensym = function() { gensym.count = gensym.count + 1; return "_gensm_" + gensym.count; }; gensym.count = 0; Bindings = function() { }; Bindings.prototype.unify = function(x, v) { if (this.hasOwnProperty(x) && x != v) throw "unable to unify"; this[x] = v; }; tryCatch = function(t, c) { var w = world.sprout(); try { in w { t(); } } catch (e) { w = null; c(); } finally { if (w != null) w.commit(); } }; father = function(x, y, bs, k) { tryCatch(function() { bs.unify(x, "abe"); bs.unify(y, "homer"); k(bs) }, function() { tryCatch(function() { bs.unify(x, "homer"); bs.unify(y, "bart"); k(bs) }, function() { tryCatch(function() { bs.unify(x, "homer"); bs.unify(y, "lisa"); k(bs) }, function() { }); }); }); }; // The tryCatch here is not really needed, since the only side // effect grandfather does on its own is in gensym, which // we don't care about. grandfather = function(x, y, bs, k) { tryCatch(function() { var z = gensym(); father(x, z, bs, function(bs) { father(z, y, bs, k) }) }, function() { }); };