clojure 中的 dissoc 无法工作

dissoc in clojure can't get to work

我有这个功能:

(defn dissoc-all [m kv]
  (let [[k & ks] kv]
    (dissoc m k ks)))

其中 m 是映射,kv 是键向量。我是这样使用的:

(dissoc-all {:a 1 :b 2} [:a :b])

=>{:b 2}

这不是我所期望的。 ks:b 但我不知道为什么 dissoc 没有使用它。任何人都可以帮助我吗?

编辑: 添加的问题是,为什么这不触发 dissoc 的第三次重载,即 dissoc [map key & ks]?

如 noisesmith 所说,将名称从 dissoc-in 更改为 dissoc-all,-in 不是这个的正确名称,我同意。

这行不通,因为 ks 是第一个之后 kv 中所有元素的集合。所以不是 :b 而是 [:b].

相反,您可以只使用应用:

(defn dissoc-in [m vs]
  (apply dissoc m vs))

此外,dissoc-in 是这个函数的奇怪名称,因为名称中带有 -in 的标准函数都进行嵌套访问,而这不使用键进行任何嵌套访问地图的。

为什么不是这样的?

(defn dissoc-all [m ks]
  (apply dissoc m ks))

(dissoc-all {:a 1 :b 2} [:a :b])

=> {}

dissoc 的第三个覆盖没有被调用的原因是因为它不需要像 [:a :b] 这样的键集合 - 它只需要键。

例如:

(dissoc {:a "a" :b "b" :c "c" :d "d"} :a :b :c)

=> {:d "d"}

进一步

您被 dissoc 的 overloads/arities 弄糊涂了,它们的效果很简单:

[m & ks]

"Returns a new map of the same (hashed/sorted) type,
  that does not contain a mapping for any of ks. "

无键和一键的显式特性是为了性能。许多 clojure 函数都是这样组织的,文档遵循组织,而不是基本思想。

现在,

的动作
(dissoc-all {:a 1 :b 2} [:a :b])
;{:b 2}

是绑定

  • k:a
  • ks[:b]

注意后者。该示例删除了 :a,但未能删除不存在的 [:b]

可以用apply破解ks:

(defn dissoc-all [m kk]
  (let [[k & ks] kk]
    (apply dissoc m k ks)))

(dissoc-all {:a 1 :b 2} [:a :b])
;{}

... 或者,更好的做法是像@noisesmith 那样做,并立即使用 apply 短路解构。