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.