Arc Forumnew | comments | leaders | submitlogin
3 points by conanite 5582 days ago | link | parent

I believe the strange behavior palsecam discovered is actually correct.

I believe the behaviour isn't even strange. Inside your for loop, (thread ...) creates a closure which references i, and when the closure is invoked, it looks up the current value of i, which has in the meantime changed.

  (def test-strange-behaviour ()
    (let fns (accum x
      (for i 0 10 (x (fn () (prn i)))))
    (each f fns (f))))

  (test-strange-behaviour) ; displays "11" 10 times
javascript has the same behaviour:

  <script type="text/javascript">
  var fns = [];

  function strange() {
    for (var i=0; i<3; i++) {
      fns[i] = function () { alert(i); }
    }

    for (var j = 0; j < 3; j++) {
      fns[j]();
    }
  }

  strange(); // alerts "3" 3 times
  </script>
The workaround is to outsource the closure-creation to another function:

  (def loop-work (i)
    (fn () (prn i)))

  (def no-strange-behaviour ()
    (let fns (accum x
      (for i 0 10 (x (loop-work i))))
    (each f fns (f))))

  (no-strange-behaviour) ; displays 0 up to 10
This works because now the closure references the i that belongs to the invocation of loop-work that created the closure; nothing modifies that i. The strangeness has nothing to do with threads; it's only about closures.