Reputation: 2411
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)
Upvotes: 1
Views: 141
Reputation: 2411
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)))
Upvotes: 1
Reputation: 17859
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)
Upvotes: 1
Reputation: 45760
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.
Upvotes: 2