为什么`(a)读为列表,而`(a b)不是?

时间:2015-03-18 20:20:09

标签: list clojure lisp cons

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

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

理论上,我理解为什么第二种形式会返回false,即该对象 实际上是clojure.lang.Cons。但实际上,我并不是这样 理解为什么 正在发生。

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

2 个答案:

答案 0 :(得分:2)

list?实际上是非常有限的功能。事实上,我还没有看到使用list?的Clojure代码,而它最多只是一个糟糕的选择,更常见的是错误的原因。

如果您想知道某些内容是否“有点”,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 |

答案 1 :(得分:2)

当读者遇到语法引用的表单时,结果是一个集合,它将iterate over each element and call syntax-quote recursively。结果为cons,以nil开头。

因此,问题归结为以下原因:

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

这似乎是一个定义问题。