On Fri, Jul 22, 2011 at 8:47 AM, octopusgrabbus <octopusgrab...@gmail.com> wrote: > > On Jul 21, 10:15 pm, Ken Wesson <kwess...@gmail.com> wrote: >> On Thu, Jul 21, 2011 at 10:13 PM, Ken Wesson <kwess...@gmail.com> wrote: >> > On Thu, Jul 21, 2011 at 8:36 PM, octopusgrabbus >> > <octopusgrab...@gmail.com> wrote: >> >> And do you have a suggestion for a functional way? > > Is all-csv-rows being re-bound with the results of [] and then > returned as the function's value?
Not really. Nothing's being rebound. But reduce is good for tasks that amount to accumulating a result while looping over a collection. (reduce + 0 [3 1 7 2 9]) gives 22 because it starts with 0, then adds 3, then adds 1, then adds 7 ... and (reduce conj [] [1 6 9 5 7]) would produce [1 6 9 5 7] by taking an empty vector, generating a vector [1] from it, then a vector [1 6], etc., and returning the end result. In both cases the objects are not changing; 0 doesn't become 3 and then 4 and [] doesn't become [1] and then [1 6], rather, a reference to 0 is replaced with a reference to 3 and then one to 4, and a reference to [] with a reference to [1] and then one to [1 6]. The final reference gets returned. Locals aren't being rebound, though; if you stuck a (println all-csv-rows) in there it would emit the same thing the function got as parameter. A (println param-vec) inside the (fn ...) would show changing values, but only because each time the fn got called it got called with a different value as first argument. During the course of a single run of the fn, param-vec isn't being rebound either. But the effect is similar to an old-fashioned Java mutating loop like: List paramList = new ArrayList(); for (Row v : allCSVRows) { ... paramList.add(something); } return paramList; but without the potential issues of having mutable state. The immutable vectors make it closer to List paramList = Collections.unmodifiableList(new ArrayList()); for (Row v : allCSVRows) { ... paramList = Collections.unmodifiableList(new ArrayList(paramList).add(something)); } return paramList; but the persistent nature of Clojure vectors makes the copying step much more efficient than copying the ArrayList above would be, due to structure sharing. But then there's the immutable local variables, so conceptually we aren't even mutating the local paramList to point to new List instances. With Java you'd have to use a recursive function with no TCO to do this. In Clojure, conceptually that's what we do do, with (fn [x y] ... (recur a b)) or (loop [x 1 y 2] ... (recur a b)) and the latter conceptually a shorthand for ((fn [x y] ... (recur a b)) 1 2) and (recur) just the same as calling that enclosing function, only with TCO. But the JVM doesn't really let you do this, so under the hood it compiles to bytecode that uses mutating locals like paramList above to carry the parameters through the recursion. But this mutation is never exposed to the programmer! You can trust that param-vec will behave as an immutable local for the duration of the fn or loop body, and when it is "mutated" you're conceptually in a different invocation of the (in the loop case, itself conceptual) function. > And again, thanks. This is exactly > what I was looking for. You're welcome. -- Protege: What is this seething mass of parentheses?! Master: Your father's Lisp REPL. This is the language of a true hacker. Not as clumsy or random as C++; a language for a more civilized age. -- 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