you do basically have to introduce a new name for the thing returned
from conj if you want to make use of it in your functional program. so
if you took an imperative program and turned it into super idiomatic
fp style, it could seem like there is suddenly a code bloat because
you need a ton of new variables.
but then you have to reconsider the approach of transforming sorta too
verbatim the imperative approach. e.g. in fp you'd want to use
something like a map rather than a for loop, as an overly simple
example of where the for loop would have re'def whereas the map
doesn't.
dunno if that made any sense - you are totally right about how this
can be a strange thing to "get", and it has been too long for me in
the imperative world, so i am not sure i even get it myself any more.
(so apologies if what i said turns out to be a misleading tub of poo.)
sincerely.
PS: and thanks for your asking about all this, it really helps other
folks think through things. (some folks might not need to as much as i
do, apologies to them for the ascii noise :-)
> You mentioned Actors. I would really like to help move Clojure in this
> direction. Once I have collected my thoughts more and done some more
> research I will post some ideas and perhaps we can get a discussion
> going about making this a reality.
I can't say i was the first to think of this, but i've been thinking
about how to integrate clojure and kilim[1]. At the moment i don't know
much about ASM, but it may not be too difficult to integrate the two
systems.
sRp
1| http://www.malhar.net/sriram/kilim/
> After reading Rich's essay on State I considered that maybe one could
> write retro-games using refs?
I think it's the way to go — thinking of it, if you were doing something
more ajaxy with heavy use of comet, in some cases agents may be used
instead of refs. Maybe.
> Assume for the purposes of this
> discussion that the retro-games website only has one user so
> concurrent access to the *games* structure isn't a concern. Would one
> still write the program using refs?
I would. I tend to use:
* vars for short-lived mutation, mainly as a way to convey contextual
data (eg current output stream, db connection, user data etc.)
* refs for synchronous long-lived mutation (ie for things that have to
be remembered between (functional) processings)
* agents for asynchronous long-lived mutation
This is how I use/understand Clojure's features, others may disagree. HTH
Christophe
--
Clojure and me http://clj-me.blogspot.com/
On the contrary, in Clojure especially refs but even agents are rather
pedestrian, and you're very likely to run into problems that can't be
solved without them. But it turns out they're pretty easy to use.
So go ahead and def your global *games* as a ref:
(def *games* (ref []))
And you can even have your add-game function, just use ref-set instead
of def, use an @ when you're reading the old value, and put it all in
a dosync:
(defn add-game [name]
(dosync
(ref-set *games* (conj @*games* {:name name :votes 0}))))
Or even better, use commute:
(defn add-game [name]
(dosync
(commute *games* merge {:name name :votes 0})))
And if you ever want to go massivly multi-threaded, you're already all
set.
BTW, you probably want to use a hash or map instead a list or vector
for *games*.
--Chouser