Is there an easier/more idiomatic way to store/swap keywords in atoms than:
(def a (atom :a))
(defn change-a [new-kw] (swap! a (fn [_] new-kw)))
No use case as yet, just wondering. It's also entirely possible that I'm missing something, and this kind of thing shouldn't happen/never actually happens in the wild because [some other pattern] is a much better solution.
atoms can be either swapped (CAS) or reset to a different value. Swapping is done with a modifying function e.g. :
user=> (swap! (atom 41) inc)
42
Notice that a previous (e.g. current) value of an atom is taken into a count when swapping.
Reseting a value of an atom is done "without regard for the current value":
user=> (reset! (atom 41) 42)
42
In your case it could be used as:
(reset! a :b)
In case you'd like to reset a value of an atom keeping the CAS semantics, you can compare-and-set! it:
user=> (def a (atom 41))
#'user/a
user=> (compare-and-set! a #a 42)
true
user=> #a
42
Related
According to Clojure's documentation, reset! can be used as:
Sets the value of atom to newval without regard for the current value.
Returns newval.
Thus, I can do:
user> (def my-test (atom 666))
#'user/my-test
user> my-test
#<Atom#66d7a880: 666>
user> #my-test
666
user> (reset! my-test 77)
77
user> my-test
#<Atom#66d7a880: 77>
user> #my-test
77
But, is there any difference between using another def instead of reset!?
user> (def my-test (atom 666))
#'user/my-test
user> my-test
#<Atom#66d7a880: 666>
user> #my-test
666
user> (reset! my-test 77)
77
user> my-test
#<Atom#66d7a880: 77>
user> #my-test
77
;;;; converting it back to the original value via def
user> (def my-test (atom 666))
#'user/my-test
user> #my-test
666
user> my-test
#<Atom#7ce4f432: 666>
user>
Just by reading the experiments on the REPL I cannot identify any difference. But I am new to Clojure, so I am probably naive here.
If there is any difference, why should I use reset! instead of a new def?
You can see the answer in the REPL output in your question. When you write (reset! a 1), you give a new value to the existing atom. When you write (def a (atom 1)), you get a brand new atom. Why does this matter? Because someone may have another reference to the old atom: in the former case they see the new value, and in the latter case they don't. Compare, for example:
(def a (atom 0))
(defn counter [c] (fn [] (swap! c inc)))
(def count-up (counter a))
(count-up) ; 1
(count-up) ; 2
(reset! a 0)
(count-up) ; 1 again
with
(def a (atom 0))
(defn counter [c] (fn [] (swap! c inc)))
(def count-up (counter a))
(count-up) ; 1
(count-up) ; 2
(def a (atom 0))
(count-up) ; 3, because the old atom still holds 2
Changes to atoms are always free of race conditions. New-def-ing is not.
A Clojure Var is meant to be a global value that, in general, never changes (as always, there are exceptions to every rule). As an example, function declarations are normally stored in a Var.
A Clojure Atom is meant to point to a value that can change. An atom may be held in a global Var or a local variable binding (e.g. in a (let ...) form). Atoms are thread-safe (this is one of their primary purposes).
If you are just playing around with experimental code with only one thread, you can do a lot of sloppy or dangerous stuff and there is no problem. However, you should learn how to use each tool for its intended purpose.
More detailed discussion:
Brave Clojure
Book Getting Clojure
Clojure.org - Vars
Clojure.org - Atoms
clojuredocs.org - atom
Clojure CheatSheet
def creates a new atom (means allocate new memory space for an atom - setting it up - setting a pointer), while reset! just resets an existing atom (just changing value in the cell the pointer points to).
Therefore it is logical that reset! must be much cheaper (faster execution and less usage of resources) than def which you can test by:
(def n 10000000)
(time (dotimes [_ n] (def a (atom 1))))
## "Elapsed time: 2294.676443 msecs"
(def b (atom 1))
(time (dotimes [_ n] (reset! b 1)))
## "Elapsed time: 106.03302 msecs"
So reset! is one magnitude of order faster than def.
Here's a working minimal example showing how Clojure can handle non-namespaced symbols:
(defmacro simple-macro [s]
(name `~s))
(str "And the answer is "
(simple-macro v1))
Now I'd like to do something more complicated. Inspired by this example:
(defn typical-closure []
(let [names (atom [])]
(fn [arg] (swap! names conj arg) #names)))
(def Q (typical-closure))
(Q 1)
(Q 2)
;; [1 2]
I now want to define a similar closure to take the names of undefined variables.
(defn take-names-fun []
(let [names (atom [])]
#((swap! names conj (simple-macro %)) (deref names))))
(def P (take-names-fun))
(P v1)
But this doesn't work as hoped; I get the error:
Unable to resolve symbol: v1 in this context
Is there a way to fix this so that we can add the name "v1" to the list of names defined above?
I tried using a macro instead (inspired by a syntax trick on page 21 of "Mastering Clojure Macros")... but this answer on ask.clojure.org says it doesn't make sense to define a closure over an atom in a macro.
(defmacro take-names-macro []
(let [names (atom [])]
`(fn [~'x] (swap! ~names conj (simple-macro ~'x)) (deref ~names))))
(def R (take-names-macro))
And indeed, I get another error here:
Can't embed object in code, maybe print-dup not defined:
However, there is no such restriction for using atoms inside defn. Maybe at the end of the day I need to put my symbols in a namespace...?
Not quite sure what it is that you're ultimately trying to accomplish.
But, since P is a function, it will always evaluate its arguments. So, if you pass it an undefined symbol, you'll get the error you got. Instead, you have to create a macro so that you can quote the undefined symbol (to stop the evaluation of the argument) and then pass that to P. Here is an example that does that.
user> (defn take-names-fun []
(let [names (atom [])]
(fn [arg] (swap! names conj (name arg)))))
#'user/take-names-fun
user> (def P (take-names-fun))
#'user/P
user> (defmacro PM [s] `(P (quote ~s)))
#'user/PM
user> (PM v1)
["v1"]
user> (PM v2)
["v1" "v2"]
user>
You might find the article on Evaluation in Clojure helpful.
#dorab's answer is nice.
But you could also tell yourself: "When entering undefined variables into a function, I have to quote them to avoid evaluation of them!"
So, after:
(defn typical-closure []
(let [names (atom [])]
(fn [arg] (swap! names conj arg) #names)))
(def Q (typical-closure))
Do:
user=> (Q 'v1)
[v1]
user=> (Q 'v2)
[v1 v2]
user=> (Q 3)
[v1 v2 3]
user=> (Q 'v4)
[v1 v2 3 v4]
user=>
In this way you don't need the macro and you can alternate between evaluated and not-evaluated arguments (undefined symbols).
So with the way fn's are written in clojure there is unfortunately no way to get the name of the var being passed as a param from within the fn body.. Someone with more experience with the clojure src may be able to explain better why that is, my initial guess would be that it has something to do with keeping thread local scopes isolated and lazy.
But there's absolutely nothing stopping you from writing a macro that wraps other macros using your closure idea!
Here's an example of how something like that may be written:
https://stackoverflow.com/a/11857444
I want to know if this is the right way to loop through an collection:
(def citrus-list ["lemon" "orange" "grapefruit"])
(defn display-citrus [citruses]
(loop [[citrus & citruses] citruses]
(println citrus)
(if citrus (recur citruses))
))
(display-citrus citrus-list)
I have three questions:
the final print displays nil, is it ok or how can avoid it?
I understand what & is doing in this example but I donĀ“t see it in other cases, maybe you could provide a few examples
Any other example to get the same result?
Thanks,
R.
First of all your implementation is wrong. It would fail if your list contains nil:
user> (display-citrus [nil "asd" "fgh"])
;;=> nil
nil
And print unneeded nil if the list is empty:
user> (display-citrus [])
;;=> nil
nil
you can fix it this way:
(defn display-citrus [citruses]
(when (seq citruses)
(loop [[citrus & citruses] citruses]
(println citrus)
(if (seq citruses) (recur citruses)))))
1) it is totally ok: for non-empty collection the last call inside function is println, which returns nil, and for empty collection you don't call anything, meaning nil would be returned (clojure function always returns a value). To avoid nil in your case you should explicitly return some value (like this for example):
(defn display-citrus [citruses]
(when (seq citruses)
(loop [[citrus & citruses] citruses]
(println citrus)
(if (seq citruses) (recur citruses))))
citruses)
user> (display-citrus citrus-list)
;;=> lemon
;;=> orange
;;=> grapefruit
["lemon" "orange" "grapefruit"]
2) some articles about destructuring should help you
3) yes, there are some ways to do this. The simplest would be:
(run! println citrus-list)
Answering your last question, you should avoid using loop in Clojure. This form is rather for experienced users that really know what they do. In your case, you may use such more user-friendly forms as doseq. For example:
(doseq [item collection]
(println item))
You may also use map but keep in mind that it returns a new list (of nils if your case) that not sometimes desirable. Say, you are interested only in printing but not in the result.
In addition, map is lazy and won't be evaluated until it has been printed or evaluated with doall.
For most purpose, you can use either map, for or loop.
=> (map count citrus-list)
(5 6 10)
=> (for [c citrus-list] (count c))
(5 6 10)
=> (loop [[c & citrus] citrus-list
counts []]
(if-not c counts
(recur citrus (conj counts (count c)))))
[5 6 10]
I tend to use map as much of possible. The syntax is more concise, and it clearly separates the control flow (sequential loop) from the transformation logic (count the values).
For instance, you can run the same operation (count) in parallel by simply replacing map by pmap
=> (pmap count citrus-list)
[5 6 10]
In Clojure, most operations on collection are lazy. They will not take effect as long as your program doesn't need the new values. To apply the effect immediately, you can enclose your loop operation inside doall
=> (doall (map count citrus-list))
(5 6 10)
You can also use doseq if you don't care about return values. For instance, you can use doseq with println since the function will always return nil
=> (doseq [c citrus-list] (println c))
lemon
orange
grapefruit
Goal: Construct a ClojureScript function that takes a string s and returns the unique channel with the name (str s "-chan") (if the channel doesn't exist, then create it). Here is my attempt:
(defn string-channel
[s]
(let [chan-name (symbol (str s "-chan"))]
(defonce chan-name (chan))
chan-name))
This yields an error. How do I accomplish this goal? Note that since I'm in ClojureScript, I am unable to use the eval construct if the solution involves a macro.
I would rather propose to keep these channels in an atom (since defining vars dynamically seems really needless here). In addition, keeping channels in one place seems to me more manageable.
(def channels (atom {}))
(defn string-channel [s]
(when-not (#channels s)
(swap! channels assoc s (chan)))
(#channels s))
It turns out the right approach was to use a defmacro:
(defmacro string-channel
[s]
`(do
(defonce ~(symbol (str s "-chan")) (chan))
~(symbol (str s "-chan"))))
Consider using memoize if the intent is to ensure a unique channel for each label s:
(def unique-channel (memoize (fn [s] (chan))))
First, I have no experience with CS and Clojure is my first language, so pardon if the following problem has a solution, that is immediately apparent for a programmer.
The summary of the question is as follows: one needs to create atoms at will with unknown yet symbols at unknown times. My approach revolves around a) storing temporarily the names of the atoms as strings in an atom itself; b) changing those strings to symbols with a function; c) using a function to add and create new atoms. The problem pertains to step "c": calling the function does not create new atoms, but using its body does create them.
All steps taken in the REPL are below (comments follow code blocks):
user=> (def atom-pool
#_=> (atom ["a1" "a2"]))
#'user/atom-pool
'atom-pool is the atom that stores intermediate to-be atoms as strings.
user=> (defn atom-symbols []
#_=> (mapv symbol (deref atom-pool)))
#'user/atom-symbols
user=> (defmacro populate-atoms []
#_=> (let [qs (vec (remove #(resolve %) (atom-symbols)))]
#_=> `(do ~#(for [s qs]
#_=> `(def ~s (atom #{}))))))
#'user/populate-atoms
'populate-atoms is the macro, that defines those atoms. Note, the purpose of (remove #(resolve %) (atom-symbols)) is to create only yet non-existing atoms. 'atom-symbols reads 'atom-pool and turns its content to symbols.
user=> (for [s ['a1 'a2 'a-new]]
#_=> (resolve s))
(nil nil nil)
Here it is confirmed that there are no 'a1', 'a2', 'a-new' atoms as of yet.
user=> (defn new-atom [a]
#_=> (do
#_=> (swap! atom-pool conj a)
#_=> (populate-atoms)))
#'user/new-atom
'new-atom is the function, that first adds new to-be atom as string to `atom-pool. Then 'populate-atoms creates all the atoms from 'atom-symbols function.
user=> (for [s ['a1 'a2 'a-new]]
#_=> (resolve s))
(#'user/a1 #'user/a2 nil)
Here we see that 'a1 'a2 were created as clojure.lang.Var$Unbound just by defining a function, why?
user=> (new-atom "a-new")
#'user/a2
user=> (for [s ['a1 'a2 'a-new]]
#_=> (resolve s))
(#'user/a1 #'user/a2 nil)
Calling (new-atom "a-new") did not create the 'a-new atom!
user=> (do
#_=> (swap! atom-pool conj "a-new")
#_=> (populate-atoms))
#'user/a-new
user=> (for [s ['a1 'a2 'a-new]]
#_=> (resolve s))
(#'user/a1 #'user/a2 #'user/a-new)
user=>
Here we see that resorting explicitly to 'new-atom's body did create the 'a-new atom. 'a-new is a type of clojure.lang.Atom, but 'a1 and 'a2 were skipped due to already being present in the namespace as clojure.lang.Var$Unbound.
Appreciate any help how to make it work!
EDIT: Note, this is an example. In my project the 'atom-pool is actually a collection of maps (atom with maps). Those maps have keys {:name val}. If a new map is added, then I create a corresponding atom for this map by parsing its :name key.
"The summary of the question is as follows: one needs to create atoms at will with unknown yet symbols at unknown times. "
This sounds like a solution looking for a problem. I would generally suggest you try another way of achieving whatever the actual functionality is without generating vars at runtime, but if you must, you should use intern and leave out the macro stuff.
You cannot solve this with macros since macros are expanded at compile time, meaning that in
(defn new-atom [a]
(do
(swap! atom-pool conj a)
(populate-atoms)))
populate-atoms is expanded only once; when the (defn new-atom ...) form is compiled, but you're attempting to change its expansion when new-atom is called (which necessarily happens later).
#JoostDiepenmaat is right about why populate-atoms is not behaving as expected. You simply cannot do this using macros, and it is generally best to avoid generating vars at runtime. A better solution would be to define your atom-pool as a map of keywords to atoms:
(def atom-pool
(atom {:a1 (atom #{}) :a2 (atom #{})}))
Then you don't need atom-symbols or populate-atoms because you're not dealing with vars at compile-time, but typical data structures at run-time. Your new-atom function could look like this:
(defn new-atom [kw]
(swap! atom-pool assoc kw (atom #{})))
EDIT: If you don't want your new-atom function to override existing atoms which might contain actual data instead of just #{}, you can check first to see if the atom exists in the atom-pool:
(defn new-atom [kw]
(when-not (kw #atom-pool)
(swap! atom-pool assoc kw (atom #{}))))
I've already submitted one answer to this question, and I think that that answer is better, but here is a radically different approach based on eval:
(def atom-pool (atom ["a1" "a2"]))
(defn new-atom! [name]
(load-string (format "(def %s (atom #{}))" name)))
(defn populate-atoms! []
(doseq [x atom-pool]
(new-atom x)))
format builds up a string where %s is substituted with the name you're passing in. load-string reads the resulting string (def "name" (atom #{})) in as a data structure and evals it (this is equivalent to (eval (read-string "(def ...)
Of course, then we're stuck with the problem of only defining atoms that don't already exist. We could change the our new-atom! function to make it so that we only create an atom if it doesn't already exist:
(defn new-atom! [name]
(when-not (resolve (symbol name))
(load-string (format "(def %s (atom #{}))" name name))))
The Clojure community seems to be against using eval in most cases, as it is usually not needed (macros or functions will do what you want in 99% of cases*), and eval can be potentially unsafe, especially if user input is involved -- see Brian Carper's answer to this question.
*After attempting to solve this particular problem using macros, I came to the conclusion that it either cannot be done without relying on eval, or my macro-writing skills just aren't good enough to get the job done with a macro!
At any rate, I still think my other answer is a better solution here -- generally when you're getting way down into the nuts & bolts of writing macros or using eval, there is probably a simpler approach that doesn't involve metaprogramming.