@Jacob: If you get too many arguments in a loop I found it best to use a map.
(loop [{:keys [a b c] :as state} a-map] (cond (and (= a 1) (= b 2)) (recur (update state :a inc)) ;; 1.7+ only, otherwise use update-in ...)) Working with named arguments (vs. positional) is a lot more user-friendly since you don't have to repeat everything all the time. HTH, /thomas On Monday, November 10, 2014 8:21:57 AM UTC+1, Jacob Goodson wrote: > > Sometimes, when writing code that loops with a good bit of branching, it > can be quite annoying to stay immutable. > > (loop [way 1 > too 2 > many 3 > args 4 > makes 5 > things 6 > annoying 7] > (cond (and (= way 3) (= too 4)) (recur (inc way).... you get the point. > > Imagine about 14 different conditions under cond and this thing starts > looking like crap. I got around this with macros and pattern matching, > however, I do not think that this happens too often for many clojurians. > > On Saturday, November 8, 2014 11:49:42 PM UTC-5, Fluid Dynamics wrote: >> >> 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.