4

在学习clojure时,我很惊讶地发现这两个对象是不同的类型:

(list? `(inc))   ;; true
(list? `(inc 1)) ;; false

理论上,我理解为什么第二种形式返回 false,那个对象实际上是一个clojure.lang.Cons. 但在实践中,我不明白为什么会这样

为什么读者的阅读`(inc)方式不同`(inc 1)?引擎盖下发生了什么?

4

2 回答 2

2

list?实际上是一个用途非常有限的函数。事实上,我还没有看到使用 Clojure 代码,list?但它充其量是一个糟糕的选择,更常见的是导致错误的原因。

如果您想知道某事是否“listy”,seq?这是一个不错的选择。

在行动:

user=> (pprint/print-table (for [item [[] () `(a) `(a b) (seq [1])]]
                              {'item (pr-str item)
                               'seq? (seq? item)
                               'list? (list? item)
                               'type (type item)}))
|            item |  seq? | list? |                                           type |
|-----------------+-------+-------+------------------------------------------------|
|              [] | false | false |            class clojure.lang.PersistentVector |
|              () |  true |  true |    class clojure.lang.PersistentList$EmptyList |
|        (user/a) |  true |  true |              class clojure.lang.PersistentList |
| (user/a user/b) |  true | false |                        class clojure.lang.Cons |
|             (1) |  true | false | class clojure.lang.PersistentVector$ChunkedSeq |
于 2015-03-19T01:56:51.163 回答
2

当读者遇到一个被语法引用的表单时,它原来是一个集合,它将遍历每个元素并递归地调用语法引用。结果是consed,以 开头nil

所以它归结为为什么以下成立的问题:

> (list? (cons 'inc nil))
true
> (list? (cons 'inc (cons 1 nil)))
false

这似乎是一个定义问题。

于 2015-03-19T12:21:54.483 回答