Do I use an atom? wrong or there is something else & hellip;

advertisements

Basically...

=> (atom? 5)

CompilerException java.lang.RuntimeException: Unable to resolve symbol: atom? in this context, compiling:(NO_SOURCE_PATH:1)

=> (atom? /a)

RuntimeException Invalid token: /a clojure.lang.Util.runtimeException (Util.java:156) RuntimeException Unmatched delimiter: ) clojure.lang.Util.runtimeException (Util.java:156)

=> (atom? "hello world")

CompilerException java.lang.RuntimeException: Unable to resolve symbol: atom? in this context, compiling:(NO_SOURCE_PATH:1)

So does anyone know what's happening?? I am using Eclipse Juno 4.2, the CounterClockwise plugin.


What's called an atom in Clojure is something completely different than what's called an atom in other Lisps. In classic Lisp an atom is a single value, defined as being not null or not a cons cell (pair):

(define (atom? x)
  (not (or (pair? x)
           (null? x ))))

In Clojure an atom is a concurrency reference type. Atoms in Clojure can be either single-valued or collections/sequences, where updating (mutable state change) is guaranteed to happen atomically.

In Clojure there's far more reference types than the cons list in Lisp, and there's all the Java interop collection types to be reckoned with. That makes it hard to define a check on single-values.

If you do want to, the simplest check is to see if something can be counted. Looking at (source counted), it references clojure.lang.RT/count and countFrom. There, several classes / interfaces are specified, which I included in the following function:

=> (defn single-valued?
     [x]
     (not (or (nil? x)
              (.. x getClass isArray)
              (some #(instance? % x) [clojure.lang.Counted
                                      clojure.lang.IPersistentCollection
                                      java.util.Collection
                                      java.util.Map]))))

=> (map single-valued? [1 "foo" \a 'x true not nil])
(true true true true true true false)

=> (map single-valued? ['(1 2 3 4)
                        [1 2 3 4]
                        {:a 1 :b 2}
                        #{1 2 3 4}
                        (seq [1 2 3 4])
                        (seq {:a 1 :b 2})
                        (seq "foo")
                        (int-array [1 2 3 4])
                        (seq [])])
(false false false false false false false false false)

Since (seq []) evaluates to nil it's not considered single-valued. Of course, java objects with multiple fields, as well as Clojure deftypes / defrecords will register as such, even though they're composite objects.