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

Fie*_*Cod 3 clojure

我从4clojure.com做任务时遇到了问题.以下是任务说明:

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

我用以下代码解决了它:

#(first (reverse %))
Run Code Online (Sandbox Code Playgroud)

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

#(0 (reverse %))
Run Code Online (Sandbox Code Playgroud)

我收到了一个错误:

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

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

编辑1: 即使以下代码不起作用,我想APersistentVector是第一个.

#((reverse %) 0)
Run Code Online (Sandbox Code Playgroud)

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

(#((vec (reverse %)) 0)[1 2 3])
Run Code Online (Sandbox Code Playgroud)

Jos*_*osh 8

如果你看一下APersistentVector的代码,你会看到:

public abstract class APersistentVector extends AFn ...
Run Code Online (Sandbox Code Playgroud)

AFn实现IFn,它扩展了java CallableRunnable接口,这意味着可以将clojure持久向量作为函数调用,并将该参数用作要检索的索引.你可以在这里看到:

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

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

({:a 1 :b 2} :b)  ;; 2
(#{:a :b} :a)     ;; :a
([1 2 3 4] 0)     ;; 1
Run Code Online (Sandbox Code Playgroud)

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

(ancestors (class 42))
=>
#{java.lang.Comparable
  java.lang.Number
  java.lang.Object
  java.io.Serializable}
Run Code Online (Sandbox Code Playgroud)

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

  • 您将注意到当您尝试将该函数应用于序列时给出的错误:`ClassCastException clojure.lang.PersistentList无法强制转换为clojure.lang.IFn`.`reverse`不返回向量; 它返回一个`PersistentList`,并且列表没有实现`IFn`(一个原因是列表不是关联的,即它们不能通过像向量这样的索引访问)@FieryCod (2认同)