I wonder if the OP is aware that you can rebind the same name multiple 
times in a let. For instance

(let [x something
      y otherthing
      x (if (pred? x y) x (some-func x y))
      x (further (complex (calculations x)))
      ...]
  (do-something-with x))

No actual mutability, but most of the times that suffices for whatever you 
might use a mutable local for in another language.

Then there's loop/recur. I'd consider let rebinding and loop/recur long 
before resorting to any sort of mutable. The most significant pain point in 
my experience has been wanting to "smuggle" a side calculation out of some 
closure that has to return something else. The most recent case I ran into 
like that involved (swap! some-atom conj thingy) where the atom held a 
vector, I also wanted to know the new length of the vector, I didn't want 
any race conditions (following up with a (count @some-atom) allowed the 
possibility of the vector changing again in between the swap and the deref, 
but I wanted to know the position of the item just conjed on), and 
dosync/ref seemed like overkill (only the one isolated mutable). I *could* 
have done something like

(let [c (int-array 1)]
  (swap! some-atom (fn [x] (let [x (conj x thingy)] (aset c 0 (count x)) 
x)))
  (let [c (aget c 0)]
    ; work with c
    ...))

but it was unnecessary to use this kluge, for swap! returns not the atom 
itself but the new value that was returned by the passed-in function. So 
all I actually needed was

(let [c (count (swap! some-atom conj thingy))]
  ...)

with no mutability besides the atom itself (and in particular no local 
mutability). I've since needed swap!'s return value on another occasion, 
when it was a map, resulting in (get-in (swap! m update-in [k1 k2] f arg1 
arg2) [k1 k2]) to both update the map and have the exact value for the 
sub-key that was updated, as of that update. With maps, it may also be 
possible to store some extra information in the map with a 
::module-local-keyword without this interfering with anything else, which 
can be pulled out of swap!'s return value, and with several kinds of 
objects you can smuggle extra information out of a closure by adding a 
::module-local-keyword to the object's *metadata* (in particular, this 
won't perturb the equality semantics of the object, as well as working with 
vectors and several other non-map-like things as well as with records and 
maps. And if you're wanting to return extra information out of an ordinary 
function or a loop where you control how the return value is interpreted, 
you can bind and destructure the return value after making that a short 
vector or a map with several thingys in it.

Lately I hardly ever find myself feeling the need for any kind of local 
mutables, and only small amounts of global state (often nothing, or just 
one atom wrapping a map handled with nesting, update-in, assoc-in, and 
get-in, though refs and dosync will put in an appearance if a high degree 
of concurrency is required).

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to