Ok, I'm a bit stuck on this one, can I actually do what I'm trying to do with this part of the code below:
(recur (conj (get-links (first links)) (rest links))))
get-links returns a sequence of urls which is fed into the initial process-links call then should recurse.
The first link i feed in works, but then the second link where I'm trying to conj one sequence on to another gives me the following error.
"Clojure.lang.LazySeq#xxxxxxx"
Now I'm wondering, is this conj'ing the reference to the instruction to generate the "rest" (rest links) of the un-evaluated sequence?
(defn process-links
[links]
(if (not (empty? links))
(do
(if (not (is-working (first links)))
(do
(println (str (first links) " is not working"))
(recur (rest links)))
(do
(println (str (first links) " is working"))
(recur (conj (get-links (first links)) (rest links))))))))
If I'm totally wrong in my approach to this, let me know.
conj adds an item to a collection. Using it on two collections creates a nested structure. You probably want to concat the two sequences instead.
To illustrate:
user> (conj [1 2 3] [4 5 6])
[1 2 3 [4 5 6]]
user> (concat [1 2 3] [4 5 6])
(1 2 3 4 5 6)
Regarding the "Clojure.lang.LazySeq#xxxxxxx" thing:
The problem is in this snippet:
(println (str (first links) " is working"))
Here you use the string concatenation function str to glue together (first links), which is not a string in this case, and " is working", which is a string. What does str do with a non-string argument? It calls the .toString method on it. What does .toString do for Clojure data? Not always the thing you'd want.
The solution is to use the pr family of functions. pr writes Clojure data to a stream in a way that is recognized by the clojure reader. Two examples of how the above snipped can be rewritten:
(do (pr (first links))
(println " is working"))
;; Sligtly less efficient since a string must be created
(println (pr-str (first links)) "is working")
Note that if you give multiple arguments to println it will print all items with spaces in between.
Related
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 am constructing a list of hash maps which is then passed to another function. When I try to print each hash maps from the list using map it is not working. I am able to print the full list or get the first element etc.
(defn m [a]
(println a)
(map #(println %) a))
The following works from the repl only.
(m (map #(hash-map :a %) [1 2 3]))
But from the program that I load using load-file it is not working. I am seeing the a but not its individual elements. What's wrong?
In Clojure tranform functions return a lazy sequence. So, (map #(println %) a) return a lazy sequence. When consumed, the map action is applied and only then the print-side effect is visible.
If the purpose of the function is to have a side effect, like printing, you need to eagerly evaluate the transformation. The functions dorun and doall
(def a [1 2 3])
(dorun (map #(println %) a))
; returns nil
(doall (map #(println %) a))
; returns the collection
If you actually don't want to map, but only have a side effect, you can use doseq. It is intended to 'iterate' to do side effects:
(def a [1 2 3])
(doseq [i a]
(println i))
If your goal is simply to call an existing function on every item in a collection in order, ignoring the returned values, then you should use run!:
(run! println [1 2 3])
;; 1
;; 2
;; 3
;;=> nil
In some more complicated cases it may be preferable to use doseq as #Gamlor suggests, but in this case, doseq only adds boilerplate.
I recommend to use tail recursion:
(defn printList [a]
(let [head (first a)
tail (rest a)]
(when (not (nil? head))
(println head)
(printList tail))))
In Clojure, how do you print the contents of a vector? (I imagine to the console, and usually for debugging purposes). If the answer can be generalized to any Seq that would be good.
Edit:
I should add that it should be a simple function that gives output that looks reasonable, so prints an item per line - so can be easily used for debugging purposes. I'm sure there are libraries that can do it, but using a library really does seem like overkill.
I usually use println. There are several other printing functions that you might want to try. See the "IO" section of the Clojure cheatsheet.
This isn't Java. Just print it, and it will look OK.
You can also use clojure.pprint/pprint to pretty-print it. This can be helpful with large, complex data structures.
These methods work for all of the basic Clojure data structures.
Exception: Don't print infinitely long lazy structures such as what (range) returns--for obvious reasons. For that you may need to code something special.
This works for me:
(defn pr-seq
([seq msg]
(letfn [(lineify-seq [items]
(apply str (interpose "\n" items)))]
(println (str "\n--------start--------\n"
msg "\nCOUNT: " (count seq) "\n"
(lineify-seq seq) "\n---------end---------"))))
([seq]
(pr-seq seq nil)))
Example usages:
(pr-seq [1 2 3])
(pr-seq (take 20 blobs) (str "First 20 of " (count blobs) " Blobs")))
If you want to just print out the elements of the sequence/vector you could just map println to your sequence/vector, but make sure you force map to evaluate using dorun:
(dorun (map println [1 2 3 4]))
This can be applied to sequences too:
(dorun (map println '(1 2 3 4)))
Another way you can do this with apply is to curry map with println and apply it to the sequence/vector:
(apply (partial map println) [[1 2 3 4]])
(apply (partial map println) ['(1 2 3 4)])
Another way you can do this is with doseq:
(doseq [e [1 2 3 4]]
(println e))
(doseq [e '(1 2 3 4)]
(println e))
This one at least stops the text going out too far to the right:
(defn pp
([n x]
(binding [pp/*print-right-margin* n]
(-> x clojure.pprint/pprint)))
([x]
(pp 100 x)))
It is possible to do partials of this function to alter the width.
I want to coalesce multiple sequences into one lazy sequence. The caveat is that it seems that all the mechanisms in core (map, interleave, etc) to accomplish this will not account for those sequences being multiple lengths. I have seen this similar post but it's not exactly what I was looking for. So basically, the goal is a function "super-fn" that has these characteristics:
=>(defn super-fn [& rest]
...)
=>(apply println (super-fn [1 2 3 ] [1 2 3 4 5]))
1 1 2 2 3 3 4 5
=>nil
It seems like it would be useful to be able to coalesce multiple streams of data like this without knowing their lengths. Is my "super-fn" in the core library and I have just missed it or am I missing some hard aspect of doing this?
I agree with bsvingen, though you could use slightly more elegant implementation:
(defn super-fn
[& colls]
(lazy-seq
(when-let [ss (seq (keep seq colls))]
(concat (map first ss)
(apply super-fn (map rest ss))))))
It also correctly handles empty input sequences:
(super-fn [1 2] []) ; => (1 2)
I'm not aware of any such function in the standard library.
It's not hard to write, though:
(defn super-fn
[& seq-seq]
(when seq-seq
(lazy-seq
(concat (filter identity
(map first seq-seq))
(apply super-fn
(seq
(filter identity
(map next seq-seq))))))))
I know I can do the following in Common Lisp:
CL-USER> (let ((my-list nil))
(dotimes (i 5)
(setf my-list (cons i my-list)))
my-list)
(4 3 2 1 0)
How do I do this in Clojure? In particular, how do I do this without having a setf in Clojure?
My personal translation of what you are doing in Common Lisp would Clojurewise be:
(into (list) (range 5))
which results in:
(4 3 2 1 0)
A little explanation:
The function into conjoins all elements to a collection, here a new list, created with (list), from some other collection, here the range 0 .. 4. The behavior of conj differs per data structure. For a list, conj behaves as cons: it puts an element at the head of a list and returns that as a new list. So what is does is this:
(cons 4 (cons 3 (cons 2 (cons 1 (cons 0 (list))))))
which is similar to what you are doing in Common Lisp. The difference in Clojure is that we are returning new lists all the time, instead of altering one list. Mutation is only used when really needed in Clojure.
Of course you can also get this list right away, but this is probably not what you wanted to know:
(range 4 -1 -1)
or
(reverse (range 5))
or... the shortest version I can come up with:
'(4 3 2 1 0)
;-).
Augh the way to do this in Clojure is to not do it: Clojure hates mutable state (it's available, but using it for every little thing is discouraged). Instead, notice the pattern: you're really computing (cons 4 (cons 3 (cons 2 (cons 1 (cons 0 nil))))). That looks an awful lot like a reduce (or a fold, if you prefer). So, (reduce (fn [acc x] (cons x acc)) nil (range 5)), which yields the answer you were looking for.
Clojure bans mutation of local variables for the sake of thread safety, but it is still possible to write loops even without mutation. In each run of the loop you want to my-list to have a different value, but this can be achieved with recursion as well:
(let [step (fn [i my-list]
(if (< i 5)
my-list
(recur (inc i) (cons i my-list))))]
(step 0 nil))
Clojure also has a way to "just do the looping" without making a new function, namely loop. It looks like a let, but you can also jump to beginning of its body, update the bindings, and run the body again with recur.
(loop [i 0
my-list nil]
(if (< i 5)
my-list
(recur (inc i) (cons i my-list))))
"Updating" parameters with a recursive tail call can look very similar to mutating a variable but there is one important difference: when you type my-list in your Clojure code, its meaning will always always the value of my-list. If a nested function closes over my-list and the loop continues to the next iteration, the nested function will always see the value that my-list had when the nested function was created. A local variable can always be replaced with its value, and the variable you have after making a recursive call is in a sense a different variable.
(The Clojure compiler performs an optimization so that no extra space is needed for this "new variable": When a variable needs to be remembered its value is copied and when recur is called the old variable is reused.)
For this I would use range with the manually set step:
(range 4 (dec 0) -1) ; => (4 3 2 1 0)
dec decreases the end step with 1, so that we get value 0 out.
user=> (range 5)
(0 1 2 3 4)
user=> (take 5 (iterate inc 0))
(0 1 2 3 4)
user=> (for [x [-1 0 1 2 3]]
(inc x)) ; just to make it clear what's going on
(0 1 2 3 4)
setf is state mutation. Clojure has very specific opinions about that, and provides the tools for it if you need it. You don't in the above case.
(let [my-list (atom ())]
(dotimes [i 5]
(reset! my-list (cons i #my-list)))
#my-list)
(def ^:dynamic my-list nil);need ^:dynamic in clojure 1.3
(binding [my-list ()]
(dotimes [i 5]
(set! my-list (cons i my-list)))
my-list)
This is the pattern I was looking for:
(loop [result [] x 5]
(if (zero? x)
result
(recur (conj result x) (dec x))))
I found the answer in Programming Clojure (Second Edition) by Stuart Halloway and Aaron Bedra.