如何解释在 clojure 中使用 fn 的 merge-with ?

Cya*_*ide 1 backend clojure

我目前正在学习 Clojure,我是一个完全的初学者,我希望能得到一些帮助理解。我今天浏览了一些代码并发现了这一点。

(let [timepoints (merge-with (fn [mf swt] [mf swt]) timepoint-max timepoint-sum )])
Run Code Online (Sandbox Code Playgroud)

哪里mf, swt, timepoint-max and timepoint-sum看起来像

{"Timepoint1": 3, "Timepoint2": 2}
Run Code Online (Sandbox Code Playgroud)

那么上面的代码做了什么?

我知道我们将变量设置timepoints为两个映射之间的某种联合(?)。但我对这fn [mf swt] [mf swt]部分特别困惑。

Rul*_*lle 6

该表达式(fn [mf swt] [mf swt])是一个匿名 clojure 函数,它根据传递给它的两个参数构造一个向量,例如

((fn [mf swt] [mf swt]) :a :b)
;; => [:a :b]
Run Code Online (Sandbox Code Playgroud)

该表达式是对带有第一个参数、第二个参数和第三个参数的函数merge-with(merge-with (fn [mf swt] [mf swt]) timepoint-max timepoint-sum )的调用。下面是我们将和绑定到一些示例值的示例:(fn [mf swt] [mf swt])timepoint-maxtimepoint-sumtimepoint-maxtimepoint-sum

(def timepoint-max {:x 0 :y 1})
(def timepoint-sum {:y 100 :z 200})

(merge-with (fn [mf swt] [mf swt]) timepoint-max timepoint-sum)
;; => {:x 0, :y [1 100], :z 200}
Run Code Online (Sandbox Code Playgroud)

阅读merge-with的文档以了解它的作用:

返回一个映射,该映射由连接到第一个映射的其余映射组成。如果一个键出现在多个映射中,则后者(从左到右)的映射将通过调用 (f val-in-result val-in-latter) 与结果中的映射组合。

在上面的例子中,我们实际计算的结果与

{:x (:x timepoint-max)
 :y ((fn [mf swt] [mf swt]) (:y timepoint-max) (:y timepoint-sum))
 :z (:z timepoint-sum)}
;; => {:x 0, :y [1 100], :z 200}
Run Code Online (Sandbox Code Playgroud)

其中该函数(fn [mf swt] [mf swt])用于在唯一重叠的 key 处组合两个值:y。

完整的表达式(let [timepoints (merge-with (fn [mf swt] [mf swt]) timepoint-max timepoint-sum )])是一个let形式,它将值绑定到符号,但它不是很有用*exprs,因为它的部分是空的,所以它总是计算为nil:

(let [timepoints (merge-with (fn [mf swt] [mf swt]) timepoint-max timepoint-sum )])
;; => nil
Run Code Online (Sandbox Code Playgroud)

为了使其评估为其他内容,例如timepoints,必须将其修改为类似

(let [timepoints (merge-with (fn [mf swt] [mf swt]) timepoint-max timepoint-sum) ] 
  timepoints)
;; => {:x 0, :y [1 100], :z 200}
Run Code Online (Sandbox Code Playgroud)