【问题标题】:In clojure, why does assoc require arguments in addition to a map, but dissoc not?在 clojure 中,为什么 assoc 除了地图之外还需要参数,而 dissoc 不需要?
【发布时间】:2013-04-23 16:53:12
【问题描述】:

在clojure中,

(assoc {})

抛出一个arity异常,但是

(dissoc {})

没有。为什么?我本来希望他们俩都抛出异常,或者在没有提供键或值时都不会进行任何更改。

编辑:我看到了允许这些表格的理由;这意味着我们可以将 assoc 或 dissoc 应用于可能为空的参数列表。我只是不明白为什么一个会被允许而另一个不会,我很好奇我是否有充分的理由错过这一点。

【问题讨论】:

  • (assoc {}) 没有意义,因此是不允许的。
  • 请注意,(dissoc {}) 也不是。
  • 我的论点是要么两者都有意义,要么都没有意义;但一个是允许的,另一个是不允许的(至少在 clojure 1.5.1 上)。我很好奇为什么。

标签: clojure


【解决方案1】:

我个人认为缺少 1-arity assoc 是一个疏忽:每当需要一个尾随参数列表时 (& stuff),该函数通常应该能够使用零参数,以便可以 @ 987654322@它到一个空列表。

Clojure 有许多其他函数可以在零参数下正常工作,例如+merge

另一方面,Clojure 还有其他接受零尾随参数的函数,例如conj.

所以 Clojure API 在这方面有点不一致.....

【讨论】:

    【解决方案2】:

    这不是一个权威的答案,而是基于我的测试和查看 ClojureDocs:

    dissoc 的 arity 包括您能够传入一个参数,即地图。在这种情况下,不会从地图中删除任何键/值。

    (def test-map {:account-no 12345678 :lname "Jones" :fnam "Fred"})
    (dissoc test-map)
    {:account-no 12345678, :lname "Jones", :fnam "Fred"}
    

    assoc 没有类似的数量。那就是调用 assoc 需要一个映射、键和值。

    现在为什么这样设计是另一回事了,如果你没有收到关于该信息的答案——我希望你会——那么我建议提供赏金或继续 Clojure 的 Google 群组并提出这个问题.

    这里是源代码。

    (defn dissoc
      "dissoc[iate]. Returns a new map of the same (hashed/sorted) type,
    that does not contain a mapping for key(s)."
      {:added "1.0"
       :static true}
      ([map] map)
      ([map key]
       (. clojure.lang.RT (dissoc map key)))
      ([map key & ks]
       (let [ret (dissoc map key)]
         (if ks
           (recur ret (first ks) (next ks))
           ret))))
    

    【讨论】:

    • 我没有将此添加到我的答案中,因为这是一个有根据的猜测。似乎 one 的 arity 用于偏函数和 Thrush 运算符。那就是(dissoc test-map)可能会被串入一个最终包含删除键的表单中。但是,这是一个有根据的猜测,我希望知道 Clojure 知识的人会回答。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-21
    • 2012-09-02
    • 2010-09-07
    • 2018-03-18
    • 2016-01-10
    相关资源
    最近更新 更多