1
votes

Here is what I have:

(def my-atom (atom []))

(defn add-to-my-atom! [x]
  (swap! my-atom conj x))

How do I append value to the vector only if it's not present already? I want to be able to use a predicate for the testing. For example in Common Lisp there is pushnew:

pushnew item place &key key test test-not

Is there something similar in Clojure? Perhaps, I should use sets instead of vectors. Fine. How do you define predicate that set will use to compare its values? For example, set can contain strings, and suppose that differences in case should not affect operations on sets, how Clojure deals with that?

2

2 Answers

2
votes

Using a vector:

user> (def my-atom (atom []))

(defn push-new
  [place item pred]
  (if (pred place item)
    (conj place item)
    place))

(defn add-to-my-atom!
  [x]
  (swap! my-atom push-new x
         (fn [place item]
           (not (some #(= (.toLowerCase %)
                          (.toLowerCase item))
                      place)))))


#'user/add-to-my-atom!
user> (add-to-my-atom! "Hello World!")
["Hello World!"]
user> (add-to-my-atom! "hello world!")
["Hello World!"]
user> (add-to-my-atom! "ABCDE")
["Hello World!" "ABCDE"]
user> (add-to-my-atom! "abcde")
["Hello World!" "ABCDE"]

Using a set with a custom sorting comparitor:

user> (def my-atom (atom (sorted-set-by (fn [a b] (compare (.toLowerCase a) (.toLowerCase b))))))
#'user/my-atom
user> (swap! my-atom conj "Hello")
#{"Hello"}
user> (swap! my-atom conj "hello")
#{"Hello"}
user> (swap! my-atom conj "abc")
#{"abc" "Hello"}
user> (swap! my-atom conj "Abc")
#{"abc" "Hello"}
2
votes

If you were not working with atoms, the fn to add to a vector if it is not there would be:

(defn push-new [v value]
   (if (some #{value} v)
       v
       (conj v value)))

Now you can easily use that fn to move from one value of the atom to the next:

(defn add-to-my-atom [the-atom x]
   (swap! the-atom push-new x))

Depending on your use case, a set can be more appropriate. Clojure relies on the equals and hashcode implementation of the objects that you put into the set, unless you use a sorted-set-by, or you can simply uppercase them before putting them into the set.