Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Clojure中的ClassCastException_Clojure - Fatal编程技术网

Clojure中的ClassCastException

Clojure中的ClassCastException,clojure,Clojure,我是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.Co

我是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\texties\Functional Programming\Programs\sample.clj:44 user/sdsu reverse

但我似乎无法理解。你能帮我做这个吗


谢谢。

正如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
应用于列表而不是向量()时会发生什么

其原因与向量和列表数据类型的构造方式有关。向量从右侧接收新值;列表,从左侧开始

当你调用
conj(next x)(first x)
时,你实际上是在一次又一次地调用
conj'(2 3 4)
。因此,最终得到的值与开始时的值相同

更好的方法是使用递归,如下所示

(defn sdsu-reverse [x]
  (if (empty? x)
    nil
    (cons (last x) (sdsu-reverse (drop-last x)))))
我希望这有帮助

编辑以回应Leonid的评论

Leonid是正确的,对于大序列,上述操作将失败。或者你可以做一些类似的事情

(defn reverse' 
  ([x] (reverse' x nil))
  ([x acc] (if (empty? x) 
             acc 
             (recur (rest x) (cons (first x) acc)))))

代码中的类强制转换异常是因为您试图从常量生成列表
i、 e.(x)所以用x替换它就不会出现类强制转换异常。

(x)
尝试调用
x
(这是一个序列)作为函数。您只需要
x
。而且(因为您正在学习),您不需要每次都计算序列。您只想检查它是否为空。@DiegoBasch确实您只想检查它是否为空,但请注意,原始代码只对它计数一次,而不是每次。正确,我想我在比较中看到了计数。OP的代码(至少现在是这样)在循环开始时计数。但是它保留了一个不必要的计数器。使用
recur
总是比使用直接递归好,不仅因为它快得多,而且因为直接递归会导致堆栈溢出。尝试反转类似于
(范围99999)
的东西,你就会明白我的意思。使用
最后一个
删除最后一个
而不是
第一个
休息
也是一个非常糟糕的主意,因为它们在应用于序列时非常无效。同意。修正了我的答案。为了完整起见:还原序列最简单、最有效的方法是使用
reduce
高阶函数:
(reduce conj()x)
,这正是内置的
reverse
函数的工作原理。
(defn reverse' 
  ([x] (reverse' x nil))
  ([x acc] (if (empty? x) 
             acc 
             (recur (rest x) (cons (first x) acc)))))