> 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

Reply via email to