2
votes

I am VERY green to Clojure. But I am trying to learn the syntax by creating some functions. I am having issues with the parentheses and syntax in general...

This function is supposed to take a list and a position and return the list with that position removed--but I am getting an error that I don't fully understand. I have done some reading and it seems like its an issue with nested parentheses.. but I'm not sure how to fix it.

Any feedback would be greatly appreciated.

The error:

ClassCastException java.lang.Long cannot be cast to clojure.lang.IPersistentCollection clojure.core/conj (core.clj:83)

The code:

(defn delete-at
"accepts a list and position--returns the list with
 value at that position removed"
(
[L, pos]
(cond
  (empty? L) nil
  (zero? pos) (rest L)
  :else (
          delete-at (first L) (rest L) (- pos 1))
  )
)
([L-new, L2, pos]
(cond
  (zero? pos) (conj L-new (rest L2))
  :else (
          (delete-at (conj L-new (first L2)) (rest L2) (- pos 1))
          )
  )
)
)
1
The parentheses in Clojure, or any other Lisp for that matter, are not the same as curly braces in any C-family language. The way you format your code seems to indicate that you believe they are. Take a look here: hitchhikersclojure.com/blog/hitchhikers-guide-to-clojure for an introduction to Clojure syntax. - Rodrigo Taboada

1 Answers

2
votes

giving it a pass through emacs' formatter makes the problem jump out to me: an extra set of () around the last call to delete-at and the arguments to the first conj call are reversed.

(defn delete-at
"accepts a list and position--returns the list with
 value at that position removed"
([L, pos]
 (cond
  (empty? L) nil
  (zero? pos) (rest L)
  :else (delete-at (first L) (rest L) (- pos 1))))
([L-new, L2, pos]
 (cond
  (zero? pos) (conj L-new (rest L2))
  :else ((delete-at (conj L-new (first L2)) (rest L2) (- pos 1))))))

when reading Clojure, lots of stacked closing parens ))))) is normal and looks good to the eye (once you get used to it) and stacked opening parens (( jumps out as suspicious. It mainly comes up when you are calling a function that returns a function, and then you want to call the resulting function.

user> (defn delete-at
 "accepts a list and position--returns the list with
  value at that position removed"
([L, pos]
 (cond
  (empty? L) nil
  (zero? pos) (rest L)
  :else (delete-at (first L) (rest L) (- pos 1))))
([L-new, L2, pos]
 (cond
  (zero? pos) (conj (rest L2) L-new)
  :else (delete-at (conj L-new (first L2)) (rest L2) (- pos 1)))))
#'user/delete-at
user> (delete-at [1 2 3] 1)
(1 3)

It's well worth getting emacs setup with cider, clojure-mode, and paredit (paredit is very useful and getting used to it is a bit of an accomplishment) This is a good place to start learning, and many people choose to use a starter kit of some sort such as emacs starter kit or emacs live