I wanted a Clojure vector in an atom to model a stateful FIFO (push to the end, pop from the beginning). tried
(def stack (atom []))
then push as follows:
(swap! stack #(conj % 1))
(swap! stack #(conj % 2))
expecting
[1 2]
but getting
(2 1)
Not a big deal, it just means that I must reverse (O(n)) the value of the atom (persistent list) to get the items in the order than I pushed them (e.g., a stream of imperative commands to a virtual machine in order). Still, it was a surprise.
Is there a clojure.core FIFO I can pack into an atom? I thought of priority-map, but it seems overkill. The examples for swap! on clojuredocs.org use lists or maps, not quite what I wanted. I found lots of samples by googling "FIFO Clojure," but some are a bit rich, e.g., clojure.core.cache (map-like and not vector-like); amalloy's ring-buffer (external dependency). Looking for something really small and straightforward. I didn't see an answer in the automatic suggestions from StackOverflow.
Something is not quite right in the wider context of your code; I'm assuming that you have much more going on than what's in the example you posted?
Here's the result in my REPL and what I'd expect:
user=> (def stack (atom []))
#'user/stack
user=> (swap! stack #(conj % 1))
[1]
user=> (swap! stack #(conj % 2))
[1 2]
user=> #stack
[1 2]
When using Vectors, items are added to the end of the collection. The result that you're seeing looks like the behaviour you'd get if stack was a list instead, e.g. adding to the front:
user=> (def stack (atom '()))
#'user/stack
user=> (swap! stack #(conj % 1))
(1)
user=> (swap! stack #(conj % 2))
(2 1)
user=> #stack
(2 1)
So I'm wondering if somewhere in your code, you've somehow ended up defining a list, rather than a vector.
Related
This is a simple attempt to reproduce some code that Ross Ihaka gave as an example of poor R performance. I was curious as to whether Clojure's persistent data structures would offer any improvement.
(https://www.stat.auckland.ac.nz/~ihaka/downloads/JSM-2010.pdf)
However , I'm not even getting to first base, with a Stack Overflow reported, and not much else to go by. Any ideas? Apologies in advance if the question has an obvious answer I've missed...
; Testing Ross Ihaka's example of poor R performance
; against Clojure, to see if persisntent data structures help
(def dd (repeat 60000 '(0 0 0 0)))
(defn repl-row [d i new-r]
(concat (take (dec i) d) (list new-r) (drop i d)))
(defn changerows [d new-r]
(loop [i 10000
data d]
(if (zero? i)
data
(let [j (rand-int 60000)
newdata (repl-row data j new-r)]
(recur (dec i) newdata)))))
user=> (changerows dd '(1 2 3 4))
StackOverflowError clojure.lang.Numbers.isPos (Numbers.java:96)
Further, if anyone has any ideas how persistent functional data structures can be used to best advantage in the example above, I'd be very keen to hear. The speedup reported not using immutable structures (link above) was about 500%!
Looking at the stack trace for the StackOverflowError, this seems to be an "exploding thunk" (lazy/suspended calculation) problem that isn't obviously related to the recursion in your example:
java.lang.StackOverflowError
at clojure.lang.RT.seq(RT.java:528)
at clojure.core$seq__5124.invokeStatic(core.clj:137)
at clojure.core$concat$cat__5217$fn__5218.invoke(core.clj:726)
at clojure.lang.LazySeq.sval(LazySeq.java:40)
at clojure.lang.LazySeq.seq(LazySeq.java:49)
at clojure.lang.RT.seq(RT.java:528)
at clojure.core$seq__5124.invokeStatic(core.clj:137)
at clojure.core$take$fn__5630.invoke(core.clj:2876)
Changing this line to realize newdata into a vector resolves the issue:
(recur (dec i) (vec newdata))
This workaround is to address the use of concat in repl-row, by forcing concat's lazy sequence to be realized in each step. concat returns lazy sequences, and in your loop/recur you're passing in the lazy/unevaluated results of previous concat calls as input to subsequent concat calls which returns more lazy sequences based on previous, unrealized lazy sequences. The final concat-produced lazy sequence isn't realized until the loop finishes, which results in a stack overflow due its dependence on thousands of previous concat-produced lazy sequences.
Further, if anyone has any ideas how persistent functional data structures can be used to best advantage in the example above, I'd be very keen to hear.
Since it seems the usage of concat here is to simply replace an element in a collection, we can get the same effect by using a vector and assoc-ing the new item into the correct position of the vector:
(def dd (vec (repeat 60000 '(0 0 0 0))))
(defn changerows [d new-r]
(loop [i 10000
data d]
(if (zero? i)
data
(let [j (rand-int 60000)
newdata (assoc data j new-r)]
(recur (dec i) newdata)))))
Notice there's no more repl-row function, we just assoc into data using the index and the new value. After some rudimentary benchmarking with time, this approach seems to be many times faster:
"Elapsed time: 75836.412166 msecs" ;; original sample w/fixed overflow
"Elapsed time: 2.984481 msecs" ;; using vector+assoc instead of concat
And here's another way to solve it by viewing the series of replacements as an infinite sequence of replacement steps, then sampling from that sequence:
(defn random-replace [replacement coll]
(assoc coll (rand-int (count coll)) replacement))
(->> (iterate (partial random-replace '(1 2 3 4)) dd)
(drop 10000) ;; could also use `nth` function
(first))
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
I've got a function like this:
(defn magic
[a b c]
(flatten (conj [] a b c)))
So on these inputs I get the following:
(magic 1 2 3) => (1 2 3)
(magic 1 [2 3] 4) => (1 2 3 4)
My question is, is there a better way of doing this?
The problem can be summarised as:
I don't know whether I will get numbers or vectors as input, but I need to return a single flat list
This could be slightly simplified (and generalized) as:
(defn magic [& args]
(flatten (apply list args)))
Or, as pointed out in the comments, it can be simplified even further (since args above is already a seq):
(defn magic [& args]
(flatten args))
Other than that, I don't see much else that can be improved about this. Is there anything in particular that's bothering you about your implementation?
If you can get seqs of seqs then you need to be more careful. And will have to recursively go into the list. There is a clojure native function for this tree-seq see the examples here:
http://clojuredocs.org/clojure_core/clojure.core/tree-seq
You'd want something like this (untested):
(defn nonempty-seq [x]
"returns x as a seq if it's a non-empty seq otherwise nil/false"
(and (coll? x) (seq x)))
(tree-seq nonempty-seq seq expr)
The thing i need - is simple queue, something, where i can put tasks, and retrieve them one-by-one from workers(without maintaining order of tasks).
I wrote something like this:
;; Definition
(def q (ref []))
;; Put
(defn put-in-queue [i]
(dosync (alter q conj i)))
;; Get
(defn get-from-queue []
(dosync
(let [v (peek q)]
(alter q pop)
v)))
Is it correct solution? (maybe there are also better solutions for this task)
You should use a clojure.lang.PersistentQueue, right tool for the job and all that :).
Sample below "borrowed" from Hidden features of Clojure:
user> (-> (clojure.lang.PersistentQueue/EMPTY)
(conj 1 2 3)
pop)
(2 3)
See the remainder of that answer for specifics.
The correct solution is probably to use a java.util.concurrent queue, most likely java.util.concurrent.LinkedBlockingQueue. j.u.c queues are robust, perfectly suited to the task and work in Clojure just fine.
See my answer to the Producer consumer with qualifications SO question for a scenario with 5 producers, 2 consumers and a limited-size queue implemented in two ways for comparison: first with c.l.PersistentQueue, second with j.u.c.LinkedBlockingQueue.
as dsm points out, when you need a queue, use a queue, and for times where you really need a vector and want to add things to the end and remove them from the front, subvec and conj are both O(1) functions on vectors.
user> (subvec [1 2 3] 1)
[2 3]
user> (conj [1 2 3] 4)
[1 2 3 4]
user> (-> [] (conj 1 2) (conj 3) (subvec 1))
In lisp, I can pass an argument to a function and have it altered within the function. (AKA destructive functions). However, in Clojure, I've read somewhere that it is not permissible to alter the given arguments within that same function. For example:
(defn add-two-lists [list1 list2]
(for [n (range (count list1))]
(+ (nth list1 n) (nth list2 n))))
This is a normal function and its output is the addition of the two identical lists. However, I want something like this:
(defn add-two-lists [list1 list2 added_list]
(set! added_list
(for [n (range (count list1))]
(+ (nth list1 n) (nth list2 n)))))
Perhaps my use of set! is wrong or misused, and I still get errors. Is there a elegant way to destructively modify arguments in Clojure?
Destructive modification is discouraged in Clojure - I would encourage you to find ways to write your code without resorting to destructive updates.
In the spirit of giving a Clojurey solution, I would write your add-two-lists function as follows:
(defn add-two-lists [list1 list2]
(map + list1 list2))
This has a few advantages:
It's purely functional
It's lazy, so you can even add lists of infinite length (try doing that with a destructively updated argument!)
It's performance is O(n) which is optimal - the versions in the question are actually O(n^2) since nth is itself an O(n) operation on lists.
It's nice and concise :-)
Clojure Provides several mutable types that would work well in this situation, for instance you could pass an atom to the function and have it set the value in that atom.
(defn add-two-lists [list1 list2 added_list]
(reset! added_list
(for [n (range (count list1))]
(+ (nth list1 n) (nth list2 n)))))
then after you call this you get the value out of the atom with #/deref
edit: if efficiency is the goal then using a transient collection may help
The with-local-vars macro lets you create thread-locally bound vars that you can modify with var-set. You also have to access the var's value with var-get, which can be shortened to just #.
(defn add-two-lists [list1 list2 added-list]
(var-set added-list
(for [n (range (count list1))]
(+ (nth list1 n) (nth list2 n)))))
(with-local-vars [my-list nil]
(add-two-lists '(1 2 3) '(3 4 5) my-list)
#my-list)
EDIT:
On a stylistic note, you could use map to add the two lists without using the nth function to random-access each index in each list:
(defn add-two-lists [list1 list2 added-list]
(var-set added-list (map + list1 list2)))
From the clojure documentation on set!
Note - you cannot assign to function params or local bindings. Only Java fields, Vars, Refs and Agents are mutable in Clojure.
Typically in courses where functional languages are chosen, you are encouraged not to use for-loops and assignments. Instead you should favor recursion and composition of functions.
So if I wanted to add 2 to each element of a list, in an imperative language, I would just do a for loop, but in a functional language, I would use recursion
user=> (def add2
(fn [mylist]
(if
(empty? mylist)
nil
(cons (+ (first mylist) 2) (add2 (rest mylist))))))
user=> (add2 (list 1 2 3))
(3 4 5)