> I'm a little confused over when to use a var vs. a ref vs. an agent > vs. an atom. For writing small (<200 lines) single-threaded programs > when do I want to use each one?
Vars are intended for global data that is not normally modified, except that they can be re-bound thread-locally. http://clojure.org/special_forms#def At the end you will see the recommentation: "Using def to modify the root value of a var at other than the top level is usually an indication that you are using the var as a mutable global, and is considered bad style. Consider either using binding to provide a thread-local value for the var, or putting a ref or agent in the var and using transactions or actions for mutation." Probably the most common use of vars is to refer to functions. The fact that their values can be changed means that you can re-load code and have new function definitions take effect during runtime; so there is an inherent desire to allow such mutations. This use is pretty similar to a shared global variable in C/C++/Java. The other common type of use is thread-local re-binding. So for example, standard out is *out* in clojure: user=> *out* #<OutputStreamWriter java.io.outputstreamwri...@688a548b> And you can thread-locally re-bind this without modifying it's global root binding: (binding [*out* (open-some-file)] (println "this will be printed to the file instead of stdout")) Doing so never affects other threads, and so covers a common use case of C/C++/Java style shared globals, except that you can safely override their values without the usual pitfalls. Atoms are for anything that you need to mutate atomically but without co-ordination. One example is a counter that keeps some kind of statistic: (def request-count (atom 0)) ... (swap! request-count inc) Here the request-count var is shared, but it's value is an atom which can be efficiently (relative to e.g. a ref) incremented by multiple threads without co-ordinating their access to the atom. Atoms are described here: http://clojure.org/atoms Refs are intended for mutation within transactions (and they enforce that fact); typically they are used when you need to update multiple things atomically, or an update is dependent on one or more reads of other refs. They are described here: http://clojure.org/refs Agents are described here: http://clojure.org/agents > Also, since you can use def to change a binding how do I know for sure > that some function is not generating side-effects? There is no guarantee; clojure does not try to provide a hard guarantee that no side-effects happen when you call some arbitrary function whose implementation you don't know or trust. However modification of shared state is very different from the usual local bindings used in clojure, that you do not easily do so by 'mistake'. > I mean if it's my > code I can be somewhat confident about what it's doing, but if it is a > blackbox function how can I trust it? A very crude example would be > something like: > (defn square [n] > (def x n) > (def n 6) > (* x x)) > > I've ran that in the repl and it doesn't change the values of what is > passed to it, but is the same true for multithreaded apps? What if > between (def n 6) and (* x x)) a different thread requested the value > of n? Basically, I want to know when is immutability guaranteed? (def..) always affects the global root binding, and is almost never used within functions like that (see the quote further above). Function-local (and thread-local) re-bindings are done using (binding ...), and is comparatively uncommon. Most code would be using (let ..) for your run-of-the-mill local variables and only start using refs/atoms/agents when there is a specific reason to do so (for example, some kind of shared cache like a connection pool). > What is a form? In this overview of clojure, it talks about bindings > and forms. The fragment that I am trying to understand is "The let > special form creates bindings that are local to that form". > http://java.ociweb.com/mark/clojure/article.html#Bindings Someone may provide a better formal definition, but a form is essentially "clojure code". In the context of the sentence above about let, the first use of 'form' refers to the use of let itself. I.e., this is a let form which evaluates to 5: (let [x 5] x) I'm not sure whether it will help, but this part of "Practical Common Lisp" may be useful even though the book is about Common Lisp: http://www.gigamonkeys.com/book/syntax-and-semantics.html -- / Peter Schuller -- 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