Reputation: 13
I am new to clojure, and am trying to understand how to concatenate lists without using the concat function.
(defn append [list1, list2]
(cond
(nil? list1) list2
:else (cons (first list1)
(append (rest list1) (list2)))))
When I run the above code, I get:
ClassCastException clojure.lang.PersistentList cannot be cast
to clojure.lang.IFn user/append
Reading from previous stackoverflow questions, it is because the cond
expression is in double parentheses. I don't believe that I do.
Why am I still getting this error?
Upvotes: 1
Views: 444
Reputation: 9865
(defn append
[l1 l2 & [acc]]
(cond (and (empty? l1) (empty? l2)) (reverse acc)
(empty? l1) (append l1 (rest l2) (cons (first l2) acc))
:else (append (rest l1) l2 (cons (first l1) acc))))
or:
(defn append
([l1 l2]
(append l1 l2 '()))
([l1 l2 acc]
(cond (and (empty? l1) (empty? l2)) (reverse acc)
(empty? l1) (append l1 (rest l2) (cons (first l2) acc))
:else (append (rest l1) l2 (cons (first l1) acc)))))
;; or using vectors and conj
(defn vec-append
[v1 v2]
(cond (empty? v2) v1
:else (vec-append (conj v1 (first v2)) (rest v2))))
(defn append
[l1 l2]
(seq (vec-append (vec l1) (vec l2))))
Upvotes: 0
Reputation: 29958
In Clojure, parentheses mean "function call". Thus the expression:
(list2)
means call a function that the list2
variable points at. This is the source of the error and the message clojure.lang.PersistentList cannot be cast to clojure.lang.IFn
Notes:
cond
has only 2 branches, it is usually clearer to just a plain if
expression.rest
and next
: (rest []) => ()
(next []) => nil
You may wish to carefully study the Clojure CheatSheet and other documention listed here.
Upvotes: 3