在Clojure中调用函数(rest [1 [2]])作为参数与使用参数调用([2])不同

时间:2015-08-17 12:43:44

标签: clojure

所以我一直在解决一个4clojure问题,我需要实现这个函数flatten,我正在尝试调试我的解决方案,这是:

(defn fn1 [x]

    (if (not (or (list? x) (vector? x)))
        (list x)
        (if (empty? (rest x))

            (if (not (or (list? x) (vector? x)))
                (list x)
                (fn1 (first x))
            )    

            (if (or (list? (first x)) (vector? (first x)))
                ( concat (fn1 (first x)) (fn1 (rest x)) )
                ( concat (fn1 (list (first x))) (fn1 (rest x)) )
            )

        )
    )
)

在尝试调试时,我遇到了以下行为:

user=> (fn1 (rest [1[2]]))
(([2]))
user=> (rest [1[2]])
([2])
user=> (fn1 '([2]))
(2)

背后的原因是什么?如何绕过它?

2 个答案:

答案 0 :(得分:1)

我的代码中没有太多关注,但看起来是因为

> (type (rest [1 2]))
clojure.lang.PersistentVector$ChunkedSeq
> (vector? (rest [1 2]))
false
> (list? (rest [1 2]))
false
> (seq? (rest [1 2]))
true

因此,如果列表的rest是列表,则向量的rest不是列表或向量, 但是ChunkedSeq

答案 1 :(得分:0)

尽管它们在REPL中呈现相同,但(rest [1 [2]])'([2])具有不同的类型:

(type (rest [1 [2]])) ; clojure.lang.PersistentVector$ChunkedSeq

(type '([2]))         ; clojure.lang.PersistentList

前者回复falselist?,而后者回答true