| author | Alan Dipert
<alan@tailrecursion.com> 2026-11-11 03:04:58 UTC |
| committer | Alan Dipert
<alan@tailrecursion.com> 2026-11-11 03:04:58 UTC |
| parent | fb4bc13d889a392ecc5dc06104274699f92dc72f |
| md/_MutableLocals.md | +3 | -3 |
diff --git a/md/_MutableLocals.md b/md/_MutableLocals.md index 84dabd5..869b6d8 100644 --- a/md/_MutableLocals.md +++ b/md/_MutableLocals.md @@ -4,7 +4,7 @@ I've been thinking about mutable local variables in Clojure. Hear me out. I like Clojure's immutable values. But sometimes I'm reading an algorithm in pseudocode, Java or C, and I'd like to port it without translating its local variables into atoms or `loop`/`recur`. -For example, this counts inversions in a vector: pairs where an earlier element is greater than a later one. +Here's an example using `loophole`, a macro provided by my Clojure library, [Blacktide](https://tailrecursion.com/repos/r/blacktide.git/). It counts inversions in a vector: pairs where an earlier element is greater than a later one. ```clojure (require '[com.tailrecursion.blacktide :refer [loophole setq label goto]]) @@ -25,7 +25,7 @@ Clojure already updates [JVM local-variable slots](https://docs.oracle.com/javas [`recur`](https://clojure.org/reference/special_forms#recur) evaluates its arguments, rebinds the loop locals, and starts the loop body again. [Clojure's compiler](https://github.com/clojure/clojure/blob/clojure-1.12.6/src/jvm/clojure/lang/Compiler.java#L7156-L7227) emits local-variable stores and a jump. We can write assignments and jumps where we want them, then compile them into Clojure that does the updating through `recur`. -Blacktide's `loophole` macro does this for a subset of Clojure. It's a compiler inside a macro, with no atoms or changes to Clojure's compiler. Mutable locals to the people. +`loophole` does this for a subset of Clojure. It's a compiler inside a macro, with no atoms or changes to Clojure's compiler. Mutable locals to the people. ## Compiling to a state machine @@ -179,7 +179,7 @@ When the index reaches five, the inner `if` returns the sum: 10. That was our `g ## Back to the inversion counter -Back at the inversion counter, we can write `(setq n (inc n))` where the counting happens, inside the nested loops. [`loophole`](https://tailrecursion.com/repos/r/blacktide.git/b/master/t/f=README.md.html) figures out the bindings and `recur` arguments needed to carry that value forward. Our assignment becomes the kind of update Clojure already knows how to compile. +Back at the inversion counter, we can write `(setq n (inc n))` where the counting happens, inside the nested loops. `loophole` figures out the bindings and `recur` arguments needed to carry that value forward. Our assignment becomes the kind of update Clojure already knows how to compile. To think, all this time, mutation was sitting inside `recur`, wearing a little hat that said FUNCTIONAL PROGRAMMING...