Factorial iterative illegal argument - clojure - clojure

(defn fac [n]
(def result 1)
(loop [i n c 1]
(if (<= c 5)
result
(recur (* c i) (inc c))
)
)
(println result)
)
(fac 5)
Error:Exception in thread "main" java.lang.IllegalArgumentException: loop requires a vector for its binding.
I am trying to write a function that evaluates a numbers factorial. Where is my mistake? It gives me 1 as answer

At first sight:
Don't use a def inside a defn.
The REPL will print the result of evaluating a function. Use it.
This gets us to
(defn fac [n]
(loop [i n c 1]
(if (<= c 5)
result
(recur (* c i) (inc c)))))
... which doesn't compile, because result is floating.
There are a few corrections required:
Return i, not result.
Start i at 1, not n.
Turn the test around: > instead of <=.
We end up with
(defn fac [n]
(loop [i 1, c 1]
(if (> c n)
i
(recur (* c i) (inc c)))))
... which works:
(fac 5)
=> 120
Edited to correct one-off error and improve explanation.

Related

Clojure: Why surrounding an expression with extra parenthesis gives NullPointerException [duplicate]

Trying to define a factors function that will return a vector of all the factors of a number using loop/recur.
;; `prime?` borrowed from https://swizec.com/blog/comparing-clojure-and-node-js-for-speed/swizec/1593
(defn prime? [n]
(if (even? n) false
(let [root (num (int (Math/sqrt n)))]
(loop [i 3] (if (> i root) true
(if (zero? (mod n i)) false
(recur (+ i 2))))))))
(defn factors [x] (
(loop [n x i 2 acc []]
(if (prime? n) (conj acc n)
(if (zero? (mod n i)) (recur (/ n i) 2 (conj acc i))
(recur n (inc i) acc))))))
But I keep running into the following error:
ArityException Wrong number of args (0) passed to: PersistentVector clojure.lang.AFn.throwArity
I must be missing something obvious here. Any suggestions are much appreciated!
Let me move the whitespace in your code so it's obvious to you what is wrong:
(defn factors [x]
((loop [n x i 2 acc []]
(if (prime? n) (conj acc n)
(if (zero? (mod n i)) (recur (/ n i) 2 (conj acc i))
(recur n (inc i) acc))))))
You see that weird (( at the start of your function? What's that all about? Remember that in Clojure, as in lisps in general, parentheses are not a grouping construct! They are a function-call mechanism, and you can't just throw extras in for fun. Here, what you wrote has the following meaning:
Run this loop that will compute a vector.
Call the resulting value as a function, passing it no arguments.

Wrong number of args (0) passed to: PersistentVector on loop/recur function

Trying to define a factors function that will return a vector of all the factors of a number using loop/recur.
;; `prime?` borrowed from https://swizec.com/blog/comparing-clojure-and-node-js-for-speed/swizec/1593
(defn prime? [n]
(if (even? n) false
(let [root (num (int (Math/sqrt n)))]
(loop [i 3] (if (> i root) true
(if (zero? (mod n i)) false
(recur (+ i 2))))))))
(defn factors [x] (
(loop [n x i 2 acc []]
(if (prime? n) (conj acc n)
(if (zero? (mod n i)) (recur (/ n i) 2 (conj acc i))
(recur n (inc i) acc))))))
But I keep running into the following error:
ArityException Wrong number of args (0) passed to: PersistentVector clojure.lang.AFn.throwArity
I must be missing something obvious here. Any suggestions are much appreciated!
Let me move the whitespace in your code so it's obvious to you what is wrong:
(defn factors [x]
((loop [n x i 2 acc []]
(if (prime? n) (conj acc n)
(if (zero? (mod n i)) (recur (/ n i) 2 (conj acc i))
(recur n (inc i) acc))))))
You see that weird (( at the start of your function? What's that all about? Remember that in Clojure, as in lisps in general, parentheses are not a grouping construct! They are a function-call mechanism, and you can't just throw extras in for fun. Here, what you wrote has the following meaning:
Run this loop that will compute a vector.
Call the resulting value as a function, passing it no arguments.

Generator pattern code can't return value

I want to create a generator to do, 1 2 3 4.
(defn getNums []
(loop [i 4
r []]
(when (<= i 0)
r ;<--- point A
(recur (dec i)
(conj r i)))))
(getNums) ;Eval to nil.
Nothing get return, why ?
Would the code in point A return result vector r ?
when, is a clojure macro defined as:
(when test & body)
So, in your first example, the body of when would be:
(do
r
(recur (dec i)
(conj r i)))
The when test itself is evaluated to false so the body of the when macro is not executed.
The return value of the function it therefore the return value of when itself is return, which is nil. Ex:
(when (< 2 1)) ; nil
By the way, there is a build in function range that does the same as your method:
(range 1 10)
And, in a more generic way, you could use the lazy function iterate:
(take 10 (iterate inc 1))
(defn getNums []
(loop [i 4
r []]
(if (<= i 0)
r
(recur (dec i)
(cons i r)))))
(getNums)

How to call one defn function in another defn and how to debugging in Clojure

I am having a problem running my program in Clojure. I just start learning Clojure a couple of weeks ago. So I don't know the quick and easy way to debug a Clojure program. My func2 raises an exception at (adj(a b)) as followed:
ClassCastException java.lang.Long cannot be cast to clojure.lang.IFn
user/func2.
I don't know what is wrong with it. Can someone point out the problem with my coding?
And in func3, I call func2 recursively, but it throws:
ArityException Wrong number of args (0) passed to: PersistentVector
clojure.lan g.AFn.throwArity (AFn.java:437)
What is wrong with func3? Thank you.
(defn adj [value1 value2]
(def result (+ (/ value1 2) (/ value2 2)))
(if (= (mod result 2) 1)
(+ result 1)
result
)
)
(defn func2 [list]
(let [[a b c d] list]
(inc d)
([(adj c a) (adj a b) (adj b c) d]))
)
(defn func3 [list]
(loop [v list r []]
(if(= (v 0) (v 1) (v 2))
(conj list r)
(func3(func2(list)))
))
)
What's the intended result of these functions? We probably need to see some sample inputs and expected results to really be able to help you.
Here's my attempt at cleaning them up. I've noted the changes I made as comments. func3 has the most serious problem in that it's an infinite recursion - there's no end condition. What should cause it to stop working and return a result?
(defn adj [value1 value2]
;; don't use def within functions, use let
(let [result (+ (/ value1 2) (/ value2 2))]
(if (= (mod result 2) 1)
(+ result 1)
result)))
(defn func2 [list]
(let [[a b c d] list]
;; The extra parens around this vector were causing it
;; to be called as a function, which I don't think is
;; what you intended:
[(adj c a) (adj a b) (adj b c) d]))
;; This needs an end condition - it's an infinite recursion
(defn func3 [list]
(loop [v list r []]
(if (= (v 0) (v 1) (v 2))
(conj list r)
;; Removed extra parens around list
(func3 (func2 list)))))
The reason I say not to use def within functions is that it always creates a global function. For local bindings you want let.
Regarding the extra parens, the difference between [1 2 3] and ([1 2 3]) is that the former returns a vector containing the numbers 1, 2, and 3, whereas the latter tries to call that vector as a function. You had excess parens around the literal vector in func2 and around list in func3, which was causing exceptions.
As a style note, the name list isn't a good choice. For one thing, it's shadowing clojure.core/list, and for another you're probably using vectors rather than lists anyway. It would be more idiomatic to use coll (for collection) or s (for sequence) as the name.
This would suggest at least one other change. In func3 you use a vector-only feature (using the vector as a function to perform lookup by index), so to be more general (accept other data structures) you can convert to a vector with vec:
(defn func3 [coll]
(loop [v (vec coll) r []]
(if (= (v 0) (v 1) (v 2))
(conj v r)
(func3 (func2 v)))))
Oh, there is no need to debug that. I suggest you have a look at LightTable.
The first two functions are easily fixed:
(defn adj [value1 value2]
;(def result (+ (/ value1 2) (/ value2 2))) def creates a global binding in current namespace !!!
(let [result (+ (/ value1 2) (/ value2 2))]
(if
(= (mod result 2) 1)
(inc result)
result)))
(defn func2 [xx]
(let [[a b c d] xx]
[ (adj c a) (adj a b) (adj b c) (inc d)]
))
The third function is not clear to me. I don't read your intent. What I understand is: "Keep applying func2 to itself until the first three elements of its result are equal." But I'm afraid this condition is never met, so I replaced it with a true in order to see just one result without blowing the stack.
(defn func3 [xx]
(loop [ v (func2 xx) ]
(if
;(= (v 0) (v 1) (v 2))
true
v
(recur (func2 v))
)))
Useful link: http://clojure.org/cheatsheet
Cheers -

Why am I getting a cast error when trying to use Simpson's rule in Clojure?

I'm trying to work through some of the exercises in SICP using Clojure, but am getting an error with my current method of executing Simpson's rule (ex. 1-29). Does this have to do with lazy/eager evalution? Any ideas on how to fix this? Error and code are below:
java.lang.ClassCastException: user$simpson$h__1445 cannot be cast to java.lang.Number
at clojure.lang.Numbers.divide (Numbers.java:139)
Here is the code:
(defn simpson [f a b n]
(defn h [] (/ (- b a) n))
(defn simpson-term [k]
(defn y [] (f (+ a (* k h))))
(cond
(= k 0) y
(= k n) y
(even? k) (* 2 y)
:else (* 4 y)))
(* (/ h 3)
(sum simpson-term 0 inc n)))
You define h as a function of no arguments, and then try to use it as though it were a number. I'm also not sure what you're getting at with (sum simpson-term 0 inc n); I'll just assume that sum is some magic you got from SICP and that the arguments you're passing to it are right (I vaguely recall them defining a generic sum of some kind).
The other thing is, it's almost always a terrible idea to have a def or defn nested within a defn. You probably want either let (for something temporary or local) or another top-level defn.
Bearing in mind that I haven't written a simpson function for years, and haven't inspected this one for algorithmic correctness at all, here's a sketch that is closer to the "right shape" than yours:
(defn simpson [f a b n]
(let [h (/ (- b a) n)
simpson-term (fn [k]
(let [y (f (+ a (* k h)))]
(cond
(= k 0) y
(= k n) y
(even? k) (* 2 y)
:else (* 4 y))))]
(* (/ h 3)
(sum simpson-term 0 inc n))))