0

为什么这是有效的:

(= '(:anything :goes :here) (filter (fn [x] true) '(:anything :goes :here)))

但不是这个?

(= (:anything :goes :here) (filter (fn [x] true) '(:anything :goes :here)))

或者

(= (:anything :goes :here) (filter (fn [x] true) (:anything :goes :here)))

甚至

(= '(:anything :goes :here) (filter (fn [x] true) (:anything :goes :here)))

是否有特殊原因要过滤的第二个 arg 是带引号的列表而不是普通列表?

user=> (filter (fn [x] true) (:abc :def :ghi))
IllegalArgumentException Don't know how to create ISeq from: clojure.lang.Keyword  clojure.lang.RT.seqFrom (RT.java:505)

事实上,我仍然不确定列表何时也是函数调用。它似乎与引用有关。除非它们是空列表,否则是否需要引用所有“普通列表”?

4

1 回答 1

2

评估列表时,假定第一个元素是函数(或宏或特殊形式)。

当列表的第一个元素是函数时,首先计算所有参数,然后将函数应用于结果值。

如果列表的第一个元素是宏或特殊形式,则每个参数可能会或可能不会根据宏/特殊形式进行评估。

Clojure 将通过尝试在作为参数给关键字函数的映射中找到该关键字作为关键字来评估其第一个元素是关键字的列表,然后返回相应的值,否则返回下一个参数(如果给定)。从而(:anything :goes: :here)将返回here

'是一个读宏,它把它的参数变成一个quote特殊的形式。 'anything=>(quote anything)

在你的情况下:

=被评估时,(:anything :goes: here)和/或'(:anything goes here)必须被评估的值。评估第一个将导致:here. (在其他 lisps 中会导致错误)。'(:anything :goes :here), 然而是 , 的缩写形式(quote (:anything :goes :here)),并且quote是一种特殊形式,它返回它的参数unevaluate,从而生成列表(:anything :goes: here),然后将其传递给=filter不进行进一步评估。

在每种情况下发生的情况是:

(= '(:anything :goes :here) (filter (fn [x] true) '(:anything :goes :here)))

=与 比较(:anything :goes :here)(:anything :goes :here)结果为真

(= (:anything :goes :here) (filter (fn [x] true) '(:anything :goes :here)))

:here与 比较(:anything :goes :here),结果为假

(= (:anything :goes :here) (filter (fn [x] true) (:anything :goes :here)))
(= '(:anything :goes :here) (filter (fn [x] true) (:anything :goes :here)))

在这两个中,filter都应用于单个关键字:here,导致错误。

于 2013-04-06T09:55:59.287 回答