这个 Clojure 表单是如何工作的?从另一个列表中删除一个列表

How does this Clojure form work? Removing a list from another list

我正在为 class 做一个项目,我偶然发现了一些被证明有用的代码,尽管我不确定下面的行如何 "reads"。我了解它所做的结果,但不知道它是如何做到的。

(remove #(some (partial = %) '(1 2 3 4)) '(1 2 3 5 6 7))

它所做的是尽可能从第二组中删除第一组中的值。因此,给定两个集合 PV,它会找到 P / V

我想我正在寻找关于正在发生的事情的英语句子?

编辑:标题。我也确实理解 remove 的作用,给定一些谓词,例如 pos? 它 returns 一个惰性的项目序列,当应用谓词时等同于 true 。

我特别不明白的是 #(some (partial = %)) 如何计算谓词。

#(some (partial = %) '(1 2 3 4))

...是...

的语法糖
(fn [x] (some (partial = x) '(1 2 3 4))

...所以,调用

(#(some (partial = %) '(1 2 3 4)) 5)

...运行...

(some (partial = 5) '(1 2 3 4))

...因此,运行 (partial = 5) 针对 '(1 2 3 4) 中的每个条目,直到找到匹配项 - 因此:(= 5 1)(= 5 2),等等——并且 returning nil 当没有匹配 returned.

nil 是错误的。因此,任何不存在匹配的序列元素将为 return 假,并被 remove 保留,而对于任何存在匹配的元素,谓词将为 return 真并被删除。


显然,为一个序列中的每个项目创建一个 lambda 函数并根据另一个序列的内容评估这些函数与实集算法相比 极其 效率低下。因此,在项目数量可能不多的任何情况下都不应该使用此代码。

改为:

(clojure.set/difference
  #{1 2 3 4 5 6 7}
  #{1 2 3 4})

...将是有效且惯用的方法。如果您从列表而不是集合文字开始,则可以将其替换为 (clojure.set/difference (into #{} list-a) (into #{} list-b))(clojure.set/difference (set list-a) (set list-b)).