What's expecting a function in this clojure code? - clojure

going through the exercises in the fp-oo book and i'm having trouble with an early exercise to add squares. Here's my code:
(defn square [n]
(* n n))
(defn add-squares [l]
(cond
(nil? l) 0
:else (+ (square (first (l))) (add-squares (rest (l))))))
This example:
(add-squares '(2 2 2 2))
should return
16
but fails with this exception:
ClassCastException clojure.lang.PersistentList cannot be cast to clojure.lang.IFn user/add-squares (NO_SOURCE_FILE:4)
which i guess means i'm trying to pass a function somewhere instead of a list which was expected. Can someone tell me which part of the code is the culprit?
Thanks,
James

This is wrong:
(first (l))
This means that you are calling l as a function.
You should use:
(first l)
And of course, the same thing for (rest (l))

Related

What's wrong with this Clojure function? [duplicate]

This question already has an answer here:
Wrong number of args (0) passed to: PersistentVector on loop/recur function
(1 answer)
Closed last year.
I'am new to clojure and i wrote this func:
(def fact (fn [n] (
(apply * (drop 1 (range n))))))
When calling it i get the error:
ClassCastException class java.lang.Long cannot be cast to class clojure.lang.IFn (java.lang.Long is in module java.base of loader 'bootstrap'; clojure.lang.IFn is in unnamed module of loader 'app') my-stuff.core/fact (form-init3352210926102455316.clj:18)
Why?
You've got an extra parenthesis around apply:
(def fact (fn [n]
(apply * (drop 1 (range n)))))
There's extra pair of parentheses- when you call for example (fact 3), result will be (2) (not list, but call of function) and 2 isn't function, so it throws error.
When you remove these parentheses, like this:
(def fact (fn [n]
(apply * (drop 1 (range n)))))
, call (fact 3) returns 2- but is this result correct? If you want to return factorial for given number, you have to use range correctly:
(defn fact [n]
(->> (range 1 (inc n))
(apply *)))
(->> is thread-last macro)
Example:
(fact 3)
=> 6

Implement range function in clojure return error

I am trying to implement the range function in clojure, but my implementation is returning an error that I cannot understand. Here it is:
(defn implement-range [a b] (
if (= a b)
(conj nil b)
((conj nil a) (implement-range (inc a) b))))
I am trying to do in a recursive way, it is not complete yet, since I am stuck with this error:
ClassCastException clojure.lang.PersistentList cannot be cast to clojure.lang.IFn user/implement-range
I think that it is a parentheses problem that I cannot see (I am a newbie in clojure :) ). Any ideas?
Thanks in advance for any help
EDIT:
I would like to return something like (1 2 3 4) if I call the function like this:
(implement-range 1 5)
You were close:
(defn implement-range [a b]
(if (>= a b)
'()
(conj (implement-range (inc a) b) a)))
(implement-range 0 5)
=> (0 1 2 3 4)
First, the main problem is that ((conj nil a) (implement-range (inc a) b)))) is attempting to call (conj nil a) as a function, with (implement-range (inc a) b) as the argument. I'm not entirely sure what you're trying to do here, but this definitely isn't what you want.
I made three changes:
You need to conj the current number to the result of the recursive call. This is "unsafe" recursion since the recursive call isn't in tail position, but while messing around, that's not a big deal. You'll want to use an alternate method though if you intend to use this for real.
If you enter a b that is larger than a, it will explode. I fixed this by changing the base case condition.
Your base case didn't make any sense. Once the recursion stops, you'll want to add to an empty list.
Just a side note, any time you see ((, little alarm bells should go off. This is often a sign of a problem, unless you're getting fancy and writing something like ((comp str inc) 1); where the first form in the expression evaluates to a function.
the simplest (and the most classic one) would be something like this:
(defn implement-range [a b]
(when (< a b)
(cons a (implement-range (inc a) b))))
user> (implement-range 1 20)
;;=> (1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19)
I did some research and found that use conj this way does not make any sense. So I came up with this:
(defn implement-range [a b] (
if (= a b)
b
(flatten (list a (implement-range (inc a) b)))))
So if I call the function with the 1 4 parameters the result will be:
(1 2 3 4)
But, since I am trying to implement a function such like the range function, it needs to remove the last element yet.
EDIT 1
The final function that I wrote looked like this:
(defn implement-range [a b] (
if (= a b)
nil
(remove nil? (flatten (list a (implement-range (inc a) b))))))
EDIT 2
After some more research I've figured out another way to solve this, with less lines of code:
(defn new-range [a b]
(take (- b a) (iterate inc a)))

Tracking down a StackOverflow in a Clojure program, contains SSCCE

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.

Deep-Reverse Clojure

I'm trying to implement deep-reverse in clojure. If lst is (1 (2 (3 4 5)) (2 3)), it should return ((3 2) ((5 4 3) 2) 1). This is what I have so far:
defn dRev [lst]
( if (= lst ())
nil
( if (list? (first lst))
( dRev (first lst) )
( concat
( dRev (rest lst)) (list (first lst))
)
)
)
)
However, my implementation only works if the nested list is the last element, but the resulted list is also flattened.
For eg: (dRev '(1 2 (3 4)) will return (4 3 2 1).
Otherwise, for eg: (dRev '(1 (2 3) 4)) will return (3 2 1) only.
I hit this brick wall for a while now, and I can't find out the problem with my code. Can anyone please help me out?
The other answer gave you the best possible implementation of a deep-reverse in Clojure, because it uses the clojure.walk/postwalk function which generalizes the problem of deep-applying a function to every element of a collection. Here I will instead walk you through the problems of the implementation you posted.
First, the unusual formatting makes it hard to spot what's going on. Here's the same just with fixed formatting:
(defn dRev [lst]
(if (= lst ())
nil
(if (list? (first lst))
(dRev (first lst))
(concat (dRev (rest lst))
(list (first lst))))))
Next, some other small fixes that don't yet fix the behaviour:
change the function name to conform to Clojure conventions (hyphenation instead of camel-case),
use the usual Clojure default name for collection parameters coll instead of lst,
use empty? to check for an empty collection,
return () in the default case because we know we want to return a list instead of some other kind of seq,
and use coll? instead list? because we can just as well reverse any collection instead of just lists:
(If you really want to reverse only lists and leave all other collections as is, reverse the last change.)
(defn d-rev [coll]
(if (empty? coll)
()
(if (coll? (first coll))
(d-rev (first coll))
(concat (d-rev (rest coll))
(list (first coll))))))
Now, the formatting fix makes it obvious what's the main problem with your implementation: in your recursive call ((d-rev (first coll)) resp. (dRev (first lst))), you return only the result of that recursion, but you forget to handle the rest of the list. Basically, what you need to do is handle the rest of the collection always the same and only change how you handle the first element based on whether that first element is a list resp. collection or not:
(defn d-rev [coll]
(if (empty? coll)
()
(concat (d-rev (rest coll))
(list (if (coll? (first coll))
(d-rev (first coll))
(first coll))))))
This is a working solution.
It is terribly inefficient though, because the concat completely rebuilds the list for every element. You can get a much better result by using a tail-recursive algorithm which is quite trivial to do (because it's natural for tail-recursion over a sequence to reverse the order of elements):
(defn d-rev [coll]
(loop [coll coll, acc ()]
(if (empty? coll)
acc
(recur (rest coll)
(cons (if (coll? (first coll))
(d-rev (first coll))
(first coll))
acc)))))
As one final suggestion, here's a solution that's halfways towards the one from the other answer by also solving the problem on a higher level, but it uses only the core functions reverse and map that applies a function to every element of sequence but doesn't deep-recurse by itself:
(defn deep-reverse [coll]
(reverse (map #(if (coll? %) (deep-reverse %) %) coll)))
You can build what you are writing with clojure.walk/postwalk and clojure.core/reverse. This does a depth-first traversal of your tree input and reverses any seq that it finds.
(defn dRev [lst]
(clojure.walk/postwalk #(if (seq? %) (reverse %) %) lst))
Here is my version of the problem, if you enter something like this:
(deep-reverse '(a (b c d) 3))
It returns
=> '(3 (d c b) a)
The problem is taken from Ninety-Nine Lisp Problems
My code ended up like this, though, they might be better implementations, this one works fine.
(defn deep-reverse
"Returns the given list in reverse order. Works with nested lists."
[lst]
(cond
(empty? (rest lst)) lst
(list? (first lst)) (deep-reverse(cons (deep-reverse (first lst)) (deep-reverse (rest lst))))
:else
(concat (deep-reverse (rest lst)) (list (first lst)))))
Hope this is what you were looking for!

Error with variadic function in Clojure

I am trying to write a custom max function in Clojure, which should support one or more arguments. However, I am running into an error that I cannot figure out. Here is the below function:
(defn my-max [arg & rest]
(loop [m arg c rest]
(cond (empty? c) m
(> m (first c)) (recur m (rest c))
:else (recur (first c) (rest c)))))
And I encounter the following error when attempting to evaluate the function:
user> (my-max 2 3 1 4 5)
ClassCastException clojure.lang.ArraySeq cannot be cast to clojure.lang.IFn user/my-max (NO_SOURCE_FILE:5)
I thought this would work because I was under the assumption that rest was just a sequence. I was able to get this function to work without a variadic signature, where the argument is simply a sequence:
(defn my-max [coll]
(loop [m (first coll) c (rest coll)]
(cond (empty? c) m
(> m (first c)) (recur m (rest c))
:else (recur (first c) (rest c)))))
The problem appears to be a name collision. You have used the name rest for the tail sequence of your calling arguments. Then you subsequently try to use the function rest, but that sequence is seen instead.