I'm confused with when atoms are dereferenced in Clojure. In the follow, I have a server-request function that receives data and updates the request-result-data which is just a map indexed by the request ID. The function blocks until the server has finished sending the data, and returns the request ID. The first snippet below works as expected. The second doesn't, because (it seems) #request-result-data is de-referenced before the function returns.
;works
(let [req-id (server-request "parameters")]
(pprint (#request-result-data req-id)))
;returns nil
(pprint (#request-result-data (server-request "parameters"))))
Is this normal behaviour? Is there a better way to code this? As intuitively it doesn't seem I need a let here.
Thank you,
If the server-request function is modifying the request-result-data atom, then it's definitely true that you need to use the first form to make sure things happen in the right order. If you have a function call (E1 E2), you shouldn't be relying on E1 or E2 being evaluated in any particular order.
Without any other context, I'd wonder why you can't have server-request return the information instead of putting it in an atom, but that goes beyond your original question.
Related
I was curious so I checked source code of swap! function on clojure repository, and it was like this:
(defn swap!
"Atomically swaps the value of atom to be:
(apply f current-value-of-atom args). Note that f may be called
multiple times, and thus should be free of side effects. Returns
the value that was swapped in."
{:added "1.0"
:static true}
([^clojure.lang.Atom atom f] (.swap atom f))
([^clojure.lang.Atom atom f x] (.swap atom f x))
([^clojure.lang.Atom atom f x y] (.swap atom f x y))
([^clojure.lang.Atom atom f x y & args] (.swap atom f x y args)))
And I don't know what the ".swap" function is doing? I tried to search for it but it's not defined in the same file, so can't find definition of it. Or is this another special thing that is actually not a function at all?
A lot of things in Clojure are actually implemented in Java, like reference types (atom, ref, var, agent), data structures (map, vector, list, set), namespaces (the actual Namespace class) and other stuff. When reading the source code for Clojure functions in clojure.core it's not rare to find an interop call to a Java method.
It is my understanding that there's a long term objective to implement these things in Clojure itself (search here for Clojure-in-Clojure), but for now these things are implemented in Java, which is really not so bad since the whole language is open source and you can check any implementation detail online in the github repo (already linked in a comment): Clojure (note that there's a jvm and a clj folder indicating in what language the code inside is implemented).
In Clojure, an expression (.x object a b c) results in a method call, which in Java would be expressed as object.x(a, b, c). For more details see Java Interop.
In this particular case, the swap! function calls an appropriately overloaded swap method of the clojure.lang.Atom instance passed as the first argument. The swap method contains the actual logic performing the swap.
Simply put, an atom is sth. that is under control of transactional memory. (Read about STM, please.) It is inmutable for its observers (dereferencing an atom returns inmutable state as of the instant of deref), but can be mutated transactionally. This is exactly what swap! does. It transactionally swaps the old value for the new value. Please note that it is very different from assignment. Assignment is not safe for concurrency.
In other words, atom works like a cell in a database table. When you query it, you will have a value, not an exception, even if at the same instant another query is updating it.
Cheers -
I'm calling clojure.core/time which is documented as "Evaluates expr and prints the time it took. Returns the value of expr"
Eg:
(time (expensive))
Macroexpanding it shows that it does store the value as a let so after outputting the time it should return immediately with the value in the let expression.
When I make the call however with an expensive computation, I see a delay and then get the time back, but then have to wait for a significant time (sometimes +10 seconds or more) for the result to appear.
Can anyone explain what's going on here?
PS: This is using clojure 1.3.0 if that makes any difference.
Maybe you are returning something lazy, of which the elements are only produced when fed to the REPL? In that case, you might want to wrap it in a dorun which forces all elements to be produced.
If you could provide the details of your expensive computation, we could see if this is true.
Useful addition from Savanni D'Gerinel's comment:
The proper syntax is probably (time (doall (computation))) if you want to return the result and (time (dorun (computation))) if you do not.
I am having some troubles figuring how to use the "let" form. In the example below, I would like to locally bind the value "cols" in order to work on it later in the function. What I am noticing, however, is that if I use "let" the function sel-opt-tmp will return a nil value instead than a list.
(defn sel-opt-tmp []
(let [cols "test"]))
(prn (sel-opt-tmp))
*The above code returns a nil value.
I understand that "let" only binds a value in the scope of a function, what I do not know is if there is a way to pass the value out of the let scope. Maybe there is something like "return" that I am not aware of? Or this is simply bad design and I should not use the binding at all in this case (this tends to create long chains of functions that are difficult to read although)?
It returns nil because the contents of the let statement is empty (or nil). Try:
(let [cols "test"] cols)
Which will return the value of cols. As seh says, a let statement evaluates to the value of its last sub-expression.
There is no such problem with passing values outside the scope as you mention. The binding cols is in force only within the scope, but the lifetime of the value of (:ks cols) is not similarly restricted. (That's why you have garbage collection: you can return values that point to data, and the data stays live as long as there are references to it.)
If you get nil from the function, that likely means that cols does not have a :ks key... or indeed might not be a map. Since cols is the result from filter, it is a sequence, and when the :ks keyword is used as a function, it returns nil for non-collections. To guard against that kind of bugs it may be a useful convention to always write (cols :ks) instead of (:ks cols) so that you get an error when what you think is a map is something else.
I have a defrecord called a bag. It behaves like a list of item to count. This is sometimes called a frequency or a census. I want to be able to do the following
(def b (bag/create [:k 1 :k2 3])
(keys bag)
=> (:k :k1)
I tried the following:
(defrecord MapBag [state]
Bag
(put-n [self item n]
(let [new-n (+ n (count self item))]
(MapBag. (assoc state item new-n))))
;... some stuff
java.util.Map
(getKeys [self] (keys state)) ;TODO TEST
Object
(toString [self]
(str ("Bag: " (:state self)))))
When I try to require it in a repl I get:
java.lang.ClassFormatError: Duplicate interface name in class file compile__stub/techne/bag/MapBag (bag.clj:12)
What is going on? How do I get a keys function on my bag? Also am I going about this the correct way by assuming clojure's keys function eventually calls getKeys on the map that is its argument?
Defrecord automatically makes sure that any record it defines participates in the ipersistentmap interface. So you can call keys on it without doing anything.
So you can define a record, and instantiate and call keys like this:
user> (defrecord rec [k1 k2])
user.rec
user> (def a-rec (rec. 1 2))
#'user/a-rec
user> (keys a-rec)
(:k1 :k2)
Your error message indicates that one of your declarations is duplicating an interface that defrecord gives you for free. I think it might actually be both.
Is there some reason why you cant just use a plain vanilla map for your purposes? With clojure, you often want to use plain vanilla data structures when you can.
Edit: if for whatever reason you don't want the ipersistentmap included, look into deftype.
Rob's answer is of course correct; I'm posting this one in response to the OP's comment on it -- perhaps it might be helpful in implementing the required functionality with deftype.
I have once written an implementation of a "default map" for Clojure, which acts just like a regular map except it returns a fixed default value when asked about a key not present inside it. The code is in this Gist.
I'm not sure if it will suit your use case directly, although you can use it to do things like
user> (:earth (assoc (DefaultMap. 0 {}) :earth 8000000000))
8000000000
user> (:mars (assoc (DefaultMap. 0 {}) :earth 8000000000))
0
More importantly, it should give you an idea of what's involved in writing this sort of thing with deftype.
Then again, it's based on clojure.core/emit-defrecord, so you might look at that part of Clojure's sources instead... It's doing a lot of things which you won't have to (because it's a function for preparing macro expansions -- there's lots of syntax-quoting and the like inside it which you have to strip away from it to use the code directly), but it is certainly the highest quality source of information possible. Here's a direct link to that point in the source for the 1.2.0 release of Clojure.
Update:
One more thing I realised might be important. If you rely on a special map-like type for implementing this sort of thing, the client might merge it into a regular map and lose the "defaulting" functionality (and indeed any other special functionality) in the process. As long as the "map-likeness" illusion maintained by your type is complete enough for it to be used as a regular map, passed to Clojure's standard function etc., I think there might not be a way around that.
So, at some level the client will probably have to know that there's some "magic" involved; if they get correct answers to queries like (:mars {...}) (with no :mars in the {...}), they'll have to remember not to merge this into a regular map (merge-ing the other way around would work fine).
I'm having some trouble understanding how the delay macro works in Clojure. It doesn't seem to do what expect it to do (that is: delaying evaluation). As you can see in this code sample:
; returns the current time
(defn get-timestamp [] (System/currentTimeMillis))
; var should contain the current timestamp after calling "force"
(def current-time (delay (get-timestamp)))
However, calling current-time in the REPL appears to immediately evaluate the expression, even without having used the force macro:
user=> current-time
#<Delay#19b5217: 1276376485859>
user=> (force current-time)
1276376485859
Why was the evaluation of get-timestamp not delayed until the first force call?
The printed representation of various objects which appears at the REPL is the product of a multimethod called print-method. It resides in the file core_print.clj in Clojure's sources, which constitutes part of what goes in the clojure.core namespace.
The problem here is that for objects implementing clojure.lang.IDeref -- the Java interface for things deref / # can operate on -- print-method includes the value behind the object in the printed representation. To this end, it needs to deref the object, and although special provisions are made for printing failed Agents and pending Futures, Delays are always forced.
Actually I'm inclined to consider this a bug, or at best a situation in need of an improvement. As a workaround for now, take extra care not to print unforced delays.