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

Reply via email to