尝试在函数调用中通过索引获取序列的第一个元素时出错

时间:2017-07-28 16:42:21

标签: clojure

我在4clojure.com执行任务时遇到了问题。 以下是任务说明:

  

编写一个返回序列中最后一个元素的函数。

我使用以下代码解决了这个问题:

#(first (reverse %))

当我想用一些索引更改first函数时。 像这样:

#(0 (reverse %))

我收到了错误:

  

java.lang.ClassCastException:java.lang.Long无法强制转换为   clojure.lang.IFn

我的问题是: 为什么我收到此错误? 我无法得到它,因为例如 ([1 2 3 4] 0)完全有效并返回序列的第一个元素,为什么我不能在函数中使用数组索引?

EDIT1: 即使以下代码也不起作用,我认为APersistentVector是第一个。

#((reverse %) 0)

EDIT2: 我设法通过将从reverse函数返回的列表转换为向量来使其工作。谢谢@Josh

(#((vec (reverse %)) 0)[1 2 3])

1 个答案:

答案 0 :(得分:8)

如果您查看APersistentVector的代码,您会看到:

public abstract class APersistentVector extends AFn ...

AFn实现IFn,它扩展了java的CallableRunnable接口,这意味着可以将clojure持久向量作为函数调用,该参数被用作检索的索引。您可以看到此here

public Object invoke(Object arg1) {
    if(Util.isInteger(arg1))
        return nth(((Number) arg1).intValue());
    throw new IllegalArgumentException("Key must be integer");
}

地图和集合也是如此;它们都可以作为函数调用:

({:a 1 :b 2} :b)  ;; 2
(#{:a :b} :a)     ;; :a
([1 2 3 4] 0)     ;; 1

但是,Long(您的数字为零)未实现IFn

(ancestors (class 42))
=>
#{java.lang.Comparable
  java.lang.Number
  java.lang.Object
  java.io.Serializable}

因此,它不能作为函数调用。