我经常发现自己处于一种我真的不在乎我是否有矢量或 map 的情况:
[:foo :bar :baz :qux]
{0 :foo, 1 :bar, 2 :baz, 3 :qux}
重要的功能(
get
, assoc
等)适用于两者。一些,例如 dissoc
, 不要在向量上工作,但他们有充分的理由不这样做。但是,我就是不明白为什么
keys
和 vals
在 map 上工作,而不是在矢量上工作。有什么好的理由不实现它们(或者可能使用更优雅的多态解决方案)?(defn keys [m]
(if (vector? m)
(seq (range (count m)))
(clojure.lang.RT/keys m)))
(defn vals [m]
(if (vector? m)
(seq m)
(clojure.lang.RT/vals m)))
如果没有充分的理由,我该如何尝试在标准 Clojure 中实现它?
最佳答案
我认为这是一个有值(value)的有效想法。
应该使用哪些功能以及哪些应该是错误的问题很难划清界限。一方面,一种语言可能过于宽容(JavaScript?),以至于它会让你伤害自己。另一方面,它可能如此规范,以至于您没有强大的抽象构成(C?)。
在这种特殊情况下,我们正在权衡检测错误的能力,您正在编写需要 map 但传递向量的代码;反对能够编写更通用的代码的好处。就我个人而言,我喜欢它被视为错误,因为我有时确实将错误类型的集合传递给函数,并且更喜欢它爆炸而不是做某事。
我会觉得调用 keys
会让人感到困惑。在向量上,因为向量没有键,所以它是可索引的。对我来说,它们是不同的东西。因此,如果我编写调用 keys
的代码在向量上,这可能是一个错误。如果我真的想要一个与向量计数大小相同的范围,我会明确地写出来。如果我想要一个可以同时处理 map 和向量的函数,我会使用条件类型来选择键或范围计数。显然,这些只是我的偏好,但对我来说,它们是不想要 keys
的重要原因。在向量上工作。具体原因是我想检测错误。
但是,您希望它与向量一起使用是完全可以理解的,因为它们是按索引关联的。
至于应该dissoc
也可以工作,其他人可能会声称为什么不呢? (dissoc [1 2 3] 0) -> [2 3])
存在性能问题,因为您无法删除 O(1) 中的元素,如果 Clojure 采用 rbb-vector 则不是真的。 .有时当您必须执行该操作时非常方便。是something people need to do ,并且在 Clojure 中相当丑陋和不透明!我们都不希望这是一个功能,但我敢打赌它在某些情况下会非常优雅。但这并不是真正的技术限制,我们只是更喜欢这种方式。
Clojure 有一个开放的 contribution过程归结为:
在 Clojure Dev Google 小组中与其他人讨论您想做什么。他们可能能够提供意见和建议,从而带来更高质量的更改和更顺畅的提交过程。提交 CA 后,您可以通过 JIRA 提交补丁。
任何人都可以向 Clojure 提交错误或增强请求。
任何签署了贡献者协议(protocol)的人都可以提供补丁或改进票证。
安检员已被授予在流程的(某些)阶段移动票证的能力。
BDFL - Rich Hickey 是 Clojure 内容的创造者和仁慈的独裁者。 Stuart Halloway 也有特殊的访问权限,通常会向 Clojure 提交补丁。
如果您觉得这将是对 Clojure 的一个很好的更改,我建议您先在 Clojure 小组中讨论它以获得对该想法的一些支持,然后将其提交给 Clojure 开发小组。一般来说,当有诸如“这是一个展示值(value)的好用例”和“这是其他人想要相同值(value)主张的一些讨论”等支持性工件时,您的想法会得到最好的接受。
关于vector - 为什么键和值不能在向量上工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35341969/