为什么我可以在clojure中使用set作为谓词?

时间:2014-12-22 02:12:05

标签: clojure functional-programming

我试图从列表或集合中删除元素,如下所示:

(remove :Veronica (list :Veronica :Hailey))

它不起作用,所以,我去删除文档,说我需要将谓词传递给remove函数。但是以下代码有效:

(remove #{:foo} [:foo :bar])
(remove #{:foo} (list :foo :bar))

#{:foo}是一个集合。它为什么有用?

是一个功能集吗?

由于

3 个答案:

答案 0 :(得分:7)

为什么以下

(remove :Veronica (list :Veronica :Hailey))
;(:Veronica :Hailey)
  • 通过集合?
  • 没有明显效果?

:Veronica之类的关键字是接受一个参数的函数,因此可以用作谓词。

但是......

  • 它需要一个map或set参数。
  • 然后它在论证中查明自己。

例如,

(:Veronica #{:Veronica})
;:Veronica

(:Veronica #{1 2 "Buckle my shoe"})
;nil

它也原谅了无用的论据:

(:Veronica 4) ; 4 is not a map or set. 
;nil

因此(:Veronica :Veronica)(:Veronica :Hailey)都是nil,所以<{p>}中的remove

(remove :Veronica (list :Veronica :Hailey))

...什么都不做,因为谓词总是评估false(ish)。


其他解决方案解释了原因

(remove #{:foo} (list :foo :bar))

...有你想要的效果。

答案 1 :(得分:3)

集合是其成员的功能。如果参数是集合的成员,则返回成员。如果参数不是集合的成员,则返回nil。这是在Clojure文档的Data Structures页面末尾记录的。引用该页面:

(def s #{:a :b :c :d})

(s :b)
-> :b

(s :k)
-> nil

答案 2 :(得分:2)

Clojure集和地图可以作为一种功能。

user=> (#{:foo} :foo)
:foo
user=> (#{:foo} :bar)
nil

因此,在您的代码中,#{:foo}作为一个函数工作,与

基本相同
(remove (fn [x] (#{:foo} x)) [:foo :bar])

有关详情,请参阅:Clojure: Using Sets and Maps as Functions