Swap with atom as last parameter for the used function - clojure

I have the following function:
(defn add-recommendations-to-cache [{:keys [trackingId rec-service recs]} cache]
(assoc-in cache [trackingId rec-service] recs))
And I have my atom defined as:
(def cache (atom {}))
If I could change the order of the arguments passed to the function, I would use:
(swap! cache add-recommendations-to-cache msg)
Since I can't, how can I swap using the atom, the function and a message that contains what the first argument requires? I have tried several possible combinations (see below), but none seem to work.
I've tried:
(swap! cache add-recommendations-to-cache msg cache)
and
(swap! cache (add-recommendations-to-cache msg))
and several others to no use.

You can pass your own function that applies the arguments in the order you want:
(swap! cache
(fn [current msg] (add-recommendations-to-cache msg current))
msg)
or
(swap! cache #(add-recommendations-to-cache %2 %1) msg)
or close over msg:
(swap! cache #(add-recommendataions-to-cache msg %))

Related

What does Clojure function #(:jerry #%) means

I'm very new in Clojure. I'm learning with help from Clojure Koans. I found an answer with code below:
(= ["Real Jerry" "Bizarro Jerry"]
(do
(dosync
(ref-set the-world {})
(alter the-world assoc :jerry "Real Jerry")
(alter bizarro-world assoc :jerry "Bizarro Jerry")
(vec (map #(:jerry #%) [the-world bizarro-world]))))))
from: https://github.com/viebel/clojure-koans/blob/master/src/koans/16_refs.clj#L42
It's pretty unfriendly for Google to search like "Clojure #%". So I get nothing from Internet.
How does it works for the function "#(:jerry #%)"?
And the code below is the answer from me, but it doesn't work.
(= ["Real Jerry" "Bizarro Jerry"]
(do
(dosync
(ref-set the-world {})
(alter the-world assoc :jerry "Real Jerry")
(alter bizarro-world assoc :jerry "Bizarro Jerry")
(vec (map (fn [x] (:jerry x)) [the-world bizarro-world]))
)))
#( ...) is a reader macro for anonymous function where % means the first argument passed to the function. For example:
#(println %)
is equivalent to:
(fn [x] (println x))
# is a reader macro for deref so again:
#some-variable
is the same as:
(deref some-variable)
and is used to dereference a current value from one of the ref types.
Thus #(:jerry #%) is an anonymous function which when applied to a ref (e.g. an atom) will deref its current value and use it as an argument to call :jerry keyword as a function with the value.
the-world and bizarro-world are "derefable", which means that you can use # in front to get their value.
You are using an anonymous function, indicated by #( ). In an anonymous function, the percent sign % indicates the argument to the function.
So #% means, "dereference the argument to this function."
:jerry is a keyword used as a function, which gets the value associated with the key :jerry in the map.
For example:
(def coll [(ref {:jerry 21})
(ref {:jerry 42})])
=> #'user/coll
(map #(:jerry #%) coll)
=> (21 42)
Besides, you could find other "weird" symbols in clojure here .
https://yobriefca.se/blog/2014/05/19/the-weird-and-wonderful-characters-of-clojure/

How can I elegantly combine resource and exception handling?

I'm writing a Clojure wrapper for an object-oriented API that heavily involves resource handling. For instance, for the Foo object, I've written three basic functions: foo?, which returns true iff something is a Foo; create-foo, which attempts to obtain the resources to create a Foo, then returns a map containing a return code and (if the construction succeeded) the newly created Foo; and destroy-foo, which takes a Foo and releases its resources. Here are some stubs for those three functions:
(def foo? (comp boolean #{:placeholder}))
(defn create-foo []
(let [result (rand-nth [::success ::bar-too-full ::baz-not-available])]
(merge {::result result}
(when (= ::success result)
{::foo :placeholder}))))
(defn destroy-foo [foo] {:pre [(foo? foo)]} nil)
Obviously, every time create-foo is called and succeeds, destroy-foo must be called with the returned Foo. Here's a simple example that doesn't use any custom macros:
(let [{:keys [::result ::foo]} (create-foo)]
(if (= ::success result)
(try
(println "Got a Foo:")
(prn foo)
(finally
(destroy-foo foo)))
(do
(println "Got an error:")
(prn result))))
There's a lot of boilerplate here: the try-finally-destroy-foo construct must be present to ensure that all Foo resources are released, and the (= ::success result) test must be present to ensure that nothing gets run assuming a Foo when there is no Foo.
Some of that boilerplate can be eliminated by a with-foo macro, similar to the with-open macro in clojure.core:
(defmacro with-foo [bindings & body]
{:pre [(vector? bindings)
(= 2 (count bindings))
(symbol? (bindings 0))]}
`(let ~bindings
(try
~#body
(finally
(destroy-foo ~(bindings 0))))))
While this does help somewhat, it doesn't do anything about the (= ::success result) boilerplate, and now two separate binding forms are required to achieve the desired result:
(let [{:keys [::result] :as m} (create-foo)]
(if (= ::success result)
(with-foo [foo (::foo m)]
(println "Got a Foo:")
(prn foo))
(do
(println "Got an error:")
(prn result))))
I simply can't figure out a good way to handle this. I mean, I could complect the behaviors of if-let and with-foo into some sort of if-with-foo macro:
(defmacro if-with-foo [bindings then else]
{:pre [(vector? bindings)
(= 2 (count bindings))]}
`(let [{result# ::result foo# ::foo :as m#} ~(bindings 1)
~(bindings 0) m#]
(if (= ::success result#)
(try
~then
(finally
(destroy-foo foo#)))
~else)))
This does eliminate even more boilerplate:
(if-with-foo [{:keys [::result ::foo]} (create-foo)]
(do
(println "Got a Foo:")
(prn foo))
(do
(println "Got a result:")
(prn result)))
However, I don't like this if-with-foo macro for several reasons:
it's very tightly coupled to the specific structure of the map returned by create-foo
unlike if-let, it causes all bindings to be in scope in both branches
its ugly name reflects its ugly complexity
Are these macros the best I can do here? Or is there a more elegant way to handle resource handling with possible resource obtainment failure? Perhaps this is a job for monads; I don't have enough experience with monads to know whether they would be useful tool here.
I'd add an error-handler to with-foo. This way the macro has a focus on what should be done. However, this simplifies the code only when all error-cases are treated by a handful of error handlers. If you have to define a custom error-handler every time you call with-foo this solution makes readability worse than an if-else construct.
I added copy-to-map. copy-to-map should copy all relevant information from the object to a map. This way the user of the macro doesn't by accident return the foo-object, since it gets destroyed inside the macro
(defn foo? [foo]
(= ::success (:result foo)))
(defn create-foo [param-one param-two]
(rand-nth (map #(merge {:obj :foo-obj :result %} {:params [param-one param-two]})
[::success ::bar-too-full ::baz-not-available])))
(defn destroy-foo [foo]
nil)
(defn err-handler [foo]
[:error foo])
(defn copy-to-map [foo]
;; pseudo code here
(into {} foo))
(defmacro with-foo [[f-sym foo-params & {:keys [on-error]}] & body]
`(let [foo# (apply ~create-foo [~#foo-params])
~f-sym (copy-to-map foo#)]
(if (foo? foo#)
(try ~#body
(finally (destroy-foo foo#)))
(when ~on-error
(apply ~on-error [~f-sym])))))
Now you call it
(with-foo [f [:param-one :param-two] :on-error err-handler]
[:success (str "i made it: " f)])
Building from #murphy's excellent idea to put the error handler into with-foo's bindings to keep the focus on the normal case, I've ended up with a solution that I like quite a lot:
(defmacro with-foo [bindings & body]
{:pre [(vector? bindings)
(even? (count bindings))]}
(if-let [[sym init temp error] (not-empty bindings)]
(let [error? (= :error temp)]
`(let [{result# ::result foo# ::foo :as m#} ~init]
(if (contains? m# ::foo)
(try
(let [~sym foo#]
(with-foo ~(subvec bindings (if error? 4 2))
~#body))
(finally
(destroy-foo foo#)))
(let [f# ~(if error? error `(constantly nil))]
(f# result#)))))
`(do
~#body)))
like my if-with-foo macro in the question, this with-foo macro is still tied to the structure returned by create-foo; unlike my if-with-foo macro and #murphy's with-foo macro, it eliminates the need for the user to manually take apart that structure
all names are properly scoped; the user's sym is only bound in the main body, not in the :error handler, and conversely, the ::result is only bound in the :error handler, not in the main body
like #murphy's solution, this macro has a nice, fitting name, instead of something ugly like if-with-foo
unlike #murphy's with-foo macro, this with-foo macro allows the user to provide any init value, rather than forcing a call to create-foo, and doesn't transform the returned value
The most basic use case simply binds a symbol to a Foo returned by create-foo in some body, returning nil if the construction fails:
(with-foo [foo (create-foo)]
["Got a Foo!" foo])
To handle the exceptional case, an :error handler can be added to the binding:
(with-foo [foo (create-foo)
:error (partial vector "Got an error!")]
["Got a Foo!" foo])
Any number of Foo bindings can be used:
(with-foo [foo1 (create-foo)
foo2 (create-foo)]
["Got some Foos!" foo1 foo2])
Each binding can have its own :error handler; any missing error handlers are replaced with (constantly nil):
(with-foo [foo1 (create-foo)
:error (partial vector "Got an error!")
foo2 (create-foo)]
["Got some Foos!" foo1 foo2])

Return a unique channel in clojurescript

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))))

two clojure map refs as elements of each other

I have two maps in refs and want to assoc them to each other in one transaction.
My function looks like this:
(defn assoc-two
[one two]
(let [newone (assoc #one :two two)
newtwo (assoc #two :one one)]
(ref-set one newone)
(ref-set two newtwo)))
Now i am calling assoc-two like this:
(dosync (assoc-two (ref {}) (ref {})))
Im getting and StackOverflowError at this point.
I also tried this:
(defn alter-two
[one two]
(alter one assoc :two two)
(alter two assoc :one one))
Is there away to do this in way that one has an entry referencing two and vice versa and still being in one transaction?
The stack overflow does not occur until you try to print one of the circular references, e.g. at the REPL.
so.core=> (def a (ref {}))
#'so.core/a
so.core=> (def b (ref {}))
#'so.core/b
so.core=> (do (dosync (alter-two a b)) :success)
:success
so.core=> (= b (:two #a))
true
so.core=> (= a (:one #b))
true
Obviously printing a circularly referenced object like this will be problematic, but see this recent question and answer on disabling default printing of contents of reference types
(remove-method print-method clojure.lang.IDeref)
(dosync (alter-two (ref {}) (ref {})))
;=> {:one #<Ref clojure.lang.Ref#7f1f91ac>}
; (prints the second ref without attempting to print its circular contents)
The answer can be found a few posts down, this is simply the REPL trying to print your recursive structure.
You have to either remove the print method:
(remove-method print-method clojure.lang.IDeref)
Or add a print method that handles your specific case, this method has to be more specific than the common clojure.lang.IDeref

Why in this example calling (f arg) and calling the body of f explicitly yields different results?

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.