probmods / webchurch

A Church to Javascript compiler (DEPRECATED)
Other
140 stars 15 forks source link

Variable hoisting lets through subtle reference errors #68

Open longouyang opened 9 years ago

longouyang commented 9 years ago

In this code, A is defined before B, but doesn't cause a ReferenceError:

(define samples
 (mh-query 1000 10
    (define A (if B #t #f))
    (define B (flip))
    A
    B)
)
(hist samples "A")

And the resulting conditional distribution always has A = false, which is unintuitive.

The problem is that the JS we compile to looks like this:

(function () {
      var A = B ? true : false;
      var B = Math.random() > 0.5;
      return A
})()

JS does variable hoisting, which means that B always exists throughout the function body but it may not have a value. Indeed, at the first line, B's value is undefined, which is falsy in JS, and leads to A being false.

We might fix this issue by generating code with a ton of nested closures, e.g.,

(function () {
      var A = B ? true : false;
      (function() {
        var B = Math.random() > 0.5;
      })()
      return A
})()

But this would likely degrade performance