我是clojure的新手,我一直在尝试不同的程序。这是我的计划:
(defn sdsu-reverse [x]
(loop [n (count x) x x]
(if (= 0 n)
(x)
(recur (- n 1) (conj (next x) (first x))))))
(= (sdsu-reverse [1 2 3 4 5]) [5 4 3 2 1])
我遇到了错误:java.lang.ClassCastException:clojure.lang.Cons无法强制转换为clojure.lang.IFn C:\ Users \ Shalima \ Documents \ Textbooks \ Functional Programming \ Programs \ sample.clj:44 user / sdsu-reverse
但我似乎无法弄明白。你能帮帮我吗?
谢谢。
答案 0 :(得分:1)
正如Alex上面所述,您需要在if表达式中将(x)
替换为x
。在括号中包装x会将其视为一个函数,而不是要返回一个值。
至于代码中的其他问题:
conj
是一个有点令人困惑的功能。
clojure.core/cons
([x seq])
Returns a new seq where x is the first element and seq is
the rest.
听起来很清楚。但请看一下将conj
应用于列表与向量(source)时会发生什么。
user=> (conj [1 2 3] 4)
[1 2 3 4]
user=> (conj '(1 2 3) 4)
(4 1 2 3)
其原因与如何构造vector和list数据类型有关。向量从右侧接收新值;列表,从左侧。
当您致电conj (next x) (first x)
时,您实际上一遍又一遍地呼叫conj '(2 3 4) '(1)
。所以你最终会得到与你开始时相同的价值。
更好的方法是使用递归,如下所示。
(defn sdsu-reverse [x]
(if (empty? x)
nil
(cons (last x) (sdsu-reverse (drop-last x)))))
我希望这会有所帮助。
编辑以回应列昂尼德的评论。
Leonid是正确的,上面的大序列会失败。或者,您可以执行类似
的操作(defn reverse'
([x] (reverse' x nil))
([x acc] (if (empty? x)
acc
(recur (rest x) (cons (first x) acc)))))
答案 1 :(得分:0)
代码中的类强制转换异常是因为您尝试从常量中创建列表 即(x)所以只需用x替换它就不会获得类别转换异常。