Clojure Koan第8节,#5

时间:2013-04-06 08:51:10

标签: clojure lisp

为什么这有效:

(= '(: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)

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

1 个答案:

答案 0 :(得分:2)

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

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

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

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

'是一个读取宏,它将其参数放入quote特殊形式。 I.e。 'anything => (quote anything)

在你的情况下:

评估=时,必须评估(:anything :goes: here)和/或'(:anything goes here)的值。对第一个的评估将导致:here。 (在其他lisps中,它会导致错误)。 '(:anything :goes :here),但是(quote (:anything :goes :here))的缩写形式,quote是一种特殊形式,可以返回未评估的参数,从而生成列表(: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,从而导致错误。