Clojure is saying that I can't call recur from a non-tail-position.
Is this not the tail position?
What is the tail position in my loop then?
(loop [i 20]
(for [x (range 1 21)]
(if (zero? (rem i x))
i
(recur (+ i 1)))))
for does not do what you think it does; it is not an imperative loop. It is a list comprehension, or sequence-generator. Therefore, there is not a return or iterate call at its end, so you cannot place recur there.
It would seem you probably do not need either loop or recur in this expression at all; the for is all you need to build a sequence, but it's not clear to me exactly what sequence you wish to build.
Further to #JohnBaker's answer, any recur refers to the (nearest) enclosing loop or fn (which may be dressed as a letfn or a defn). There is no such thing in your snippet. So there is nothing for the recur to be in tail position to.
But just replace the for with loop, and you get
(loop [i 20]
(loop [x 1]
(if (zero? (rem i x))
i
(recur (+ i 1)))))
... which evaluates to 20,no doubt what you intended.
However, the outer loop is never recurred to, so might at well be a let:
(let [i 20]
(loop [x 1]
(if (zero? (rem i x))
i
(recur (+ i 1)))))
The recur is in tail position because there is nothing left to do in that control path through the loop form: the recur form is the returned value. Both arms of an if have their own tail position.
There are some other disguised ifs that have their own tail position: ors and ands are such.
Related
I want to write a function to return the sum of all numbers divisible by 3 in a given list. I don't know how to pattern match on the size of a list. I get a nil pointer exception when I run the following code.
I am trying to do this using first principles, instead of using loop map and reduce
(defn sum3
[[head & tail]]
(if (= (mod head 3) 0)
(+ head (sum3 tail))
(sum3 tail))
[[head]]
(if (= (mod head 3) 0)
head
0))
(defn -main
"I don't do a whole lot ... yet."
[& args]
(println (sum3 [1 2 3])))
Function dispatch in clojure is done on the number of arguments to the function and not on the number of destructured values in the function call.
Once the appropriate arity has been selected, and the function has started running, the destructuring occurs and binds the symbols to the desctructured values.
Fortunatly clojure offers arbitrary custom function dispatch in the form of multimethods so if you want to dispatch based on the length of the arguments you can. For your example it's overkill though not particularly hard. There are other cases where it makes sense.
A normal, single arity, approach to this function would look like this:
user> (defn sum3
[[head & tail]]
(if (seq tail)
(if (= (mod head 3) 0)
(+ head (sum3 tail))
(sum3 tail))
(if (= (mod head 3) 0)
head
0)))
#'user/sum3
user> (sum3 [1 2 3 4 5 6])
9
You should in general always use recur rather than direct recursion though for this question it's not too much of an issue when demonstrating this principal .
First let's do the version using reduce:
(defn sum3 [coll]
(reduce (fn [sum el]
(if (zero? (mod el 3))
(+ sum el)
sum)) 0 coll))
Notice the use of zero?. No need for pattern-matching here.
Then we can go on to use recursivity:
(defn sum3
([coll] (sum3 0 coll))
([sum [head & tail]]
(let [add (if (zero? (mod head 3))
(+ sum head)
sum)]
(if tail
(recur add tail)
add))))
Again, no pattern matching (you would have to use core.match for that -clojure does not use pattern matching). The dispatch is only made using the number of arguments. This is why your function was not valid syntax: it was in both cases a 1-arity function. Note the use of recur to recurse the function. It can only be used for tail-recursion.
We could make it a 1-arity function without dispatching on arguments as well:
(defn sum3
[[head & tail]]
(let [m3? (zero? (mod head 3))]
(if (seq tail)
(if m3?
(+ head (sum3 tail))
(sum3 tail))
(if m3? head 0))))
Note that this version is not tail-recursive and will overflow for big inputs.
But really the reduce version - or even the loop version look much better.
in fact the main error is in the defn syntax. You don't define two arities here, rather make one arity [[head]] and then goes the body, which is totally valid clojure code. To make 2 arities you should put each into brackets:
(defn sum3
([[head]]
(if (= (mod head 3) 0)
head
0))
([[head & tail]]
(if (= (mod head 3) 0)
(+ head (sum3 tail))
(sum3 tail))))
but it would also fail
because you don't define different arities, they are equal (one argument call), so the compiler would produce an error. Clojure destructuring is not pattern matching at all. It is just a way of retrieving items from a collection. But you can fix this (emulate kind of length pattern matching) with a minor change:
user>
(defn sum3
([head]
(if (= (mod head 3) 0)
head
0))
([head & tail]
(if (= (mod head 3) 0)
(+ head (apply sum3 tail))
(apply sum3 tail))))
#'user/sum3
user> (sum3 1 2 3 4 5 6)
9
user> (apply sum3 [1 2 3 4 5 6])
9
now you have fair variant with two different arities.
But yes, it is not tail recursive, so in real life you would go with reduce or loop/recur
I am having a hard time tracking down a stackoverflow error produced by my clojure implementation of the Bron-Kerbosch algorithm.
Below is my implementation of the algorithm itself, and here is a link to a SSCCE outlining the issue http://pastebin.com/gtpTT4B4.
(defn Bron-Kerbosch [r p x graph cliques]
;(println (str "R:" r " P:" p " X:" x " Clq:" cliques))
(cond (and (empty? p) (empty? x)) (concat cliques r)
:else
(let [neigh (neighV graph (dec (count p)))]
(loop [loop-clq '(cliques)
loop-cnt (dec (count p))
loop-p '(p)
loop-x '(x)]
(cond (= -1 loop-cnt) loop-clq
:else
(recur (concat loop-clq
(Bron-Kerbosch (concat r loop-cnt)
(concat p neigh)
(filter (set x) neigh)
graph cliques))
(dec loop-cnt)
(filter (set p) loop-cnt)
(concat x loop-cnt)))))))
I would have to assume that the issue obviously lies within one of my two bootstrap conditions (cond (and (empty? p) (empty? x)) and (cond (= -1 loop-cnt) because the function algorithm is recursive.
Though this assumes that I am building the lists x r p correctly. Judging by the output of the commented out print statement (cliques is always printed as an EmptyList) I assume that my list comprehension might also be the issue.
Along the same lines, the other issue I can somewhat see is that I am not actually calling the algorithm properly in the BK-Call function (in the SSCCEE).
My overall question is what is causing this? Though this is somewhat too open, another question that might lead me to my answer is how I might go about using the print statement on the first line.
When the print statement is uncommented it produces the output
R:clojure.lang.LazySeq#2044e0b9 P:clojure.lang.LazySeq#7f9700a5 X:clojure.lang.LazySeq#1 Clq:clojure.lang.PersistentList$EmptyList#1
I assume that if I could see that x r p are at each call I might be able to see where the algorithm is going wrong.
Can anyone point me in the right direction?
EDIT: The neighV function from the SSCCE
(defn neighV [graph nodenum]
(let [ret-list (for [i (range (count graph)) :when (contains? (graph i) nodenum)] i)]
ret-list))
EDIT2: Noisesmith's answers had gotten me closer to the solution and made sense to me. I wrapped all of my concat in doall. After trying to call the function again I was getting "Cannot cast Long to Seq" errors, I figured that these stemmed from trying to concat loop-cnt onto lists in the function
fptests.core> (BK-Call (sanity1))
IllegalArgumentException Don't know how to create ISeq from: java.lang.Long clojure.lang.RT.seqFrom (RT.java:505)
fptests.core> (concat 1 '(2 3))
IllegalArgumentException Don't know how to create ISeq from: java.lang.Long clojure.lang.RT.seqFrom (RT.java:505)
So I then wrapped each loop-cnt in a '() to turn it into a list before it is concat
fptests.core> (concat '(1) '(2 3))
(1 2 3)
Which, after I made all of these changes, I ended back at my stack overflow.. Here is the new Bron-Kerbosch function with all of the edits. I guess I now have the same questions as I did before..
Though the new ones are, did I implement that changes that I should have correctly, does the usage of '() make sense to fix the issue that came up after implementing noisesmith's changes?
(defn Bron-Kerbosch1 [r p x graph cliques]
(cond (and (empty? p) (empty? x)) (doall (concat cliques r))
:else
(let [neigh (neighV graph (dec (count p)))]
(loop [loop-clq '(cliques)
loop-cnt (dec (count p))
loop-p '(p)
loop-x '(x)]
(cond (= -1 loop-cnt) loop-clq
:else
(recur (doall (concat loop-clq
(Bron-Kerbosch1 (doall (concat r '(loop-cnt)))
(doall (concat p neigh))
(filter (set x) neigh)
graph cliques)))
(dec loop-cnt)
(filter (set p) '(loop-cnt))
(doall (concat x '(loop-cnt)))))))))
EDIT3: After patiently waiting for my prn statements to stop (not sure why I put them in when I knew it was in a SO) I found that most if not all statements printed were along the lines of
"R:" (loop-cnt loop-cnt loop-cnt loop-cnt loop-cnt loop-cnt loop-cnt ...)
"P:" (range (count graph) 0 2 3) " X:" () " Clq:" ()
After inspecting this some I realized that I have not been recursively calling the function properly. I have been union'ing items to P instead of removing them. This causes P to continuously grow. This is most likely the cause of my stack overflow. Though there are still some issues. I still am creating a stackoverflow, yet again.
Once I fixed my issue of continuing to union to P my issue is that when I concat loop-cnt it is not, I guess to say, evaluated to a value but it stays as a variable name loop-cnt. I suspect that my stack overflow now lies with my bootstrap condition not being met because it cannot be met if loop-cnt is not evaluated to a number.
So I think my issue now lies with concat loop-cnt to a list as a number and not a variable.
concat is lazy. Recursive calls that build concat on top of concat, without realizing any of the prior layers of laziness, each add to the size of the stack of calls that will be needed to realize the lazy-seq.
Does this concatenation need to be lazy at all? If not, wrap the calls to concat in calls to doall. This will make the concatenation eager, which reduces the size of the call stack needed to realize the final result, and thus eliminating the StackOverflowError.
Also, the correct way to print a lazy-seq and see the contents is prn, you can use pr-str to get the form of the value that pr or prn would use as a string, if needed.
You are misusing quoted lists, I think.
For example, in (defn Bron-Kerbosch1 [ ... ] ... ), '(cliques) evaluates to a list containing the symbol cliques, not to a list containing the argument cliques as its one element. You want (list cliques) for that.
Similar cases abound.
Learning Clojure and trying to understand the implementation:
What's the difference from:
(def factorial
(fn [n]
(loop [cnt n acc 1]
(if (zero? cnt)
acc
(recur (dec cnt) (* acc cnt))
; in loop cnt will take the value (dec cnt)
; and acc will take the value (* acc cnt)
))))
and the following C-like pseudocode
function factorial (n)
for( cnt = n, acc = 1) {
if (cnt==0) return acc;
cnt = cnt-1;
acc = acc*cnt;
}
// in loop cnt will take the value (dec cnt)
// and acc will take the value (* acc cnt)
Are clojure's "loop" and "recur", forms specifically designed to code a simple imperative loop ?
(assuming pseudocode's "for" creates it's own scope, so cnt and acc exists only inside the loop)
Are Clojure's loop and recur forms specifically designed to code a simple imperative loop?
Yes.
In functional terms:
A loop is a degenerate form of recursion called tail-recursion.
The 'variables' are not modified in the body of the loop. Instead,
they are re-incarnated whenever the loop is re-entered.
Clojure's recur makes a tail-recursive call to the surrounding recursion point.
It re-uses the one stack frame, so working faster and avoiding stack
overflow.
It can only happen as the last thing to do in any call - in so-called tail position.
Instead of being stacked up, each successive recur call overwrites the last.
A recursion point is
a fn form, possibly disguised in defn or letfn OR
a loop form, which also binds/sets-up/initialises the
locals/variables.
So your factorial function could be re-written
(def factorial
(fn [n]
((fn fact [cnt acc]
(if (zero? cnt)
acc
(fact (dec cnt) (* acc cnt))))
n 1)))
... which is slower, and risks stack overflow.
Not every C/C++ loop translates smoothly. You can get trouble from nested loops where the inner loop modifies a variable in the outer one.
By the way, your factorial function
will cause integer overflow quite quickly. If you want to avoid
this, use 1.0 instead of 1 to get floating point (double)
arithmetic, or use *' instead of * to get Clojure's BigInt
arithmetic.
will loop endlessly on a negative argument.
A quick fix for the latter is
(def factorial
(fn [n]
(loop [cnt n acc 1]
(if (pos? cnt)
(recur (dec cnt) (* acc cnt))
acc))))
; 1
... though it would be better to return nil or Double.NEGATIVE_INFINITY.
One way to look at loop/recur is that it lets you write code that is functional, but where the underlying implementation ends up essentially being an imperative loop.
To see that it is functional, take your example
(def factorial
(fn [n]
(loop [cnt n acc 1]
(if (zero? cnt)
acc
(recur (dec cnt) (* acc cnt))))))
and rewrite it so that the loop form is broken out to a separate helper function:
(def factorial-helper
(fn [cnt acc]
(if (zero? cnt)
acc
(recur (dec cnt) (* acc cnt)))))
(def factorial'
(fn [n]
(factorial-helper n 1)))
Now you can see that the helper function is simply calling itself; you can replace recur with the function name:
(def factorial-helper
(fn [cnt acc]
(if (zero? cnt)
acc
(factorial-helper (dec cnt) (* acc cnt)))))
You can look at recur, when used in factorial-helper as simply making a recursive call, which is optimized by the underlying implementation.
I think an important idea is that it allows the underlying implementation to be an imperative loop, but your Clojure code still remains functional. In other words, it is not a construct that allows you to write imperative loops that involve arbitrary assignment. But, if you structure your functional code in this way, you can gain the performance benefit associated with an imperative loop.
One way to successfully transform an imperative loop to this form is to change the imperative assignments into expressions that are "assigned to" the argument parameters of the recursive call. But, of course, if you encounter an imperative loop that makes arbitrary assignments, you may not be able to translate it into this form. In this view, loop/recur is a much more constrained construct.
I'm learning Clojure, and I'm trying to solve the Problem 31: Write a function which packs consecutive duplicates into sub-lists.
(= (__ [1 1 2 1 1 1 3 3]) '((1 1) (2) (1 1 1) (3 3)))
I know I can solve this using identity, and in a functional way, but I want to solve it using recursion, because I've not well established this idea in my brain.
My solution would be this:
(defn packing [lista]
(loop [[fst snd :as all] lista mem [] tmp '(fst)]
(print "all is " all "\n\n") ;; something is wrong; it always is an empty list
(if (seq? all)
(if (= fst snd)
(recur (rest all) mem (cons snd tmp))
(recur (rest all) (conj mem tmp) (list snd)))
(seq mem))))
My idea is a recursive loop always taking the first 2 items and comparing. If they are the same number, I include this inside a temporary list tmp; if they're different, I include my temporary list inside men. (This is my final list; a better name would be final_list.)
Because it compares the first 2 items, but at the same time it needs a recursive loop only bypassing the first item, I named the entire list all.
I don't know if the logic is good but inclusive if this was wrong I'm not sure why when I print.
(print "all is " all "\n\n") I receive an empty list
A few points:
'(fst) creates a list containing a symbol fst, not the value of fst, this is one of the reasons to prefer using vectors, e.g., [fst]
you should avoid assuming the input will not be empty
you can use conj for both lists and vectors
destructuring is nestable
(defn packing [coll]
(loop [[x & [y :as more] :as all] coll
result []
same '()]
(if all
(if (= x y)
(recur more result (conj same x))
(recur more (conj result (conj same x)) '()))
result)))
in your code all isn't empty..only happen than is an infinite loop and you always see a empty list...in the firsts lines you can see than it works like expected..
the mistake is in (seq? all) because a empty list is a seq too... try (seq? '()) and return true...then you do a empty loop
you need change this for (empty? all) your code would be
other mistake is '(fst) because it return the simbol fst and not the value...change it for (list fst)
(defn badpacking [lista]
(loop [[fst snd :as all] lista mem [] tmp (list fst)]
(if (empty? all)
(seq mem)
(if (= fst snd)
(recur (rest all) mem (cons snd tmp))
(recur (rest all) (conj mem tmp) (list snd))))))
I would like to transform the following sequence:
(def boollist [true false false false true false true])
Into the following:
[[true] [false false false true] [false true]]
My code leads to a Stackoverflow:
(defn sep [boollst]
(loop [lst boollst
separated [[]]
[left right] (take 2 lst)]
(if (nil? left) separated)
(recur (next lst)
(if (false? left)
(conj (last separated) left)
(conj separated [left]))
(take 2 (next lst)))))
Is there an elegant way of transforming this?
There's probably a much more elegant way, but this is what I came up with:
(defn f
([xs] (f xs [] []))
([[x & xs :as all] acc a]
(if (seq all)
(if x
(recur xs [] (conj a (conj acc x)))
(recur xs (conj acc x) a))
a)))
It just traverses the sequence keeping track of the current vector of falses, and a big accumulator of everything so far.
A short, "clever" solution would be:
(defn sep [lst]
(let [x (partition-by identity lst)]
(filter last (map concat (cons [] x) x))))
The "stack overflow" issue is due to the philosophy of Clojure regarding recursion and is easily avoided if approached correctly. You should always implement these types of functions* in a lazy way: If you can't find a trick for solving the problem using library functions, as I did above, you should use "lazy-seq" for the general solution (like pmjordan did) as explained here: http://clojure.org/lazy
* Functions that eat up a list and return a list as the result. (If something other than a list is returned, the idiomatic solution is to use "recur" and an accumulator, as shown by dfan's example, which I would not consider idiomatic in this case.)
Here's a version that uses lazy evaluation and is maybe a little more readable:
(defn f [bools]
(when-not (empty? bools)
(let
[[l & r] bools
[lr rr] (split-with false? r)]
(lazy-seq (cons
(cons l lr)
(f rr))))))
It doesn't return vectors though, so if that's a requirement you need to manually pass the result of concat and of the function itself to vec, thus negating the advantage of using lazy evaluation.
The stack overflow error is because your recur is outside of the if. You evaluate the if form for side effects, then unconditionally recur. (feel free to edit for format, I'm not at a real keyboard).